User Tools

Site Tools


os_cp:threads

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
os_cp:threads [2024/04/18 11:32]
jkonczak [Accessing the same data from multiple threads]
os_cp:threads [2025/04/25 13:55] (current)
jkonczak [POSIX condition variables]
Line 69: Line 69:
 \\ \\
 <​html><​span style="​float:​right"><​small>​Needs header:<​br><​code>​pthread.h</​code></​small></​span>​ <​html><​span style="​float:​right"><​small>​Needs header:<​br><​code>​pthread.h</​code></​small></​span>​
-<a href="​https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_create.html"></​html>​+<a href="​https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_create.html"></​html>​
 ''​int **pthread_create**(pthread_t *restrict //​threadIdentifier//,'' ​ \\ ''​int **pthread_create**(pthread_t *restrict //​threadIdentifier//,'' ​ \\
 ''​                   const pthread_attr_t *restrict //​attr//,'' ​ \\ ''​                   const pthread_attr_t *restrict //​attr//,'' ​ \\
Line 132: Line 132:
 \\ \\
 <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​ <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​
-<a href="​https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_join.html"></​html>​+<a href="​https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_join.html"></​html>​
 ''​int **pthread_join**(pthread_t //thread//, void %%**%%//​value_ptr//​);''​ ''​int **pthread_join**(pthread_t //thread//, void %%**%%//​value_ptr//​);''​
 <​html></​a></​html>​ <​html></​a></​html>​
Line 209: Line 209:
 \\ \\
 <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​ <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​
-<a href="​https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_detach.html"></​html>​+<a href="​https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_detach.html"></​html>​
 ''​int **pthread_detach**(pthread_t //​thread//​);''​ ''​int **pthread_detach**(pthread_t //​thread//​);''​
 <​html></​a></​html>​ <​html></​a></​html>​
Line 275: Line 275:
 POSIX offers a mechanism called //​cancellation//​. That is, one can send to a POSIX offers a mechanism called //​cancellation//​. That is, one can send to a
 thread a cancellation request using the thread a cancellation request using the
-''​[[https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_cancel.html|pthread_cancel]]''​+''​[[https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_cancel.html|pthread_cancel]]''​
 function. Each thread can select is behaviour on receiving such request using the function. Each thread can select is behaviour on receiving such request using the
-''​[[https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_setcancelstate.html|pthread_setcancelstate]]''​+''​[[https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_setcancelstate.html|pthread_setcancelstate]]''​
 and and
-''​[[https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_setcancelstate.html|pthread_setcanceltype]]''​+''​[[https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_setcancelstate.html|pthread_setcanceltype]]''​
 functions. One may either allow or disallow cancalling a thread, and one may functions. One may either allow or disallow cancalling a thread, and one may
 choose whether the cancallation should ouccur immediatly after a request, or choose whether the cancallation should ouccur immediatly after a request, or
 at the next cancallation point. Cancellation points are the execution points at the next cancallation point. Cancellation points are the execution points
 of several pthread functions, among which notably ​ of several pthread functions, among which notably ​
-''​[[https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_setcancelstate.html|pthread_testcancel]]''​+''​[[https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_setcancelstate.html|pthread_testcancel]]''​
 is there just to this end. is there just to this end.
 Once the thread complies to the cancellation request, it roughly does the same Once the thread complies to the cancellation request, it roughly does the same
Line 374: Line 374:
 } }
 </​code>​ </​code>​
 +<​html></​div></​html>​
 +<​html><​div style="​margin-top:​-1.4em;​ line-height:​ 1em"></​html>​
 +<​small>​If the code above always returns the right answer, try to run it a million times: \\
 +''​for X in `seq 1000000`; do RES=$(%%./​%%//​progname//​);​ test "​$RES"​ -ne 16000 && echo -e "​\n$RES"​ && break || echo -n '​.';​ done''​
 +</​small>​
 <​html></​div></​html>​ <​html></​div></​html>​
  
Line 396: Line 401:
 \\ \\
 <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​ <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​
-<a href="​https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_mutex_init.html"></​html>​+<a href="​https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_mutex_init.html"></​html>​
 ''​pthread_mutex_t //mutex// = **PTHREAD_MUTEX_INITIALIZER**;''​ ''​pthread_mutex_t //mutex// = **PTHREAD_MUTEX_INITIALIZER**;''​
 <​html></​a></​html>​ <​html></​a></​html>​
Line 403: Line 408:
 \\ \\
 <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​ <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​
-<a href="​https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_mutex_init.html"></​html>​+<a href="​https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_mutex_init.html"></​html>​
 ''​int **pthread_mutex_init**(pthread_mutex_t *restrict //​mutex//,''​ \\ ''​int **pthread_mutex_init**(pthread_mutex_t *restrict //​mutex//,''​ \\
 ''​                       const pthread_mutexattr_t *restrict //​attr//​)''​ ''​                       const pthread_mutexattr_t *restrict //​attr//​)''​
Line 415: Line 420:
 \\ \\
 <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​ <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​
-<a href="​https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_mutexattr_init.html"></​html>​+<a href="​https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_mutexattr_init.html"></​html>​
 ''​int **pthread_mutexattr_init**(pthread_mutexattr_t *//​attr//​)''​ ''​int **pthread_mutexattr_init**(pthread_mutexattr_t *//​attr//​)''​
 <​html></​a></​html>​ <​html></​a></​html>​
 \\ \\
 and finally set the attributes using corresponding functions: and finally set the attributes using corresponding functions:
-  * <​html><​a href="​https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_mutexattr_settype.html"></​html>​ ''​int pthread_mutexattr_set**type**(pthread_mutexattr_t *//attr//, int //​type//​)''<​html></​a></​html>​ sets mutex type (see below),  +  * <​html><​a href="​https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_mutexattr_settype.html"></​html>​ ''​int pthread_mutexattr_set**type**(pthread_mutexattr_t *//attr//, int //​type//​)''<​html></​a></​html>​ sets mutex type (see below),  
-  * <​small><​html><​a href="​https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_mutexattr_setpshared.html"></​html>''​int pthread_mutexattr_set**pshared**(pthread_mutexattr_t *//attr//, int //​pshared//​)''<​html></​a></​html>​ allows sharing mutexes between processes (they need to reside in shared memory), </​small>​ +  * <​small><​html><​a href="​https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_mutexattr_setpshared.html"></​html>''​int pthread_mutexattr_set**pshared**(pthread_mutexattr_t *//attr//, int //​pshared//​)''<​html></​a></​html>​ allows sharing mutexes between processes (they need to reside in shared memory), </​small>​ 
-  * <​small><​html><​a href="​https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_mutexattr_setrobust.html"></​html>''​int pthread_mutexattr_set**robust**(pthread_mutexattr_t *//attr//, int //​robust//​)''<​html></​a></​html>​ when a thread holding a mutex terminated, a robust mutex will return appropriate error instead of waiting,</​small>​ +  * <​small><​html><​a href="​https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_mutexattr_setrobust.html"></​html>''​int pthread_mutexattr_set**robust**(pthread_mutexattr_t *//attr//, int //​robust//​)''<​html></​a></​html>​ when a thread holding a mutex terminated, a robust mutex will return appropriate error instead of waiting,</​small>​ 
-  * <​small>''​[[https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_mutexattr_setprotocol.html|pthread_mutexattr_setprotocol]]''​ and ''​[[https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_mutexattr_setprioceiling.html|setprioceiling]]''​ deal with priorities.</​small>​+  * <​small>''​[[https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_mutexattr_setprotocol.html|pthread_mutexattr_setprotocol]]''​ and ''​[[https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_mutexattr_setprioceiling.html|setprioceiling]]''​ deal with priorities.</​small>​
  
 The mutex type impacts what happens when a mutex that is already locked is The mutex type impacts what happens when a mutex that is already locked is
Line 447: Line 452:
 \\ \\
 <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​ <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​
-<a href="​https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_mutex_lock.html"></​html>​+<a href="​https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_mutex_lock.html"></​html>​
 ''​int **pthread_mutex_lock**(pthread_mutex_t *//​mutex//​)''​ \\ ''​int **pthread_mutex_lock**(pthread_mutex_t *//​mutex//​)''​ \\
 ''​int pthread_mutex_trylock(pthread_mutex_t *//​mutex//​)''​ ''​int pthread_mutex_trylock(pthread_mutex_t *//​mutex//​)''​
 <​html></​a></​html>​ <​html></​a></​html>​
 \\ \\
-<​small><​html><​a href="​https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_mutex_timedlock.html"></​html>​+<​small><​html><​a href="​https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_mutex_timedlock.html"></​html>​
 ''​int pthread_mutex_timedlock(pthread_mutex_t *restrict //mutex//, const struct timespec *restrict //​abstime//​)''​ ''​int pthread_mutex_timedlock(pthread_mutex_t *restrict //mutex//, const struct timespec *restrict //​abstime//​)''​
 <​html></​a></​html></​small>​ <​html></​a></​html></​small>​
Line 467: Line 472:
 \\ \\
 <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​ <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​
-<a href="​https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_mutex_lock.html"></​html>​+<a href="​https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_mutex_lock.html"></​html>​
 ''​int **pthread_mutex_unlock**(pthread_mutex_t *//​mutex//​)''​ ''​int **pthread_mutex_unlock**(pthread_mutex_t *//​mutex//​)''​
 <​html></​a></​html>​ <​html></​a></​html>​
Line 613: Line 618:
 \\ \\
 To create a rwlock one has to create a ''​pthread_rwlock_t''​ variable and initialize To create a rwlock one has to create a ''​pthread_rwlock_t''​ variable and initialize
-it with either ''​[[https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_rwlock_init.html|PTHREAD_RWLOCK_INITIALIZER]]''​ macro or ''​[[https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_rwlock_init.html|pthread_rwlock_init]]''​ function.+it with either ''​[[https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_rwlock_init.html|PTHREAD_RWLOCK_INITIALIZER]]''​ macro or ''​[[https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_rwlock_init.html|pthread_rwlock_init]]''​ function.
 \\ \\
 A read-write lock can be locked with: A read-write lock can be locked with:
-  * ''​[[https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_rwlock_rdlock.html|pthread_rwlock_rdlock]]''​ and ''​[[https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_rwlock_rdlock.html|pthread_rwlock_tryrdlock]]''​ in shared (read) mode, +  * ''​[[https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_rwlock_rdlock.html|pthread_rwlock_rdlock]]''​ and ''​[[https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_rwlock_rdlock.html|pthread_rwlock_tryrdlock]]''​ in shared (read) mode, 
-  * ''​[[https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_rwlock_wrlock.html|pthread_rwlock_wrlock]]''​ and ''​[[https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_rwlock_wrlock.html|pthread_rwlock_trywrlock]]''​ in exclusive (write) mode.+  * ''​[[https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_rwlock_wrlock.html|pthread_rwlock_wrlock]]''​ and ''​[[https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_rwlock_wrlock.html|pthread_rwlock_trywrlock]]''​ in exclusive (write) mode.
 <​small>''​pthread_rwlock_timedrdlock''​ / ''​pthread_rwlock_timedwrlock''​ variants are also available.</​small>​ <​small>''​pthread_rwlock_timedrdlock''​ / ''​pthread_rwlock_timedwrlock''​ variants are also available.</​small>​
 \\ \\
-To unlock a rwlock (locked in any mode), ''​[[https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_rwlock_unlock.html|pthread_rwlock_unlock]]''​ is used.+To unlock a rwlock (locked in any mode), ''​[[https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_rwlock_unlock.html|pthread_rwlock_unlock]]''​ is used.
  
  
Line 699: Line 704:
 ===== Critical sections, deadlocks ===== ===== Critical sections, deadlocks =====
  
-~~Exercise.#​~~ Which lines of code are the critical section ​in the code below?+~~Exercise.#​~~ ​Download and read through the {{os_cp:​threads:​another_bad_idea.c}} file. Which lines of code are the critical section? \\ <​small>​The vital parts of the file is presented ​below.</​small>​
  
-~~Exercise.#​~~ Spot the deadlock scenario in the code below.+~~Exercise.#​~~ Spot the deadlock scenario in the code from the previous exercise.
  
 ~~Exercise.#​~~ Fix the code so that it no longer is able to deadlock. ~~Exercise.#​~~ Fix the code so that it no longer is able to deadlock.
  
-<​html><​div style="​line-height:​1.2em"></​html+<​html><​div style="​line-height:​1em"></​html>​ 
-<small+<code c> 
-<​code ​c another_bad_idea.c> +  … 
-#include <​pthread.h>​ +10│ struct myIO {FILE *in; FILE *out;}; 
-#include <​stdint.h>​ +11│ void* threadFunc(void *num); 
-#include <​stdio.h>​ +  … 
-#include <​stdlib.h>​ +17│ struct { 
-#include <​string.h>​ +18│   pthread_mutex_t mtx; 
- +19│   char text[256];​ 
-struct { +20│ } item[5]; 
-  pthread_mutex_t mtx; +21│ 
-  char text[256];​ +22│ int main(int argc, char **argv) { 
-} item[5]; +  … 
- +28│   ​for ​(intptr_t ​i = 1; i < 5; ++i) { 
-const char *arg0; +29│     ​pthread_t tid
- +30│     ​pthread_create(&tidNULLthreadFunc(void *)i); 
-void *threadFunc(intptr_t ​num) { +31│     ​pthread_detach(tid); 
-  char name[1024], cmd[1024]+32│   } 
-  ​sprintf(name"​%s.pipe.%ld"​arg0num); +33│   ​threadFunc(0); 
-  ​sprintf(cmd, "rm -f %s; mkfifo %s", name, name); +34│ } 
-  ​system(cmd); +35│ 
-  ​FILE ​*myPipe ​fopen(name, "​r+"​); +36│ void *threadFunc(void* numRaw) { 
- +37│   ​intptr_t num = (intptr_tnumRaw
-  while (1) { +38│   ​struct myIO win = openWin(num);​ 
-    char line[1024], nl+  ​… 
-    ​fscanf(myPipe"​%1023[^\n]%c"​, line, &nl); +48│   while (1) { 
- +49│     ​fprintf(win.out,​ "> "); 
-    int argOne = atoi(line);​ +50│ 
-    if (argOne >= 5 || argOne < 0) +51│     char line[1024];​ 
-      ​continue;​ +52│     fgets(line1024win.in); 
- +53│     ​line[strlen(line)-1] = 0
-    ​char *argTwoTxt = strchr(line,​ ' '); +54│ 
- +55│     int argOne = atoi(line);​ 
-    if (!argTwoTxt) { +  … 
-      pthread_mutex_lock(&​item[argOne].mtx);​ +61│     char *argTwoTxt = strchr(line,​ ' '); 
-      ​printf("T%ld reads %d as: %s\n", num, argOne, item[argOne].text);​ +62│ 
-      pthread_mutex_unlock(&​item[argOne].mtx);​ +63│     if (!argTwoTxt) { 
-      continue; +65│       pthread_mutex_lock(&​item[argOne].mtx);​ 
-    +66│       ​fprintf(win.out, ​"T#%ld reads %d as: %s\n", num, argOne, item[argOne].text);​ 
- +67│       pthread_mutex_unlock(&​item[argOne].mtx);​ 
-    argTwoTxt++;​ +68│       continue; 
-    char *e; +69│     
-    int argTwo = strtol(argTwoTxt,​ &e, 10); +70│ 
- +71│     argTwoTxt++;​ 
-    if (!*e && argTwo < 5 && argTwo >= 0 && argOne != argTwo) { +72│     char *e; 
-      pthread_mutex_lock(&​item[argOne].mtx);​ +73│     int argTwo = strtol(argTwoTxt,​ &e, 10); 
-      pthread_mutex_lock(&​item[argTwo].mtx);​ +74│ 
-      ​printf("T%ld copies %d to %d\n", num, argTwo, argOne); +75│     if (!*e && argTwo < 5 && argTwo >= 0 && argOne != argTwo) { 
-      memcpy(item[argOne].text,​ item[argTwo].text,​ sizeof(item[argOne].text));​ +77│       pthread_mutex_lock(&​item[argOne].mtx);​ 
-      pthread_mutex_unlock(&​item[argTwo].mtx);​ +78│       pthread_mutex_lock(&​item[argTwo].mtx);​ 
-      pthread_mutex_unlock(&​item[argOne].mtx);​ +79│       ​fprintf(win.out, ​"T#%ld copies %d to %d\n", num, argTwo, argOne); 
-    } else { +80│       memcpy(item[argOne].text,​ item[argTwo].text,​ sizeof(item[argOne].text));​ 
-      pthread_mutex_lock(&​item[argOne].mtx);​ +81│       pthread_mutex_unlock(&​item[argTwo].mtx);​ 
-      ​printf("T%ld assigns to %d the value: %s\n", num, argOne, argTwoTxt);​ +82│       pthread_mutex_unlock(&​item[argOne].mtx);​ 
-      memset(item[argOne].text,​ 0, sizeof(item[argOne].text));​ +83│     } else { 
-      strncpy(item[argOne].text,​ argTwoTxt, sizeof(item[argOne].text) - 1); +85│       pthread_mutex_lock(&​item[argOne].mtx);​ 
-      pthread_mutex_unlock(&​item[argOne].mtx);​ +86│       ​fprintf(win.out, ​"T#%ld assigns to %d the value: %s\n", num, argOne, argTwoTxt);​ 
-    +87│       memset(item[argOne].text,​ 0, sizeof(item[argOne].text));​ 
-  +88│       strncpy(item[argOne].text,​ argTwoTxt, sizeof(item[argOne].text) - 1); 
-} +89│       pthread_mutex_unlock(&​item[argOne].mtx);​ 
- +90│     
-int main(int argc, char **argv) { +91│   
-  ​arg0 = argv[0]; +92│ 
- +  ​
-  printf("​To use this program, write to one of the %s.pipe.<​thread_id>​ the " +
-         "​following:​\n"​ +
-         " ​ <​num> ​            ​prints <​text>​ from item <​num>​\n"​ +
-         " ​ <num> <​text> ​     puts <​text>​ to item <​num>​\n"​ +
-         " ​ <​num1>​ <​num2> ​    ​copies to item <​num1>​ the text from item <​num2>​\n"​ +
-         "​Valid pipe numbers are 0-4, valid item numbers are 0-4.",​ +
-         ​arg0);​ +
- +
-  for (int i = 0; i < 5; ++i) +
-    pthread_mutex_init(&​item[i].mtx,​ NULL); +
- +
-  for (intptr_t i = 1; i < 5; ++i) { +
-    pthread_t tid; +
-    pthread_create(&​tid,​ NULL, (void *(*)(void *))threadFunc,​ (void *)i); +
-    pthread_detach(tid);​ +
-  } +
-  threadFunc(0);​ +
-}+
 </​code>​ </​code>​
-</​small>​ 
 <​html></​div></​html>​ <​html></​div></​html>​
  
Line 815: Line 801:
 \\ \\
 <​html><​span style="​float:​right"><​small>​Need header:<​br><​code>​pthread.h</​code></​small></​span>​ <​html><​span style="​float:​right"><​small>​Need header:<​br><​code>​pthread.h</​code></​small></​span>​
-<a href="​https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_key_create.html"></​html>​+<a href="​https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_key_create.html"></​html>​
 ''​int **pthread_key_create**(pthread_key_t *//key//, void (*//​destructor//​)(void*))''​ ''​int **pthread_key_create**(pthread_key_t *//key//, void (*//​destructor//​)(void*))''​
 <​html></​a></​html>​ <​html></​a></​html>​
 \\ \\
-<​html><​a href="​https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_setspecific.html"></​html>​+<​html><​a href="​https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_setspecific.html"></​html>​
 ''​int **pthread_setspecific**(pthread_key_t //key//, const void *//​value//​)''​ ''​int **pthread_setspecific**(pthread_key_t //key//, const void *//​value//​)''​
 \\ \\
Line 891: Line 877:
 When one thread needs to execute some logic once a specific condition is fulfilled, When one thread needs to execute some logic once a specific condition is fulfilled,
 it should: it should:
 +<​html><​div style="​margin-top:​-1.2em"></​div></​html>​
 +<WRAP group>
 +<WRAP half column>
   - lock a mutex,   - lock a mutex,
   - check the condition,   - check the condition,
-  - if the condition is false:+  - while the condition is false:
     - wait on a condition variable,     - wait on a condition variable,
     - go back to step 2,     - go back to step 2,
   - do the logic,   - do the logic,
   - unlock the mutex.   - unlock the mutex.
 +</​WRAP>​
 +<WRAP half column>
 +<​html>​
 +<pre class="​code c" style="​margin-top:​-1.4em;​margin-bottom:​-1.4em;">​
 +<span style="​opacity:​0.66">​pthread_mutex_</​span>​lock<​span class="​br0">​(</​span><​span class="​sy0">&​amp;</​span>​mutex<​span class="​br0">​)</​span><​span class="​sy0">;</​span>​
 +<span class="​kw1">​while</​span><​span class="​br0">​(</​span><​span class="​sy0">​!</​span><​i>​condition</​i><​span class="​br0">​)</​span>​
 +  <span style="​opacity:​0.66">​pthread_cond_</​span>​wait<​span class="​br0">​(</​span><​span class="​sy0">&​amp;</​span>​condvar<​span class="​sy0">,</​span>​ <span class="​sy0">&​amp;</​span>​mutex<​span class="​br0">​)</​span><​span class="​sy0">;</​span>​
 +<​i>​logic<​span class="​br0">​(</​span><​span class="​br0">​)</​span><​span class="​sy0">;</​span></​i>​
 +<span style="​opacity:​0.66">​pthread_mutex_</​span>​unlock<​span class="​br0">​(</​span><​span class="​sy0">&​amp;</​span>​mutex<​span class="​br0">​)</​span><​span class="​sy0">;</​span>​
 +</​pre>​
 +</​html>​
 +</​WRAP>​
 +</​WRAP>​
 A thread that may change the state and thus affect the condition should: A thread that may change the state and thus affect the condition should:
 +<​html><​div style="​margin-top:​-1.2em"></​div></​html>​
 +<WRAP group>
 +<WRAP half column>
   - lock the mutex,   - lock the mutex,
   - do its logic,   - do its logic,
   - signal the condition variable,   - signal the condition variable,
   - unlock the mutex((One can also signal the condition variable after unlocking the mutex.)).   - unlock the mutex((One can also signal the condition variable after unlocking the mutex.)).
 +</​WRAP>​
 +<WRAP half column>
 +<​html>​
 +<pre class="​code c" style="​padding-top:​0;​ padding-bottom:​0;​ margin-top:​-1.4em;​margin-bottom:​-1.4em;">​
 +<span style="​opacity:​0.66">​pthread_mutex_</​span>​lock<​span class="​br0">​(</​span><​span class="​sy0">&​amp;</​span>​mutex<​span class="​br0">​)</​span><​span class="​sy0">;</​span>​
 +<​i>​logic_that_changes_condition<​span class="​br0">​(</​span><​span class="​br0">​)</​span><​span class="​sy0">;</​span></​i>​
 +<span style="​opacity:​0.66">​pthread_cond_</​span>​signal<​span class="​br0">​(</​span><​span class="​sy0">&​amp;</​span>​condvar<​span class="​br0">​)</​span><​span class="​sy0">;</​span>​
 +<span style="​opacity:​0.66">​pthread_mutex_</​span>​unlock<​span class="​br0">​(</​span><​span class="​sy0">&​amp;</​span>​mutex<​span class="​br0">​)</​span><​span class="​sy0">;</​span>​
 +</​pre>​
 +</​html>​
 +</​WRAP>​
 +</​WRAP>​
  
 <​small>​ <​small>​
 The example conditions include: The example conditions include:
 +<​html><​div style="​margin-top:​-1.2em"></​div></​html>​
   * a boolean flag is set; the flag indicates that another thread finished a part of the computation and the results can used,   * a boolean flag is set; the flag indicates that another thread finished a part of the computation and the results can used,
   * a list of items is not empty; the list contains tasks to be done by this thread,   * a list of items is not empty; the list contains tasks to be done by this thread,
Line 915: Line 933:
 \\ \\
 <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​ <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​
-<a href="​https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_cond_init.html"></​html>​+<a href="​https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_cond_init.html"></​html>​
 ''​pthread_cond_t //cond// = **PTHREAD_COND_INITIALIZER**;''​ ''​pthread_cond_t //cond// = **PTHREAD_COND_INITIALIZER**;''​
 <​html></​a></​html>​ <​html></​a></​html>​
Line 923: Line 941:
 \\ \\
 <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​ <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​
-<a href="​https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_cond_init.html"></​html>​+<a href="​https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_cond_init.html"></​html>​
 ''​int pthread_cond_init(pthread_cond_t *restrict //cond//, const pthread_condattr_t *restrict //​attr//​)''​ ''​int pthread_cond_init(pthread_cond_t *restrict //cond//, const pthread_condattr_t *restrict //​attr//​)''​
 <​html></​a></​html>​ <​html></​a></​html>​
Line 931: Line 949:
 \\ \\
 <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​ <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​
-<a href="​https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_cond_wait.html"></​html>​+<a href="​https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_cond_wait.html"></​html>​
 ''​int **pthread_cond_wait**(pthread_cond_t *restrict //cond//, pthread_mutex_t *restrict //​mutex//​)''​ ''​int **pthread_cond_wait**(pthread_cond_t *restrict //cond//, pthread_mutex_t *restrict //​mutex//​)''​
 <​html></​a></​html>​ <​html></​a></​html>​
Line 940: Line 958:
 \\ \\
 <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​ <​html><​span style="​float:​right"><​small>​Needs header: <​code>​pthread.h</​code></​small></​span>​
-<a href="​https://​pubs.opengroup.org/​onlinepubs/​9699919799/​functions/​pthread_cond_broadcast.html"></​html>​+<a href="​https://​pubs.opengroup.org/​onlinepubs/​9799919799/​functions/​pthread_cond_broadcast.html"></​html>​
 ''​int **pthread_cond_signal**(pthread_cond_t *restrict //​cond//​)''​\\ ''​int **pthread_cond_signal**(pthread_cond_t *restrict //​cond//​)''​\\
 ''​int **pthread_cond_broadcast**(pthread_cond_t *restrict //​cond//​)''​ ''​int **pthread_cond_broadcast**(pthread_cond_t *restrict //​cond//​)''​
os_cp/threads.1713432736.txt.gz · Last modified: 2024/04/18 11:32 by jkonczak