/* Compile with cc -Og -o thread_sleeps -pthread thread_sleeps.c */ #include #include #include #include #include int main(int argc, char *argv[]); void* sender(void*); void* receiver(void*); static pthread_mutex_t mutex; static pthread_cond_t sent = PTHREAD_COND_INITIALIZER; int n_sends = 0; #define NPASSES 20 int main(int argc, char *argv[]) { pthread_t sender_tid; pthread_t receiver_tid; pthread_mutexattr_t attr; /* * Unfortunately the default initialization for mutexes is a poor choice. * Create an error-checking mutex. If you are doing multiple mutexes, * you only need to do the first two lines once. */ pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); pthread_mutex_init(&mutex, &attr); if (pthread_create (&sender_tid, NULL, sender, NULL) != 0) { fprintf(stderr, "Couldn't create sender thread\n"); return 1; } if (pthread_create (&receiver_tid, NULL, receiver, NULL) != 0) { fprintf(stderr, "Couldn't create receiver thread\n"); return 1; } if (pthread_join (sender_tid, NULL) != 0) { fprintf(stderr, "Couldn't join with sender thread\n"); return 1; } if (pthread_join (receiver_tid, NULL) != 0) { fprintf(stderr, "Couldn't join with receiver thread\n"); return 1; } return 0; } /* * The sender sends one signal per second, bumping n_sends each time. */ void* sender(void* data) { int error; int i; for (i = 0; i < NPASSES; i++) { sleep(1); printf("Sender sent %d time(s)\n", i + 1); error = pthread_mutex_lock(&mutex); if (error) { (void)fprintf(stderr, "Lock failed: %s\n", strerror(error)); exit(1); } ++n_sends; error = pthread_cond_signal(&sent); if (error) { (void)fprintf(stderr, "Signal failed: %s\n", strerror(error)); exit(1); } error = pthread_mutex_unlock(&mutex); if (error) { (void)fprintf(stderr, "Unlock failed: %s\n", strerror(error)); exit(1); } } return NULL; } /* * The receiver counts the number of sends it has seen. After * receiving a message, it might sleep up to 3 seconds. */ void* receiver(void* data) { int error; int messages_seen = 0; while (1) { if (messages_seen >= NPASSES) { printf(" Receiver saw %d messages\n", messages_seen); return NULL; } error = pthread_mutex_lock(&mutex); if (error) { (void)fprintf(stderr, "Lock failed: %s\n", strerror(error)); exit(1); } while (n_sends == messages_seen) { error = pthread_cond_wait(&sent, &mutex); if (error) { (void)fprintf(stderr, "Wait failed: %s\n", strerror(error)); exit(1); } } error = pthread_mutex_unlock(&mutex); if (error) { (void)fprintf(stderr, "Unlock failed: %s\n", strerror(error)); exit(1); } ++messages_seen; printf(" Receiver saw %d messages...", messages_seen); if (n_sends < messages_seen) { printf("Oops! Saw more messages than sent!\n"); exit(1); } else if (n_sends == messages_seen) { int sleep_time = random() % 4; if (sleep_time == 0) printf("but not sleeping\n"); else { printf("sleeping %d second(s)\n", sleep_time); sleep(sleep_time); } } else printf("continuing immediately\n"); } }