Różnice między wybraną wersją a wersją aktualną.
| Both sides previous revision Poprzednia wersja Nowa wersja | Poprzednia wersja | ||
| sk2:cpp11_threads [2024/11/07 14:41] jkonczak | sk2:cpp11_threads [2024/11/07 23:21] (aktualna) jkonczak [[ekstra] Wątki w C++] | ||
|---|---|---|---|
| Linia 20: | Linia 20: | ||
| } | } | ||
| </code> | </code> | ||
| + | <html><div style="margin-top:-1.2em;margin-bottom:-1.2em"></div></html> | ||
| + | ++++ Odpowiednik kodu w C używający pthreads| | ||
| + | <html><div style="line-height:105%;margin-top:-3em"></div></html> | ||
| + | <code cpp threadHelloWorld.c> | ||
| + | #include <pthread.h> | ||
| + | #include <stdlib.h> | ||
| + | #include <stdio.h> | ||
| + | |||
| + | struct funkcja_argumenty{ | ||
| + | unsigned count; | ||
| + | const char * argument; | ||
| + | }; | ||
| + | |||
| + | void * funkcja(void * rawArgs){ | ||
| + | struct funkcja_argumenty *args = rawArgs; | ||
| + | while(args->count--) | ||
| + | printf("Hello %s\n", args->argument); | ||
| + | free(rawArgs); | ||
| + | /* kod wykonywany w drugim wątku */ | ||
| + | return NULL; | ||
| + | } | ||
| + | int main(void){ | ||
| + | pthread_t tid; | ||
| + | struct funkcja_argumenty *args = malloc(sizeof(struct funkcja_argumenty)); | ||
| + | args->count = 3; | ||
| + | args->argument = "world"; | ||
| + | pthread_create(&tid, NULL, funkcja, args); | ||
| + | /* kod wykonywany w pierwszym wątku */ | ||
| + | pthread_join(tid, NULL); | ||
| + | return 0; | ||
| + | } | ||
| + | </code> | ||
| + | ++++ | ||
| Podsumowanie tworzenia wątków: | Podsumowanie tworzenia wątków: | ||
| Linia 48: | Linia 81: | ||
| <small> | <small> | ||
| - | W C++ ustandaryzowano też zmienne lokalne dla wątku – w deklaracji zmiennej wystarczy dodać słowo kluczowe ''thread_local'', np: | + | W C+%%%%+ ustandaryzowano też zmienne lokalne dla wątku – w deklaracji zmiennej wystarczy dodać słowo kluczowe ''thread_local'', np: | 
| <html><div style="line-height:105%;margin-top:-1.2em"></div></html> | <html><div style="line-height:105%;margin-top:-1.2em"></div></html> | ||
| <code cpp> | <code cpp> | ||
| Linia 60: | Linia 93: | ||
| Przykład synchronizacji między wątkami (producent-konsument): | Przykład synchronizacji między wątkami (producent-konsument): | ||
| + | <html><div style="line-height:105%;margin-top:-1.2em"></div></html> | ||
| <code cpp condVarHelloWorld.cpp> | <code cpp condVarHelloWorld.cpp> | ||
| #include <condition_variable> | #include <condition_variable> | ||
| Linia 101: | Linia 135: | ||
| } | } | ||
| </code> | </code> | ||
| + | <html><div style="margin-top:-1.2em;margin-bottom:-1.2em"></div></html> | ||
| + | ++++ Odpowiednik kodu w C używający pthreads| | ||
| + | <html><div style="line-height:105%;margin-top:-3em"></div></html> | ||
| + | <code cpp condVarHelloWorld.c> | ||
| + | #include <pthread.h> | ||
| + | #include <stdio.h> | ||
| + | #include <stdlib.h> | ||
| + | #include <string.h> | ||
| + | |||
| + | struct dumbQueue *msgQueue; | ||
| + | |||
| + | struct dumbQueue* dumbQueue_create (void); | ||
| + | void dumbQueue_push  (struct dumbQueue *q, void *element); | ||
| + | void* dumbQueue_pop  (struct dumbQueue *q); | ||
| + | int  dumbQueue_isEmpty(struct dumbQueue *q); | ||
| + | |||
| + | pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; | ||
| + | pthread_cond_t  cv = PTHREAD_COND_INITIALIZER; | ||
| + | |||
| + | _Thread_local char *msg; | ||
| + | |||
| + | void producer(void) { | ||
| + | while (1) { | ||
| + | msg = malloc(255); | ||
| + | scanf("%*[\n]"); | ||
| + | scanf("%254[^\n]", msg); | ||
| + | { | ||
| + | pthread_mutex_lock(&mtx); | ||
| + | dumbQueue_push(msgQueue, msg); | ||
| + | pthread_cond_signal(&cv); | ||
| + | pthread_mutex_unlock(&mtx); | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | void *consumer(void *_) { | ||
| + | while (1) { | ||
| + | { | ||
| + | pthread_mutex_lock(&mtx); | ||
| + | while (dumbQueue_isEmpty(msgQueue)) | ||
| + | pthread_cond_wait(&cv, &mtx); | ||
| + | msg = dumbQueue_pop(msgQueue); | ||
| + | pthread_mutex_unlock(&mtx); | ||
| + | } | ||
| + | printf("%s\n", msg); | ||
| + | free(msg); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | int main(void) { | ||
| + | msgQueue = dumbQueue_create(); | ||
| + | pthread_t tid; | ||
| + | pthread_create(&tid, NULL, consumer, NULL); | ||
| + | producer(); | ||
| + | } | ||
| + | |||
| + | /*****/  struct dumbQueue { | ||
| + | /* T */ struct dumbQueue_e { | ||
| + | /* h */ void *element; | ||
| + | /* i */ struct dumbQueue_e *next; | ||
| + | /* s */ } *head, *tail; | ||
| + | /* */  }; | ||
| + | /* i */  | ||
| + | /* s */ struct dumbQueue *dumbQueue_create(void) { | ||
| + | /* */  struct dumbQueue *q = malloc(sizeof(struct dumbQueue)); | ||
| + | /* j */ q->head = malloc(sizeof(struct dumbQueue_e)); | ||
| + | /* u */ q->head->next = NULL; | ||
| + | /* s */ q->tail = q->head; | ||
| + | /* t */ return q; | ||
| + | /* */  } | ||
| + | /* a */  | ||
| + | /* */  void dumbQueue_push(struct dumbQueue *q, void *element) { | ||
| + | /* d */ q->tail->next = malloc(sizeof(struct dumbQueue_e)); | ||
| + | /* u */ q->tail = q->tail->next; | ||
| + | /* m */ q->tail->next = NULL; | ||
| + | /* b */ q->tail->element = element; | ||
| + | /* */  } | ||
| + | /* q */  | ||
| + | /* u */ void *dumbQueue_pop(struct dumbQueue *q) { | ||
| + | /* e */ struct dumbQueue_e *next = q->head->next; | ||
| + | /* u */ free(q->head); | ||
| + | /* e */ q->head = next; | ||
| + | /* */  return q->head->element; | ||
| + | /* i */ } | ||
| + | /* m */  | ||
| + | /* p */ int dumbQueue_isEmpty(struct dumbQueue *q) { | ||
| + | /* l */ return q->head->next == NULL; | ||
| + | /*****/  } | ||
| + | </code> | ||
| + | ++++ | ||
| ===== [ekstra] <functional> w C++ ===== | ===== [ekstra] <functional> w C++ ===== | ||