-
Notifications
You must be signed in to change notification settings - Fork 11
BDZ_3 Parallel programming #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include <time.h> | ||
|
|
||
| #include "MyList.h" | ||
| #define SIZE 10 // максимальный размер двоичного числа | ||
|
|
||
|
|
||
| // Функция для инициализации списка | ||
| void initList(DoublyLinkedList* list) { | ||
| list->head = NULL; | ||
| list->tail = NULL; | ||
| list->size = 0; | ||
| } | ||
|
|
||
|
|
||
| // Функция выделения памяти под новый узел | ||
| Node* createNode(int value) { | ||
| Node* newNode = (Node*)malloc(sizeof(Node)); | ||
| if (newNode == NULL) { | ||
| printf("Memory allocation error!\n"); | ||
| exit(1); // аварийное завершение | ||
| } | ||
| newNode->data = value; | ||
| newNode->prev = NULL; | ||
| newNode->next = NULL; | ||
| return newNode; | ||
| } | ||
|
|
||
| // Функция добавления элемента в конец списка | ||
| void append(DoublyLinkedList* list, int value) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. А если передать указатель, который |
||
| Node* newElement = createNode(value); | ||
| if (list -> head == NULL){ // если список пустой | ||
| newElement -> prev = NULL; | ||
| list -> head = newElement; | ||
| } | ||
| else { // уже не пустой | ||
| newElement -> prev = list -> tail; // связь текущего с предыдущим | ||
| list -> tail -> next = newElement; // связь предыдущего с текущим | ||
| } | ||
| list -> tail = newElement; // переопределение конца(указателя) на новый элемент | ||
| ++(list -> size); // увеличение списка | ||
| } | ||
|
|
||
| // Функция освобождения памяти | ||
| void freeList(DoublyLinkedList* list) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. также с |
||
| Node* current = list->head; | ||
| while (current != NULL) { | ||
| Node* temp = current; | ||
| current = current->next; // освобождаем память, запоминая указатель на следующий элемент | ||
| free(temp); | ||
| } | ||
| list->head = NULL; // уничтожаем указатели непосредственно списка | ||
| list->tail = NULL; | ||
| list->size = 0; | ||
| } | ||
|
|
||
| // Функция вывода списка от начала к концу | ||
| void printForward(const DoublyLinkedList* list){ | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Также с |
||
| Node* current = list -> head; | ||
| printf("Dec list: "); | ||
| while(current != NULL){ | ||
| printf("%d ", current -> data); | ||
| current = current -> next; | ||
| } | ||
| printf("\n"); | ||
| } | ||
|
|
||
| // Функция вывода списка от конца к началу | ||
| void printBackward(const DoublyLinkedList* list){ | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Также с |
||
| Node* current = list -> tail; | ||
| printf("Dec list: "); | ||
| while(current != NULL){ | ||
| printf("%d ", current -> data); | ||
| current = current -> prev; | ||
| } | ||
| printf("\n"); | ||
| } | ||
|
|
||
| void generateRandomList(DoublyLinkedList* list, int count){ | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Также с
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. У тебя |
||
| // Инициализация генератора случайных чисел | ||
| srand(time(NULL)); | ||
| for (int i = 0; i < count; ++i){ | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. такая же проблема с codestyle |
||
| append(list, rand() % 100); | ||
| } | ||
| } | ||
|
|
||
| // Функция для вывода списка в двоичном виде | ||
| void printBinaryValue(const DoublyLinkedList* list) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Также с |
||
| printf("Binary list: "); | ||
| Node* current = list -> head; | ||
| int numberDec; | ||
| int count = -1; | ||
| while(current != NULL){ | ||
| numberDec = current -> data; | ||
| int* numberBin = (int*)calloc(SIZE, sizeof(int)); | ||
| if (numberBin == NULL){ | ||
| printf("Memory allocation error!\n"); | ||
| exit(1); | ||
| } | ||
| //printf("%d ", numberDex); | ||
| numberBin[++count] = numberDec % 2; | ||
| while (numberDec != 0){ | ||
| numberDec /= 2; | ||
| numberBin[++count] = numberDec % 2; // добываем 0 и 1 из числа | ||
| } | ||
|
|
||
|
|
||
| // разворачиваем двоичное число | ||
| for (int i = 0; i < count / 2; ++i){ | ||
| int bubble = numberBin[i]; | ||
| numberBin[i] = numberBin[count - 1 - i]; // обмен крайних элементов, двигаемся к середине | ||
| numberBin[count - 1 - i] = bubble; | ||
| } | ||
| // вывод в консоль | ||
| for (int i = 0;i < count; ++i){ | ||
| printf("%d",numberBin[i]); | ||
| } | ||
| printf(" "); // пробел между двоичными числами | ||
| free(numberBin); // освобождаем память | ||
| numberBin = NULL; | ||
| numberDec = 0; | ||
| count = -1; | ||
| current = current -> next; | ||
| } | ||
| printf("\n"); | ||
| } | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. потерял |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| #ifndef MYLIST_H | ||
| #define MYLIST_H | ||
|
|
||
| /* Концепция двухсвязного спиcка | ||
|
|
||
| NULL <- [prev0 data0 next0] <-> [prev1 data1 next1] <-> [prev2 data2 next2] -> NULL | ||
|
|
||
| Node0(head) Node1 Node2(tail) | ||
|
|
||
|
|
||
| next0 = &Node1 | ||
| next1 = &Node2 | ||
| next2 = NULL | ||
|
|
||
| prev0 = NULL | ||
| prev1 = &Node0 | ||
| prev2 = &Node1 | ||
|
|
||
| */ | ||
|
|
||
| // Cтруктура узла двухсвязного списка (один элемент списка) | ||
| typedef struct Node { | ||
| int data; | ||
| struct Node* prev; // указатель на прерыдущий элемент | ||
| struct Node* next; // указатель на следующий элемент | ||
| } Node; | ||
|
|
||
| // Структура самого списка | ||
| typedef struct { | ||
| Node* head; // указатель на первый элемент | ||
| Node* tail; // указатель на последний элемент | ||
| int size; // счетчик элементов списка | ||
| } DoublyLinkedList; | ||
|
|
||
|
|
||
| void initList(DoublyLinkedList* list); | ||
| Node* createNode(int value); | ||
| void append(DoublyLinkedList* list, int value); | ||
| void freeList(DoublyLinkedList* list); | ||
|
|
||
| void printForward(const DoublyLinkedList* list); | ||
| void printBackward(const DoublyLinkedList* list); | ||
|
|
||
| void generateRandomList(DoublyLinkedList* list, int count); | ||
|
|
||
| void printBinaryValue(const DoublyLinkedList* list); | ||
|
|
||
|
|
||
| #endif // MYLIST_H | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. потерял \n |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| #include <pthread.h> | ||
| #include <stdio.h> | ||
| #include "MyThreads.h" | ||
|
|
||
| // Функция для посчета нулевых битов в числе | ||
| int countZeroBits(int numberDec){ | ||
| int count = 0; | ||
| while(numberDec != 0){ | ||
| if (numberDec % 2 == 0){ | ||
| ++count; | ||
| } | ||
| numberDec /= 2; | ||
| } | ||
| return count; | ||
| } | ||
|
|
||
| // Функция для подсчета единичных битов в числе | ||
| int countOneBits(int numberDec){ | ||
| int count = 0; | ||
| while(numberDec != 0){ | ||
| if (numberDec % 2 == 1){ | ||
| ++count; | ||
| } | ||
| numberDec /= 2; | ||
| } | ||
| return count; | ||
| } | ||
| // Функция инициализации и запуска потоков | ||
| void threadStart(ThreadArgs* args1, ThreadArgs* args2){ | ||
| // Создание потоков | ||
| pthread_t thread1; | ||
| pthread_t thread2; | ||
|
|
||
| if (pthread_create(&thread1, NULL, threadExecution, args1) != 0) { | ||
| printf("Failed to create thread 1"); | ||
| exit(1); // аварийное завершение | ||
| } | ||
| if (pthread_create(&thread2, NULL, threadExecution, args2) != 0) { | ||
| printf("Failed to create thread 2"); | ||
| exit(1); // аварийное завершение | ||
| } | ||
| /* разбор функции pthread_create | ||
| &thread1 - Указатель на переменную типа pthread_t, в которую будет записан идентификатор созданного потока | ||
| NULL - Указатель на атрибуты потока (используем атрибуты по умолчанию) | ||
| threadExecution - Функция обработки данных в потоке | ||
| &args1 - Указатель на аргументы, которые будут переданы в функцию threadExecution | ||
| */ | ||
|
|
||
| // Ожидание завершения потоков | ||
| pthread_join(thread1, NULL); | ||
| pthread_join(thread2, NULL); | ||
| } | ||
|
|
||
| // функция выполнения обработки данных в потоке | ||
| void* threadExecution(void* args) { | ||
| ThreadArgs* targs = (ThreadArgs*)args; // преобразуем принятые аргументы в структуру | ||
|
|
||
| Node* currentNode = NULL; // объявляем текущий узел | ||
| Node* nextNode = NULL; // и следующий | ||
|
|
||
| currentNode = targs -> flag ? targs -> head : targs -> tail; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Пиши доступ к указателю без пробелов |
||
|
|
||
| while (1) { | ||
|
|
||
| // блокируем список на время чтения узла | ||
| pthread_mutex_lock(targs -> listMutex); | ||
|
|
||
| // разблокировка, если конец списка | ||
| if (currentNode == NULL) { | ||
| pthread_mutex_unlock(targs -> listMutex); | ||
| break; | ||
| } | ||
|
|
||
| // Сохраняем данные и следующий узел локально | ||
| int data = currentNode -> data; | ||
| nextNode = targs -> flag ? currentNode -> next : currentNode -> prev; | ||
|
|
||
| // теперь разблокируем список (чтение завершено) | ||
| pthread_mutex_unlock(targs -> listMutex); | ||
|
|
||
| // Обработка данных | ||
| if (targs -> flag) { | ||
| targs -> countZero += countZeroBits(data); | ||
| } else { | ||
| targs -> countOne += countOneBits(data); | ||
| } | ||
| ++(targs -> countNodes); | ||
| currentNode = nextNode; | ||
| } | ||
| targs = NULL; | ||
| return NULL; | ||
| } | ||
|
|
||
| // функция для вывода результата в консоль | ||
| void threadPrint(ThreadArgs* args1, ThreadArgs* args2){ | ||
| printf("\n"); | ||
| printf("Thread 1:\n"); | ||
| printf("Zero bits: %d\n", args1 -> countZero); | ||
| printf("Count nodes: %d\n", args1 -> countNodes); | ||
| printf("\n"); | ||
| printf("Thread 2:\n"); | ||
| printf("One bits: %d\n", args2 -> countOne); | ||
| printf("Count nodes: %d\n", args2 -> countNodes); | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| #ifndef MYTHREADS_H | ||
| #define MYTHREADS_H | ||
| #include "MyList.h" | ||
|
|
||
| // Структура аргументов для работы с потоком | ||
| typedef struct { | ||
| Node* head; // Указатель на голову списка | ||
| Node* tail; // Указатель на хвост списка | ||
| int countZero; // Счетчик нулевых битов (для потока 1) | ||
| int countOne; // Счетчик единичных битов (для потока 2) | ||
| int countNodes; // Счетчик обработанных элементов | ||
| int flag; // Флаг направления обхода (1 - от головы, 0 - от хвоста) | ||
| pthread_mutex_t* listMutex; // Мьютекс для синхронизации доступа к списку | ||
| } ThreadArgs; | ||
|
|
||
| int countZeroBits(int numberDec); | ||
| int countOneBits(int numberDec); | ||
| void threadStart(ThreadArgs* args1, ThreadArgs* args2); | ||
| void* threadExecution(void* args); | ||
| void threadPrint(ThreadArgs* args1, ThreadArgs* args2); | ||
|
|
||
| #endif //MYTHREADS_H | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. потерял |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| #include "delay.h" | ||
|
|
||
| #ifdef _WIN32 | ||
| #include <windows.h> | ||
| #else | ||
| #include <unistd.h> | ||
| #endif | ||
|
|
||
| // функция для задержки консоли в Linux или Windows | ||
| void delay_ms(int milliseconds) { | ||
| #ifdef _WIN32 | ||
| Sleep(milliseconds); | ||
| #else | ||
| usleep(milliseconds * 1000); | ||
| #endif | ||
| } | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. потерял |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| #ifndef DELAY_H | ||
| #define DELAY_H | ||
|
|
||
|
|
||
| void delay_ms(int milliseconds); | ||
|
|
||
| #endif // DELAY_H | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. потерял |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| #include <stdio.h> | ||
| #include <pthread.h> | ||
| #include "MyList.h" | ||
| #include "delay.h" | ||
| #include "MyThreads.h" | ||
|
|
||
|
|
||
| int main() { | ||
| // Подготовка данных | ||
| int sizeList = 0; | ||
| printf("Enter a number of type int: "); | ||
| scanf("%d", &sizeList); | ||
| printf("\n"); | ||
| DoublyLinkedList MyList; | ||
| initList(&MyList); | ||
| generateRandomList(&MyList, sizeList); | ||
|
|
||
| // Смотрим на подготовленные данные | ||
| printForward(&MyList); // десятичный вид | ||
| printBinaryValue(&MyList); // двоичный вид | ||
|
|
||
| // Многопоточность | ||
|
|
||
| // Инициализация мьютекса | ||
| pthread_mutex_t listMutex = PTHREAD_MUTEX_INITIALIZER; | ||
| /* | ||
| Мьютексы нужны для защиты от одновременного | ||
| доступа сразу нескольких потоков к одному | ||
| обЪекту. Их необходимо использовать, если | ||
| предполагается, что список будет не просто | ||
| считываться, а изменяться в разных потоках. | ||
|
|
||
| */ | ||
|
|
||
| // Подготовка аргументов для потоков (инициализация структур) | ||
| ThreadArgs args1 = {MyList.head, MyList.tail, 0, 0, 0, 1, &listMutex}; // Поток 1 (от головы) | ||
| ThreadArgs args2 = {MyList.head, MyList.tail, 0, 0, 0, 0, &listMutex}; // Поток 2 (от хвоста) | ||
|
|
||
| // Запуск многопоточной обработки | ||
| threadStart(&args1, &args2); | ||
|
|
||
| // Вывод результатов | ||
| threadPrint(&args1, &args2); | ||
|
|
||
| delay_ms(5000); // задержка отображения в консоли (Linux|Windows) | ||
| pthread_mutex_destroy(&listMutex); // Уничтожение мьютекса | ||
| freeList(&MyList); // освобождение памяти | ||
| return 0; | ||
| } | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. потерял |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Не пойму что значит
1. Введи типы ошибок и их условные обозначения.Что-то на подобие этого и обрабатывай разные виды ошибок. Как минимум с сложном коде по названию будет понятно что за тип ошибки, если не до конца ясно логике в коде