// multiple threads generating musical notes // // POSIX version, using locks and conditions // #include #include #include #include // // compile flags: -pthread #define Pthread_create(a,b,c,d) assert(pthread_create(a,b,c,d) == 0) #define Pthread_mutex_lock(m) assert(pthread_mutex_lock(m) == 0) #define Pthread_mutex_unlock(m) assert(pthread_mutex_unlock(m) == 0) #define Pthread_cond_signal(c) assert(pthread_cond_signal(c) == 0) #define Pthread_cond_wait(c,m) assert(pthread_cond_wait(c,m) == 0) #define N 3 // number of threads int notes0[] = { 44, 6, 42, 6, 40, 12, -1 }; int notes1[] = { 47, 2, 52, 4, 52, 2, 51, 2, 49, 2, 51, 2, 52, 4, 47, 2, 47, 4, -1 }; int notes2[] = { 47, 6, 45, 4, 45, 2, 44, 12, -1 }; typedef struct { pthread_mutex_t lock; // lock for wait condition pthread_cond_t cond; // wait condition // int wait; // 0 = play() should wait, 1 = main() should wait, -1 = done int *notes; // key, duration pairs, end with -1 double value; // output value } Data; Data D[N] = { { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 1, notes0, 0 }, { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 1, notes1, 0 }, { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 1, notes2, 0 } }; double pi, ratio; void play( int key, int duration, Data *d) { double r, w = (2*pi*440*pow(ratio,key-49))/8000.0; int n = (duration/10.0)*8000.0; for( int i = 0; i < n; ++i) { r = sin(w*i) + 0.5*sin(2*w*i) + 0.25*sin(3*w*i); Pthread_mutex_lock( &d->lock); while( d->wait == 0) Pthread_cond_wait( &d->cond, &d->lock); d->value = r; d->wait = 0; Pthread_cond_signal( &d->cond); Pthread_mutex_unlock( &d->lock); } } void *f( void *v) { Data *d = v; for( int i = 0; d->notes[i] >= 0; i += 2) play( d->notes[i], d->notes[i+1], d); Pthread_mutex_lock( &d->lock); while( d->wait == 0) Pthread_cond_wait( &d->cond, &d->lock); d->wait = -1; // done Pthread_cond_signal( &d->cond); Pthread_mutex_unlock( &d->lock); return 0; } int main( void) { int done; double sum; pthread_t t[N]; pi = 4*atan(1); ratio = pow(2,1.0/12.0); for( int i = 0; i < N; ++i) Pthread_create( t+i, 0, f, D+i); while( 1) { done = 1; sum = 0; for( int i = 0; i < N; ++i) { Pthread_mutex_lock( &D[i].lock); while( D[i].wait == 1) Pthread_cond_wait( &D[i].cond, &D[i].lock); if( D[i].wait == 0) { done = 0; sum += D[i].value; D[i].wait = 1; Pthread_cond_signal( &D[i].cond); } Pthread_mutex_unlock( &D[i].lock); } if( done) break; printf( "%g\n", sum); } return 0; }