%
% This file was automatically produced at Feb 27 2003, 22:51:56 by
% c2latex -c condvar2_sol.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: condvar2\_sol.c\mbox{}\\
$\ast$ DESCRIPTION:\mbox{}\\
$\ast$   Solution for the condvar2.c program.  The inc\_count routine uses a\mbox{}\\
$\ast$   pthread\_cond\_broadcast() routine instead of the pthread\_cond\_signal()\mbox{}\\
$\ast$   routine.\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: 01/07/2003  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  6\mbox{}\\
{\tt \#define} TCOUNT 10\mbox{}\\
{\tt \#define} COUNT\_LIMIT 12\mbox{}\\
\mbox{}\\
{\bf int}     count = 0;\mbox{}\\
{\bf int}     thread\_ids[6] = \{0,1,2,3,4,5\};\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{}\\
\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\_broadcast(\&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*{4\indentation}printf({\tt"$\ast$$\ast$$\ast$Before cond\_wait: thread \%d$\backslash$n"}, $\ast$my\_id);\mbox{}\\
\hspace*{4\indentation}pthread\_cond\_wait(\&count\_threshold\_cv, \&count\_mutex);\mbox{}\\
\hspace*{4\indentation}printf({\tt"$\ast$$\ast$$\ast$Thread \%d Condition signal received.$\backslash$n"}, $\ast$my\_id);\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[6];\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[2], \&attr, watch\_count, ({\bf void} $\ast$)\&thread\_ids[2]);\mbox{}\\
\hspace*{2\indentation}pthread\_create(\&threads[3], \&attr, watch\_count, ({\bf void} $\ast$)\&thread\_ids[3]);\mbox{}\\
\hspace*{2\indentation}pthread\_create(\&threads[4], \&attr, watch\_count, ({\bf void} $\ast$)\&thread\_ids[4]);\mbox{}\\
\hspace*{2\indentation}pthread\_create(\&threads[5], \&attr, watch\_count, ({\bf void} $\ast$)\&thread\_ids[5]);\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{}\\
\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}
