Thread: PThreads - specifically pthread_cond_wait and pthread_cond_signal

  1. #1
    Registered User
    Join Date
    Mar 2011
    Posts
    21

    PThreads - specifically pthread_cond_wait and pthread_cond_signal

    Having a little problem with a threaded producer/consumer application - one producer, multiple consumers.

    Code:
     producer(){
    for (i=9; i<argc; i++){
    		//handle files
    		input = fopen(argv[i], "r");
    		if (!input){
    			fprintf(stderr, "File \"%s\" Not available.\n", argv[i]);
    			continue;
    		}//if
    		while(!feof(input)){
    			if (pthread_mutex_lock(&bufMutex[writepos]))
    				fail("Mutex Error");
    			while (BUF_FULL){
    				if (name-'a'<max){
    					if (pthread_create(&thread[name-'a'], NULL, reader, &name))
    						fail("Error Creating Reader Threads");
    					name++;
    				}//if
    				pthread_cond_wait(&NotFull, &bufMutex[writepos]);
    			}//while
    			do{
    				fgets(buffer[writepos], LINELEN, input);
    				int len=strlen(buffer[writepos])-1;
    				if (len && buffer[writepos][len]=='\n')
    					buffer[writepos][len]=0x0;
    			}while (!feof(input) && buffer[writepos][0]==0x0);
    			
    			if (pthread_mutex_unlock(&bufMutex[writepos]))
    				fail("Mutex Error");
    			if (!buffer[writepos][0])
    				continue;
    			writepos = (writepos+1)%lines;
    			if(pthread_cond_signal(&NotEmpty))fail("Signaling Error!");
    			usleep(1000*fdelay);	
    		}//while
    	}//for
    	printf("Finished reading.\n");
    	if (pthread_mutex_lock(&bufMutex[writepos]))
    		fail("Mutex Error");
    	buffer[writepos][0]=0x0;
    	writepos++;
    	if (pthread_mutex_unlock(&bufMutex[writepos]))
    		fail("Mutex Error");
    	void *whocares;
    	printf("Write Position: %d  Read Position: %d\n", writepos, readpos);
    	printf("Threads in existence: %d\n", (int)name-'a');
    	printf("Hey, other threads, wake up!\n");
    	if(pthread_cond_signal(&NotEmpty))fail("Signaling Error!");
    	printf("Waiting for thread termination.\n");
    	for(name=name-'b';name>=0;name--)
    		pthread_join(thread[(int)name], &whocares);
        }
    }
    Code:
    consumer(){
    	char buf[LINELEN];
    	do{
    		if (pthread_mutex_lock(&readTex)) fail("Error locking Mutex"); //protect me from other readers
    		while (BUF_EMPTY){
    			printf("\nWaiting for buffer to have data...");
    			pthread_cond_wait(&NotEmpty, &readTex);
    			printf("I'm up!");
    		}
    		if (pthread_mutex_lock(&bufMutex[readpos])) fail("Error locking Mutex"); //protect me from the writer
    		strcpy(buf, buffer[readpos]);
    		printf("\nGot a line...");
    		if (buf[0]){
    			readpos = (readpos+1)%lines;
    			printf("Not empty.\n");
    		}
    		//else
    			//break;
    		if (pthread_mutex_unlock(&bufMutex[readpos])) fail("Error locking Mutex");
    		if (pthread_mutex_unlock(&readTex)) fail("Error locking Mutex");
    		if (pthread_cond_signal(&NotFull))fail("Signaling Error!");
    		char* tokenizer=buf;
    		char* tok;
    		usleep(1000*tdelay);
    		while((tok=nextTok(&tokenizer))[0]!=0x0){
    			addWord(tok, strlen(tok)%2);
    			printf("%c", *((char*)n));
    			
    		}
    	}while(buf[0]);
    	if(pthread_cond_signal(&NotEmpty))fail("Signaling Error!");
    	pthread_exit((void *)NULL); 
    	return NULL;  //I know this is redundant, but hey.
    }
    For some reason, the last pthread_cond_signal in the producer doesn't actually want to wake up the consumer. Anyone have any idea why?
    Last edited by FrankTheKneeMan; 04-06-2011 at 10:13 AM. Reason: Unreadable code

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    How do you determine it "doesn't want to wake up the consumer"? Are you sure there is a consumer that is blocked on that NotEmpty? If not, there is nobody to wake up. Maybe you mean to signal NotFull? This is really difficult to debug as is, since I don't know what exactly you are trying to accomplish here, and I'm missing several key variable and function definitions. It would be really helpful if you could give us the smallest compilable piece of code that demonstrates the problem, and maybe some usage instructions, so I can help you debug.

  3. #3
    Registered User
    Join Date
    Mar 2011
    Posts
    21
    Well, I've pumped the code full of those diagnostic print statements, and the output goes something like this:

    Waiting for buffer to have data...I'm up!
    Got a line...Not empty.
    bbbbbbbbbbbb
    Waiting for buffer to have data...I'm up!
    Got a line...Not empty.
    bbbbbbbbbbbb
    Waiting for buffer to have data...Finished reading.
    Write Position: 7 Read Position: 6
    Threads in existence: 1
    Hey, other threads, wake up!
    Waiting for thread termination.
    Indicating that the consumer thread is hanging on the pthread_cond_wait(); I'll attach the file (it's really not that much more information). Some usage:
    counter -b numlines -t maxcounters -d fi ledelay -D threaddelay file ...
    - numlines is a positive non-zero integer;
    - maxcounters is a positive non-zero integer no greater than 26;
    - fi ledelay is a positive integer (zero allowed); and
    - threaddelay is a positive integer (zero allowed)
    - file is a text file (additional arguments allowed, each will be read as a text file)
    The consumer reads a line into the buffer, then the consumer breaks it into "words" and adds it to the lists. Even and odd length words are separated. Eventually it will print them.

    I'm compiling via
    Code:
    $ gcc -g -lpthread -Wall -o counter counter.c

  4. #4
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    How many consumer threads are there?

    When you call pthread_cond_signal(), only one thread will be woken up. If you want all threads on that condvar to wake up, you need to call pthread_cond_broadcast() instead.

    Probably your call to pthread_join() blocks because some consumer is still waiting for a wakeup that it will never receive because you're using the wrong kind of wakeup.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  5. #5
    Registered User
    Join Date
    Mar 2011
    Posts
    21
    Variable. I've been running it with only one, just to test functionality. Changed it to a broadcast, but it didn't seem to help. All the literature I've read says that once signaled, the thread should wake up... but it just isn't. I find that the most befuddling. Clearly, there's something I'm missing here.

  6. #6
    Registered User
    Join Date
    Mar 2011
    Posts
    21
    Found it. I wasn't unlocking the right mutex - I'm using an array of mutexes to lock individual buffer slots, and I was incrementing the array variable, and thus it attempted to unlock the next mutex rather then the one from before. So it was hanging two calls later.

    Thanks for your help.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Threads other than pthreads?
    By dayalsoap in forum C Programming
    Replies: 10
    Last Post: 05-28-2010, 01:56 AM
  2. using pthreads with an API that uses pthreads
    By MK27 in forum C Programming
    Replies: 3
    Last Post: 03-06-2009, 02:47 PM
  3. Pthreads performance
    By C_ntua in forum C Programming
    Replies: 42
    Last Post: 06-17-2008, 11:29 AM
  4. Difference between win32 and linux pthreads
    By philipsan in forum C Programming
    Replies: 1
    Last Post: 02-07-2006, 04:57 PM
  5. pthreads and resources
    By ubermensch in forum C Programming
    Replies: 2
    Last Post: 02-07-2006, 02:27 AM

Tags for this Thread