| // Copyright 2015 The Emscripten Authors. All rights reserved. |
| // Emscripten is available under two separate licenses, the MIT license and the |
| // University of Illinois/NCSA Open Source License. Both these licenses can be |
| // found in the LICENSE file. |
| |
| #include <pthread.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <emscripten/emscripten.h> |
| #include <emscripten/console.h> |
| |
| #define NUM_THREADS 3 |
| #define TCOUNT 10 |
| #define COUNT_LIMIT 12 |
| |
| int count = 0; |
| int thread_ids[3] = {0,1,2}; |
| pthread_mutex_t count_mutex; |
| pthread_cond_t count_threshold_cv; |
| |
| void *inc_count(void *t) |
| { |
| int i; |
| long my_id = (long)t; |
| |
| for (i=0; i<TCOUNT; i++) { |
| pthread_mutex_lock(&count_mutex); |
| count++; |
| |
| /* |
| Check the value of count and signal waiting thread when condition is |
| reached. Note that this occurs while mutex is locked. |
| */ |
| if (count == COUNT_LIMIT) { |
| pthread_cond_signal(&count_threshold_cv); |
| emscripten_outf("inc_count(): thread %ld, count = %d Threshold reached.\n", my_id, count); |
| } |
| emscripten_outf("inc_count(): thread %ld, count = %d, unlocking mutex\n", my_id, count); |
| pthread_mutex_unlock(&count_mutex); |
| |
| /* Do some "work" so threads can alternate on mutex lock */ |
| //sleep(1); |
| } |
| pthread_exit(NULL); |
| } |
| |
| void *watch_count(void *t) |
| { |
| long my_id = (long)t; |
| |
| emscripten_outf("Starting watch_count(): thread %ld\n", my_id); |
| |
| /* |
| Lock mutex and wait for signal. Note that the pthread_cond_wait |
| routine will automatically and atomically unlock mutex while it waits. |
| Also, note that if COUNT_LIMIT is reached before this routine is run by |
| the waiting thread, the loop will be skipped to prevent pthread_cond_wait |
| from never returning. |
| */ |
| pthread_mutex_lock(&count_mutex); |
| while (count<COUNT_LIMIT) { |
| pthread_cond_wait(&count_threshold_cv, &count_mutex); |
| emscripten_outf("watch_count(): thread %ld Condition signal received.\n", my_id); |
| count += 125; |
| emscripten_outf("watch_count(): thread %ld count now = %d.\n", my_id, count); |
| } |
| pthread_mutex_unlock(&count_mutex); |
| pthread_exit(NULL); |
| } |
| |
| int main (int argc, char *argv[]) |
| { |
| int i, rc; |
| long t1=1, t2=2, t3=3; |
| pthread_t threads[3]; |
| |
| /* Initialize mutex and condition variable objects */ |
| pthread_mutex_init(&count_mutex, NULL); |
| pthread_cond_init(&count_threshold_cv, NULL); |
| |
| /* For portability, explicitly create threads in a joinable state */ |
| pthread_create(&threads[0], NULL, watch_count, (void *)t1); |
| pthread_create(&threads[1], NULL, inc_count, (void *)t2); |
| pthread_create(&threads[2], NULL, inc_count, (void *)t3); |
| |
| /* Wait for all threads to complete */ |
| for (i=0; i<NUM_THREADS; i++) { |
| pthread_join(threads[i], NULL); |
| } |
| emscripten_outf("Main(): Waited on %d threads. Done.\n", NUM_THREADS); |
| |
| /* Clean up and exit */ |
| pthread_mutex_destroy(&count_mutex); |
| pthread_cond_destroy(&count_threshold_cv); |
| return 0; |
| } |