#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>.
# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/016'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode       name
# ------ ---------- ------------------------------------------
#    422 -rw-rw-r-- hdr
#     51 -rw-rw-r-- bodies
#   2905 -rw-rw-r-- page01.pre
#   1349 -rw-rw-r-- page02.pre
#    247 -rw-rw-r-- page03.pre
#    310 -rw-rw-r-- page04.pre
#    606 -rw-rw-r-- page05.pre
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
     && ($dir/gettext --version >/dev/null 2>&1)
  then
    set `$dir/gettext --version 2>&1`
    if test "$3" = GNU
    then
      gettext_dir=$dir
    fi
  fi
  if test "$locale_dir" = FAILED && test -f $dir/shar \
     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
  then
    locale_dir=`$dir/shar --print-text-domain-dir`
  fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
  echo=echo
else
  TEXTDOMAINDIR=$locale_dir
  export TEXTDOMAINDIR
  TEXTDOMAIN=sharutils
  export TEXTDOMAIN
  echo="$gettext_dir/gettext -s"
fi
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
  shar_touch=touch
else
  shar_touch=:
  echo
  $echo 'WARNING: not restoring timestamps.  Consider getting and'
  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 1231235999 $$.touch
#
if mkdir _sh00306; then
  $echo 'x -' 'creating lock directory'
else
  $echo 'failed to create lock directory'
  exit 1
fi
# ============= hdr ==============
if test -f 'hdr' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'hdr' '(file already exists)'
else
  $echo 'x -' extracting 'hdr' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'hdr' &&
<HTML>
<HEAD>
X   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
X   <META NAME="Author" CONTENT="James CE Johnson">
X   <TITLE>ACE Tutorial 016</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F">
X
<CENTER><B><FONT SIZE=+2>ACE Tutorial 016</FONT></B></CENTER>
X
<CENTER><B><FONT SIZE=+2>Making ACE_Condition easier to use</FONT></B></CENTER>
X
<P>
<HR WIDTH="100%">
SHAR_EOF
  $shar_touch -am 03191459100 'hdr' &&
  chmod 0664 'hdr' ||
  $echo 'restore of' 'hdr' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'hdr:' 'MD5 check failed'
34600093c989939b7a2a6806f2b18f22  hdr
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`"
    test 422 -eq "$shar_count" ||
    $echo 'hdr:' 'original size' '422,' 'current size' "$shar_count!"
  fi
fi
# ============= bodies ==============
if test -f 'bodies' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'bodies' '(file already exists)'
else
  $echo 'x -' extracting 'bodies' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'bodies' &&
PAGE=2
Condition_i.h
Condition_i.cpp
condition.cpp
SHAR_EOF
  $shar_touch -am 1029153398 'bodies' &&
  chmod 0664 'bodies' ||
  $echo 'restore of' 'bodies' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'bodies:' 'MD5 check failed'
53b96616ae101b38fd1e30b2ab8707a2  bodies
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`"
    test 51 -eq "$shar_count" ||
    $echo 'bodies:' 'original size' '51,' 'current size' "$shar_count!"
  fi
fi
# ============= page01.pre ==============
if test -f 'page01.pre' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'page01.pre' '(file already exists)'
else
  $echo 'x -' extracting 'page01.pre' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'page01.pre' &&
The ACE framework has quite a few objects for syncronizing your
threads and even processes.  We've mentioned a few in passing already:
X ACE_Thread_Mutex and ACE_Barrier for instance.
<P>
Another interesting one is the ACE_Condition template.  By using an
ACE_Condition you can have your code wait for an arbitrary condition
to occur.  That condition is "embodied" in a variable of your choice.
That variable can, in turn, be any data type you wish.  This makes
ACE_Condition much more flexible than a simple mutex, barrier or
semaphore.
<P>
In this tutorial, I'll create a wrapper class around the ACE_Condition
and the assorted housekeeping items necessary to make it work.  I'll
use a simple integer as the condition variable but keep in mind that
you can use any data type you want.
<P>
Kirthika's abstract:
<ul>
An ACE_Condition class is a synchronisation mechanism employed in
situations where one or more threads cannot access the shared resource
unless some 'condition' becomes true. The ACE_Condition is associated
with a Mutex-lock which is released before blocking internally in the
wait call. Once the blocked thread is signaled to wake up again it
internally re-acquires the lock before checking the condition.
Unless the condition is true and it has the lock, it cant go ahead.
Once the shared resource is freed, a signal is sent to the waiting
threads which can now contend for the lock and access the resource.
<P>
Pizza-delivery metaphor: (courtesy Dr.Schmidt)
<ul>
Pizza delivery boy --  thread<br>
keys to delivery van -- mutex-lock<br>
pizza ready for delivery -- condition<br>
</Ul>
Situation: <br>
<ul>
Five pizza delivery boys use the same van. While the van is
unavailable, the boys go to sleep. When the van returns and the keys
are returned, the current user of the van nudges the other sleeping boys
to wake up and fight for the keys. Once the keys are obtained and the
pizza
is ready and out of the kitchen, the boy with the pizza and the keys can
now deliver it.
</ul>
<P>
This tutorial makes use of  a wrapper class around the ACE_Condition and
uses a integer value as the condition. The four kinds of condition
implemented
are: !=, >=, <=, == by using C++ operator overloading. Guards are used
within
the methods to make sure that the method is thread-safe. Once the thread
completes
its job, it broadcasts to the waiting on it.
<P>
An ACE_Task is used to stress test the various conditions.
A test object is created for each condition and the main thread waits
until the condition becomes true. For instance: <= condition:
Five threads are spwaned which in turn increment the condition
variable, which is initialised to 1 by 2. Remember that you are waiting
on
the <= condition. So once 3 threads have been thru it, the value becomes
6
and the condition becomes true!
<P>
This simple example shows us how to program and use the Condition
variable for
synchronisation.
</ul>
SHAR_EOF
  $shar_touch -am 03191459100 'page01.pre' &&
  chmod 0664 'page01.pre' ||
  $echo 'restore of' 'page01.pre' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'page01.pre:' 'MD5 check failed'
