#include #include #include #include #include #define MAX_BURST 10 #define FILL_RATE 1 int bucketLevel=MAX_BURST; int BUCKET_SIZE= MAX_BURST; int PACKET_SIZE=1; /* one char per "packet" going to the screen */ int fillingRate= FILL_RATE; pthread_mutex_t bucketLock = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t bucketChange = PTHREAD_COND_INITIALIZER; sigset_t mask; void * fillBucket(void * arg) /* fill the bucket at a constant * rate while it is not full*/ { struct itimerval timerval; struct timeval period; int signo; period.tv_sec=1; period.tv_usec=0; timerval.it_interval=timerval.it_value=period; setitimer(ITIMER_REAL, & timerval, NULL); while (1) { signo=SIGINT; /* anything different from SIGALRM */ while(signo!=SIGALRM) /* this should not be necessary if mask specifies one signal */ sigwait(&mask, &signo); /* to wait until SIGALRM condition arises, sigwait clears the signal from the set of pending signals.*/ pthread_mutex_lock(&bucketLock); if (bucketLevel+fillingRate <= BUCKET_SIZE) bucketLevel+=fillingRate; pthread_mutex_unlock(&bucketLock); pthread_cond_signal(&bucketChange); } } int main(int argc, char * argv[]) { pthread_t tid; char c; int err; /* this is to handle signals in a thread. */ sigemptyset(&mask); /* here we initialize mask to an empty set */ sigaddset(&mask,SIGALRM); /* include SIGALRM in the set */ pthread_sigmask(SIG_BLOCK, &mask, NULL); /* When the SIGALRM condition arises, it is added to a set of signal pending for the process, but in the case of a BLOCKED signal, its delivery is postponed. */ err = pthread_create(&tid, NULL, fillBucket, NULL); if (err != 0){ printf("can't create thread \n"); exit(0); } c = getchar(); while (c!=EOF) { pthread_mutex_lock(&bucketLock); while ( bucketLevel < PACKET_SIZE) /* while bucket is almost empty */ pthread_cond_wait(&bucketChange, &bucketLock); bucketLevel-=PACKET_SIZE; pthread_mutex_unlock(&bucketLock); putchar(c); fflush(stdout); c = getchar(); } exit(0); }