Home | | Network Programming and Management | Condition Variables

Chapter: Network Programming and Management : Advanced Sockets

Condition Variables

A mutex is fine to prevent simultaneous access to a shared variable, but we need something else to let us go to sleep waiting for some condition to occur.

Condition Variables

 

A mutex is fine to prevent simultaneous access to a shared variable, but we need something else to let us go to sleep waiting for some condition to occur. Let's demonstrate this with an exampleBut,

 

we cannot call the Pthread function until we know that a thread has terminated. We first declare a global variable that counts the number of terminated threads and protect it with a mutex.

 

int ndone; /* number of terminated threads */ 

pthread_mutex_t ndone_mutex = PTHREAD_MUTEX_INITIALIZER;

 

We then require that each thread increment this counter when it terminates, being careful to use the associated mutex.

 

void *

do_get_read (void *vptr)

 

{

...

 

Pthread_mutex_lock(&ndone_mutex);

ndone++;

Pthread_mutex_unlock(&ndone_mutex);

 

return(fptr); /* terminate thread */

 

}

 

A condition variable, in conjunction with a mutex, provides this facility. The mutex provides mutual exclusion and the condition variable provides a signaling mechanism.

 

In terms of Pthreads, a condition variable is a variable of type pthread_cond_t. They are used with

 

the following two functions:

 

#include <pthread.h>

 

int   pthread_cond_wait(pthread_cond_t *cptr, pthread_mutex_t *mptr);

 

int   pthread_cond_signal(pthread_cond_t *cptr);

Both return: 0 if OK, positive Exxx 

value on error

 

The term "signal" in the second function's name does not refer to a Unix SIGxxx signal.

Why is a mutex always associated with a condition variable? The "condition" is normally the value of some variable that is shared between the threads. The mutex is required to allow this variable tobe set and tested by the different threads. For example, if we did not have the mutex in the example code just shown, the main loop would test it as follows:

 

 

/* Wait for thread to terminate */ while (ndone == 0)

Pthread_cond_wait(&ndone_cond, &ndone_mutex);

 

 

The thread would have to unlock and lock the mutex and the code would look like the following:

 

/* Wait for thread to terminate */ Pthread_mutex_lock(&ndone_mutex); while (ndone == 0) {

 

Pthread_mutex_unlock(&ndone_mutex); Pthread_cond_wait(&ndone_cond, &ndone_mutex); Pthread_mutex_lock(&ndone_mutex);

}

 

#include <pthread.h>

 

int  pthread_cond_broadcast                       (pthread_cond_t    * cptr);

 

int  pthread_cond_timedwait                       (pthread_cond_t    * cptr, pthread_mutex_t *mptr,

const

struct timespec *abstime);

 

Both return: 0 if OK, positive Exxx

value on error

 

pthread_cond_timedwait lets a thread place a limit on how long it will block. abstime is a timespec structure (as we defined with the pselect function, that specifies the system time when the function must return, even if the condition variable has not been signalled yet. If this timeout occurs, ETIME is returned.

 

This time value is an absolute time; it is not a time delta. That is, abstime is the system time—the number of seconds and nanoseconds past January 1, 1970, UTC—when the function should return. This differs from both select and pselect, which specify the number of seconds and microseconds (nanoseconds for pselect) until some time in the future when the function should return. The normal procedure is to call gettimeofday to obtain the current time (as a timeval structure!), and copy this into a timespec structure, adding in the desired time limit. For example,

struct timeval tv;

 

struct timespec ts;

 

if (gettimeofday(&tv, NULL) < 0)

 

err_sys("gettimeofday error");

 

ts.tv_sec = tv.tv_sec + 5;         /* 5 seconds in future */

 

ts.tv_nsec = tv.tv_usec * 1000; /* microsec to nanosec */

 

 

pthread_cond_timedwait( ..., &ts);

 

 

The advantage in using an absolute time instead of a delta time is if the function prematurely returns (perhaps because of a caught signal), the function can be called again, without having to change the contents of the timespec structure. The disadvantage, however, is having to call gettimeofday before the function can be called the first time.

 

The POSIX specification defines a clock_gettime function that returns the current time as a timespec structure.


Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail
Network Programming and Management : Advanced Sockets : Condition Variables |


Privacy Policy, Terms and Conditions, DMCA Policy and Compliant

Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.