/* * This is the thread routine for removing * items from the chat buffer and sending * them to the user. */ #include #include #include "chat.h" void *OutputToUser(void *ptArgs) { struct chatbuff * volatile G ; int mySock ; struct linebuff myLineBuff ; int myNextSlot ; int stillConnected ; FILE *sockOut ; mySock = ((struct ptGenericArg *)ptArgs) -> sock ; G = ((struct ptGenericArg *)ptArgs) -> G ; free(ptArgs) ; stillConnected = 1 ; /* This locking is really a little excessive */ /* but perhaps there really aren't atomic integer reads */ pthread_mutex_lock(&G->nextSlotMutex) ; myNextSlot = G->nextSlot ; pthread_mutex_unlock(&G->nextSlotMutex) ; if ((sockOut = fdopen(mySock, "w")) == (FILE *)NULL) { perror("fdopen") ; pthread_exit((void *)NULL) ; } while (stillConnected) { int i ; pthread_mutex_lock(&G->nextSlotMutex) ; while (myNextSlot == G->nextSlot) pthread_cond_wait(&G->nextSlotConditional, &G->nextSlotMutex) ; pthread_mutex_unlock(&G->nextSlotMutex) ; /* RW lock only needed if being lapped */ pthread_rwlock_rdlock(&G->buffRWlock[myNextSlot]) ; bcopy((void *)&G->buff[myNextSlot], (void *)&myLineBuff, sizeof(struct linebuff)); pthread_rwlock_unlock(&G->buffRWlock[myNextSlot]) ; for (i=0; inextSlotMutex) ; INCRSLOT(&myNextSlot) ; pthread_mutex_unlock(&G->nextSlotMutex) ; } return ((void *)NULL) ; }