% % This file was automatically produced at Feb 27 2003, 22:51:56 by % c2latex -c condvar1.c % \documentclass[11pt,a4paper]{article} \setlength{\textwidth}{15cm} \setlength{\textheight}{22.5cm} \setlength{\hoffset}{-2cm} \setlength{\voffset}{-2cm} \begin{document} \expandafter\ifx\csname indentation\endcsname\relax% \newlength{\indentation}\fi \setlength{\indentation}{0.5em} \begin{flushleft} {$/\ast$\it{}$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$\mbox{}\\ $\ast$ FILE: condvar1.c\mbox{}\\ $\ast$ DESCRIPTION:\mbox{}\\ $\ast$ Example code for using Pthreads condition variables. The main thread\mbox{}\\ $\ast$ creates three threads. Two of those threads increment a "count" variable,\mbox{}\\ $\ast$ while the third thread watches the value of "count". When "count" \mbox{}\\ $\ast$ reaches a predefined limit, the waiting thread is signaled by one of the\mbox{}\\ $\ast$ incrementing threads.\mbox{}\\ $\ast$\mbox{}\\ $\ast$ SOURCE: Adapted from example code in "Pthreads Programming", B. Nichols\mbox{}\\ $\ast$ et al. O'Reilly and Associates. \mbox{}\\ $\ast$ LAST REVISED: 02/11/2002 Blaise Barney\mbox{}\\ $\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast$$\ast/$}\mbox{}\\ \mbox{}\\ {\tt \#include} $<${\tt{}pthread.h}$>$\mbox{}\\ {\tt \#include} $<${\tt{}stdio.h}$>$\mbox{}\\ \mbox{}\\ {\tt \#define} NUM\_THREADS 3\mbox{}\\ {\tt \#define} TCOUNT 10\mbox{}\\ {\tt \#define} COUNT\_LIMIT 12\mbox{}\\ \mbox{}\\ {\bf int} count = 0;\mbox{}\\ {\bf int} thread\_ids[3] = \{0,1,2\};\mbox{}\\ pthread\_mutex\_t count\_mutex;\mbox{}\\ pthread\_cond\_t count\_threshold\_cv;\mbox{}\\ \mbox{}\\ {\bf void} $\ast$inc\_count({\bf void} $\ast$idp) \mbox{}\\ \{\mbox{}\\ \hspace*{2\indentation}{\bf int} j,i;\mbox{}\\ \hspace*{2\indentation}{\bf double} result=0.0;\mbox{}\\ \hspace*{2\indentation}{\bf int} $\ast$my\_id = idp;\mbox{}\\ \mbox{}\\ \hspace*{2\indentation}{\bf for} (i=0; i $<$ TCOUNT; i++) \{\mbox{}\\ \hspace*{4\indentation}pthread\_mutex\_lock(\&count\_mutex);\mbox{}\\ \hspace*{4\indentation}count++;\mbox{}\\ \mbox{}\\ \hspace*{4\indentation}{$/\ast$\it{} \mbox{}\\ \hspace*{4\indentation}Check the value of count and signal waiting thread when condition is\mbox{}\\ \hspace*{4\indentation}reached. Note that this occurs while mutex is locked. \mbox{}\\ \hspace*{4\indentation}$\ast/$}\mbox{}\\ \hspace*{4\indentation}{\bf if} (count == COUNT\_LIMIT) \{\mbox{}\\ \hspace*{6\indentation}pthread\_cond\_signal(\&count\_threshold\_cv);\mbox{}\\ \hspace*{6\indentation}printf({\tt"inc\_count(): thread \%d, count $=$ \%d Threshold reached.$\backslash$n"}, \mbox{}\\ \hspace*{13\indentation}$\ast$my\_id, count);\mbox{}\\ \hspace*{6\indentation}\}\mbox{}\\ \hspace*{4\indentation}printf({\tt"inc\_count(): thread \%d, count $=$ \%d, unlocking mutex$\backslash$n"}, \mbox{}\\ \hspace*{11\indentation}$\ast$my\_id, count);\mbox{}\\ \hspace*{4\indentation}pthread\_mutex\_unlock(\&count\_mutex);\mbox{}\\ \mbox{}\\ \hspace*{4\indentation}{$/\ast$\it{} Do some work so threads can alternate on mutex lock $\ast/$}\mbox{}\\ \hspace*{4\indentation}{\bf for} (j=0; j $<$ 1000; j++)\mbox{}\\ \hspace*{6\indentation}result = result + ({\bf double})random();\mbox{}\\ \hspace*{4\indentation}\}\mbox{}\\ \hspace*{2\indentation}pthread\_exit(NULL);\mbox{}\\ \}\mbox{}\\ \mbox{}\\ {\bf void} $\ast$watch\_count({\bf void} $\ast$idp) \mbox{}\\ \{\mbox{}\\ \hspace*{2\indentation}{\bf int} $\ast$my\_id = idp;\mbox{}\\ \mbox{}\\ \hspace*{2\indentation}printf({\tt"Starting watch\_count(): thread \%d$\backslash$n"}, $\ast$my\_id);\mbox{}\\ \mbox{}\\ \hspace*{2\indentation}{$/\ast$\it{}\mbox{}\\ \hspace*{2\indentation}Lock mutex and wait for signal. Note that the pthread\_cond\_wait routine\mbox{}\\ \hspace*{2\indentation}will automatically and atomically unlock mutex while it waits. \mbox{}\\ \hspace*{2\indentation}Also, note that if COUNT\_LIMIT is reached before this routine is run by\mbox{}\\ \hspace*{2\indentation}the waiting thread, the loop will be skipped to prevent pthread\_cond\_wait\mbox{}\\ \hspace*{2\indentation}from never returning.\mbox{}\\ \hspace*{2\indentation}$\ast/$}\mbox{}\\ \hspace*{2\indentation}pthread\_mutex\_lock(\&count\_mutex);\mbox{}\\ \hspace*{2\indentation}{\bf while} (count $<$ COUNT\_LIMIT) \{\mbox{}\\ \hspace*{4\indentation}pthread\_cond\_wait(\&count\_threshold\_cv, \&count\_mutex);\mbox{}\\ \hspace*{4\indentation}printf({\tt"watch\_count(): thread \%d Condition signal received.$\backslash$n"}, $\ast$my\_id);\mbox{}\\ \hspace*{4\indentation}\}\mbox{}\\ \hspace*{2\indentation}pthread\_mutex\_unlock(\&count\_mutex);\mbox{}\\ \hspace*{2\indentation}pthread\_exit(NULL);\mbox{}\\ \}\mbox{}\\ \mbox{}\\ {\bf int} main({\bf int} argc, {\bf char} $\ast$argv[])\mbox{}\\ \{\mbox{}\\ \hspace*{2\indentation}{\bf int} i, rc;\mbox{}\\ \hspace*{2\indentation}pthread\_t threads[3];\mbox{}\\ \hspace*{2\indentation}pthread\_attr\_t attr;\mbox{}\\ \mbox{}\\ \hspace*{2\indentation}{$/\ast$\it{} Initialize mutex and condition variable objects $\ast/$}\mbox{}\\ \hspace*{2\indentation}pthread\_mutex\_init(\&count\_mutex, NULL);\mbox{}\\ \hspace*{2\indentation}pthread\_cond\_init (\&count\_threshold\_cv, NULL);\mbox{}\\ \mbox{}\\ \hspace*{2\indentation}{$/\ast$\it{}\mbox{}\\ \hspace*{2\indentation}For portability, explicitly create threads in a joinable state \mbox{}\\ \hspace*{2\indentation}$\ast/$}\mbox{}\\ \hspace*{2\indentation}pthread\_attr\_init(\&attr);\mbox{}\\ \hspace*{2\indentation}pthread\_attr\_setdetachstate(\&attr, PTHREAD\_CREATE\_JOINABLE);\mbox{}\\ \hspace*{2\indentation}pthread\_create(\&threads[0], \&attr, inc\_count, ({\bf void} $\ast$)\&thread\_ids[0]);\mbox{}\\ \hspace*{2\indentation}pthread\_create(\&threads[1], \&attr, inc\_count, ({\bf void} $\ast$)\&thread\_ids[1]);\mbox{}\\ \hspace*{2\indentation}pthread\_create(\&threads[2], \&attr, watch\_count, ({\bf void} $\ast$)\&thread\_ids[2]);\mbox{}\\ \mbox{}\\ \hspace*{2\indentation}{$/\ast$\it{} Wait for all threads to complete $\ast/$}\mbox{}\\ \hspace*{2\indentation}{\bf for} (i = 0; i $<$ NUM\_THREADS; i++) \{\mbox{}\\ \hspace*{4\indentation}pthread\_join(threads[i], NULL);\mbox{}\\ \hspace*{2\indentation}\}\mbox{}\\ \hspace*{2\indentation}printf ({\tt"Main(): Waited on \%d threads. Done.$\backslash$n"}, NUM\_THREADS);\mbox{}\\ \mbox{}\\ \hspace*{2\indentation}{$/\ast$\it{} Clean up and exit $\ast/$}\mbox{}\\ \hspace*{2\indentation}pthread\_attr\_destroy(\&attr);\mbox{}\\ \hspace*{2\indentation}pthread\_mutex\_destroy(\&count\_mutex);\mbox{}\\ \hspace*{2\indentation}pthread\_cond\_destroy(\&count\_threshold\_cv);\mbox{}\\ \hspace*{2\indentation}pthread\_exit (NULL);\mbox{}\\ \mbox{}\\ \}\mbox{}\\ \mbox{}\\ \end{flushleft} \end{document}