поток параллелизма newb ie здесь. Итак, у меня есть проблема, когда мой encrypt_thread иногда зависает, и я почти уверен, что это из-за того, как я использовал свои семафоры.
Что делает моя программа :
read_from_file - это поток, который читает символы из файла в input_buffer по одному символу за раз. Каждый раз, когда это происходит, он уменьшает empty_in_input_buffer на 1 и увеличивает full_in_input_buffer на 1. Если empty_in_input равен 0, он ожидает сообщения (& empty_in_input_buffer) из потока Encrypt.
Поток шифрования ожидает сообщения (& full_in_input_buffer) из потока Read, чтобы начать шифрование символа. Затем он вызывает post (& empty_in_input_buffer) и затем wait (& empty_in_output_buffer) . Как только он помещает зашифрованный символ в output_buffer, он вызывает post (& empty_in_output_buffer) . Encrypt - это «посредник», ожидающий размещения нового символа в input_buffer и освобождения нового слота в output_buffer.
Запись потоковых вызовов wait ( & full_in_output_buffer) чтобы затем возобновить выполнение и записать символ в output_buffer в файл. После этого он вызывает post (& empty_in_output_buffer) .
Я хочу достичь максимального параллелизма, чтобы, если read_from_file поместил новый символ в слот 5 input_buffer, затем encrypt может по-прежнему обращаться к слотам 3 и 4 для шифрования и записи в output_buffer. Я не использовал мьютекс для блокировки input_buffer, так как элементы в буфере не изменяются, только читаются, шифруются и помещаются в output_buffer, но я могу ошибаться, полагая, что он мне не нужен.
Программа также запрашивает у пользователя buffer_size в самом начале. Дело в том, что моя программа зависает половину времени, и она отлично работает в другой половине, что указывает на то, что у меня есть состояние гонки, которое я не учитываю. Тем не менее, я не смог понять, где это происходит.
Редактировать: fill_letter_arr просто создает массив символов алфавита в верхнем и нижнем регистре букв. is_in_letters просто проверяет, является ли символ буквой алфавита. Мое шифрование очень простое и шифрует только письма.
Основная нить:
int main(int argc, char *argv[]){
//sem_init(&encrypt_signals_read, 0, 1);
int buf_size;
file_in = fopen(argv[1], "r");
file_out = fopen(argv[2], "w");
take_input(&buf_size);
struct thread_args args = {
malloc(sizeof(char)*buf_size),
malloc(sizeof(char)*buf_size),
buf_size,
0,
};
sem_init(&empty_in_input,0,buf_size);
sem_init(&empty_in_output,0,buf_size);
sem_init(&full_in_input_buffer,0,0);
sem_init(&full_in_output_buffer,0,0);
//creating threads
pthread_t read_thread,encrypt_thread,write_thread;
if(pthread_create(&read_thread,NULL,read_from_file,&args) != 0){
printf("Error creating read thread!");
}
if(pthread_create(&encrypt_thread,NULL,encrypt,&args) != 0){
printf("Error creating encrypt thread!");
}
if(pthread_create(&write_thread,NULL,write_to_file,&args) != 0){
printf("Error creating write thread!");
}
pthread_join(read_thread,NULL);
pthread_join(encrypt_thread,NULL);
pthread_join(write_thread,NULL);
fclose(file_in);
fclose(file_out);
}
Чтение нити:
void* read_from_file(void* args){
struct thread_args* shared = (struct thread_args*) args;
char c = '0';
int i = 0;
int val,val1,val2,val3;
if (file_in != NULL){
do{
c = fgetc(file_in);
if(i >= shared->buffer_size)
i = 0;
sem_wait(&empty_in_input);
shared->input_buffer[i] = c;
sem_post(&full_in_input_buffer);
i++;
}while(c != EOF);
}
if (ferror(file_in) != 0 ) {
fputs("Error reading file", stderr);
exit(1);
}
}
Шифрование нити:
void* encrypt(void* args){
struct thread_args* shared = (struct thread_args*) args;
int s = 1;
int i = 0;
char c = '0';
int val,val1,val2,val3,val4;
fill_letters_arr(0);
do{
if(i >= shared->buffer_size)
i = 0;
sem_wait(&full_in_input_buffer);
c = shared->input_buffer[i];
sem_post(&empty_in_input);
if(is_in_letters(&c) == true){
encrypt_letter(&s,&c);
}
sem_wait(&empty_in_output);
shared->output_buffer[i] = c;
sem_post(&full_in_output_buffer);
i++;
}while(c != EOF);
}
Писание нити:
void* write_to_file(void* args){
struct thread_args* shared = (struct thread_args*) args;
char c = '0';
int i = 0;
int val,val1,val2,val3;
if (file_out != NULL){
while(c != EOF){
if(i >= shared->buffer_size)
i = 0;
sem_wait(&full_in_output_buffer);
c = shared->output_buffer[i];
fputc(c,file_out);
sem_post(&empty_in_output);
i++;
}
}
if (ferror(file_in) != 0 ) {
fputs("Error reading file", stderr);
}
}