a6fd2e6607a2b96c93d8a829a1fb53cc  page01.pre
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`"
    test 2905 -eq "$shar_count" ||
    $echo 'page01.pre:' 'original size' '2905,' 'current size' "$shar_count!"
  fi
fi
# ============= page02.pre ==============
if test -f 'page02.pre' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'page02.pre' '(file already exists)'
else
  $echo 'x -' extracting 'page02.pre' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'page02.pre' &&
We'll look first at the declaration of the wrapper class.
<P>
The way you use ACE_Condition is something like this:
<UL>
<LI>First, the setup...
<UL>
<LI>Create a variable using your choice of data types
<LI>Create a mutex that will provide thread-safe access to that
variable
<LI>Create an ACE_Condition that uses the mutex
</UL>
<P>
<LI>Waiting for the condition...
<UL>
<PRE>
the_mutex.acquire();
while( the_variable != some_desired_state_or_value )
X  the_condition.wait();
the_mutex.release();
</PRE>
Note that when <i>the_condition</i> is created, it must be given a
reference to the mutex.  That's because the wait() method will release
the mutex before waiting and reacquire it after being signaled.
</UL>
<P>
<LI>Setting the condition...
<UL>
<PRE>
the_mutex.acquire();
the_variable = some_new_value_or_state;
the_condition.signal() <i>OR</i> the_condition.broadcast()
</pre>
</UL>
</UL>
<P>
The problem I have is remembering to setup everything and co-ordinate
the locking, waiting and signaling.  Even if I remember it all
correctly it just makes my application code more complex than it
should be.
<P>
To help out with that, I've created the class below to encapsulate the
three elements necessary for the condition to work.  I've then added
methods for manipulation of the condition variable and waiting for the
condition to occur.
<HR>
SHAR_EOF
  $shar_touch -am 03191459100 'page02.pre' &&
  chmod 0664 'page02.pre' ||
  $echo 'restore of' 'page02.pre' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'page02.pre:' 'MD5 check failed'
6c1b6e8f9597666558619d52c87be915  page02.pre
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`"
    test 1349 -eq "$shar_count" ||
    $echo 'page02.pre:' 'original size' '1349,' 'current size' "$shar_count!"
  fi
fi
# ============= page03.pre ==============
if test -f 'page03.pre' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'page03.pre' '(file already exists)'
else
  $echo 'x -' extracting 'page03.pre' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'page03.pre' &&
Ok, now we'll take a look at the definition of the class.  You already
know how to use an ACE_Condition & it's not really that difficult.
Still, imagine how much more cluttered your code would be if it had to
include the mess I've got below!
<HR>
SHAR_EOF
  $shar_touch -am 03191459100 'page03.pre' &&
  chmod 0664 'page03.pre' ||
  $echo 'restore of' 'page03.pre' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'page03.pre:' 'MD5 check failed'
bdf2bed6845300288a14d1a41f6ef8a6  page03.pre
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`"
    test 247 -eq "$shar_count" ||
    $echo 'page03.pre:' 'original size' '247,' 'current size' "$shar_count!"
  fi
fi
# ============= page04.pre ==============
if test -f 'page04.pre' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'page04.pre' '(file already exists)'
else
  $echo 'x -' extracting 'page04.pre' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'page04.pre' &&
We finally get to the main() application.  I create a simple Task
derivative that will serve as a baseclass for other objects that test
specific functions of the Condition class.  Notice how easy it is to
integrate a Condition into the application without keeping track of
three related member variables.
<HR>
SHAR_EOF
  $shar_touch -am 03191459100 'page04.pre' &&
  chmod 0664 'page04.pre' ||
  $echo 'restore of' 'page04.pre' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'page04.pre:' 'MD5 check failed'
a2b2c42216f88e006a18d37adcb31c1d  page04.pre
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`"
    test 310 -eq "$shar_count" ||
    $echo 'page04.pre:' 'original size' '310,' 'current size' "$shar_count!"
  fi
fi
# ============= page05.pre ==============
if test -f 'page05.pre' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'page05.pre' '(file already exists)'
else
  $echo 'x -' extracting 'page05.pre' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'page05.pre' &&
And that's all...
<P>
For general use, it would make sense to convert Condition into a
template and get rid of some of the operators that don't make sense.
Using an integer as the condition type probably isn't realistic since
you could just use a semaphore or barrier for that case.  Still, the
Tutorial shows the basics and provides a foundation on which you can
create a more useful class for your application.
<P>
<UL>
<LI><A HREF="Condition_i.h">Condition_i.h</A>
<LI><A HREF="Condition_i.cpp">Condition_i.cpp</A>
<LI><A HREF="condition.cpp">condition.cpp</A>
<LI><A HREF="Makefile">Makefile</A>
</UL>
SHAR_EOF
  $shar_touch -am 03191459100 'page05.pre' &&
  chmod 0664 'page05.pre' ||
  $echo 'restore of' 'page05.pre' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'page05.pre:' 'MD5 check failed'
3926547773016bf56d809fae9170625e  page05.pre
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`"
    test 606 -eq "$shar_count" ||
    $echo 'page05.pre:' 'original size' '606,' 'current size' "$shar_count!"
  fi
fi
rm -fr _sh00306
exit 0
