Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save akolybelnikov/6cec5d38c5684875155aaff6e58febf8 to your computer and use it in GitHub Desktop.
Save akolybelnikov/6cec5d38c5684875155aaff6e58febf8 to your computer and use it in GitHub Desktop.
C11 code to have a POSIX multithreaded application which signal work completion via a condition variable, and then terminate.
#include <unistd.h>
#include <stdbool.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 10
pthread_mutex_t cv_mutex;
pthread_cond_t notification_cv;
pthread_t threads[NUM_THREADS];
bool allfinished = false;
void *worker(void *arg) {
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
int loop = 0;
while (true) {
printf("iteration %d\n", loop);
++loop;
/* Do some "work": */
;
pthread_mutex_lock(&cv_mutex);
if (loop > 5) { /* Simulate "work end" */
allfinished = true;
pthread_cond_broadcast(&notification_cv);
pthread_mutex_unlock(&cv_mutex);
pthread_exit(NULL);
}
pthread_mutex_unlock(&cv_mutex);
}
pthread_exit(NULL);
}
void *master(void *t) {
/* Lock mutex and wait for signal. */
pthread_mutex_lock(&cv_mutex);
while (!allfinished)
pthread_cond_wait(&notification_cv, &cv_mutex);
printf("master: woken up.\n");
pthread_mutex_unlock(&cv_mutex);
for (size_t i = 0; i < NUM_THREADS; ++i) {
pthread_cancel(threads[i]);
}
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
pthread_attr_t attr;
/* Initialize mutex and condition variable objects */
pthread_mutex_init(&cv_mutex, NULL);
pthread_cond_init(&notification_cv, NULL);
/* For portability, explicitly create threads in a joinable state */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_t s;
pthread_create(&s, &attr, master, NULL);
for(size_t i = 0; i < sizeof threads / sizeof *threads; ++i) {
if (!pthread_create (&threads[i], &attr, worker, NULL) ) {
printf("worker %zu created\n", i);
}
}
/* Wait for all threads to complete. This will not wait forever because the master
* thread will cancel all of the workers:
*/
for (size_t i = 0; i < sizeof threads / sizeof *threads; ++i) {
pthread_join(threads[i], NULL);
printf("worker %zu done\n", i);
}
pthread_join(s, NULL);
printf("master done\n");
/* Clean up and exit */
pthread_attr_destroy(&attr);
pthread_mutex_destroy(&cv_mutex);
pthread_cond_destroy(&notification_cv);
pthread_exit(NULL);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment