Hello,

PTHREAD_COND_WAIT(3) is precise but easy to misread.

It first say it will unlock the mutex given as a second argument, and after
talking about the rest say it will be locked again.

This second lock it supposed to have a particular usage, reading
documentation about this i found a stackoverflow answer that is very clear
:
http://stackoverflow.com/questions/2763714/why-do-pthreads-condition-variable-functions-require-a-mutex

g+ community was talking about this book :
http://pragprog.com/book/pb7con/seven-concurrency-models-in-seven-weeks

is there an exemple inside ?

My poor brain is not even to produce something 'good':

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <unistd.h>
#include <sys/queue.h>

#define NTHREADS    7

int on = 1;
pthread_cond_t      jobs_signal  = PTHREAD_COND_INITIALIZER;
pthread_mutex_t     jobs_lock = PTHREAD_MUTEX_INITIALIZER;

struct job {
  int type;
  SIMPLEQ_ENTRY(job) entries;
};


void *consumer(void *parm)
{
  int           rc;
  struct job*   current_job;
  SIMPLEQ_HEAD(jobhead, job) *jobs_queue = (struct jobhead*)parm;
  while (on) {
    rc = pthread_mutex_lock(&jobs_lock);
    warn("consumer thread control code, lock:%d", rc);

    while (SIMPLEQ_EMPTY(jobs_queue) && on) {
      warn("consumer thread is waiting");
      rc = pthread_cond_wait(&jobs_signal, &jobs_lock);
      warn("consumer thread received signal %d", rc);
    }
    if (on == 0) {
      pthread_mutex_unlock(&jobs_lock);
      pthread_cond_broadcast(&jobs_signal); //FIXME: OF course only one
thread is waiting so must resignal....
      return NULL;
    }

    current_job = SIMPLEQ_FIRST(jobs_queue);
    SIMPLEQ_REMOVE_HEAD(jobs_queue, entries);

    warn("consume jobs_queue one at a time here: %X", current_job->type);

    rc = pthread_mutex_unlock(&jobs_lock);
    warn("consumer pthread_mutex_lock():  %d", rc);

    warn("consume jobs_queue in each threads at the time here: %X",
current_job->type);
    free(current_job);
  }
  return NULL;
}

int main(int argc, char **argv)
{
  int                   rc=0;
  int                   i;
  pthread_t             threadid[NTHREADS];
  struct job*           new_job;
  SIMPLEQ_HEAD(jobhead, job) jobs = SIMPLEQ_HEAD_INITIALIZER(jobs);

  printf("Create %d threads\n", NTHREADS);
  for(i=0; i<NTHREADS; ++i) {
    rc = pthread_create(&threadid[i], NULL, consumer, &jobs);
    warn("pthread_create(,,consumer,jobs) : %d", rc);
  }
  //lets produce

  i = 50;
  while (--i) {
    new_job = malloc(sizeof(struct job));
    if (new_job == 0) err(3, "cant malloc");
    new_job->type = rand();
    rc = pthread_mutex_lock(&jobs_lock);
    warn("producer thread create job: (lock)%d, type %X", rc,
new_job->type);
    SIMPLEQ_INSERT_TAIL(&jobs, new_job, entries);
    pthread_cond_signal(&jobs_signal);
    rc = pthread_mutex_unlock(&jobs_lock);
    warn("producer pthread_mutex_lock(): %d", rc);
  }
  while (0xBAD) {
    sleep(1);
    rc = pthread_mutex_lock(&jobs_lock);
    if (SIMPLEQ_EMPTY(&jobs)) break;
    rc = pthread_mutex_unlock(&jobs_lock);
  }
  rc = pthread_mutex_unlock(&jobs_lock);

  //quit
  on = 0;
  pthread_cond_broadcast(&jobs_signal);
  warn("waiting for threads...");
  for (i=0; i<NTHREADS; ++i) {
    rc = pthread_join(threadid[i], NULL);
  }
  warn("cleaning locks...");
  pthread_cond_destroy(&jobs_signal);
  pthread_mutex_destroy(&jobs_lock);

  warn("exit");
  return 0;
}








-- 
---------------------------------------------------------------------------------------------------------------------
() ascii ribbon campaign - against html e-mail
/\

Reply via email to