Sophie

Sophie

distrib > Mandriva > 10.0-com > i586 > by-pkgid > 21280410b6ea906d791d7a12afae2579 > files > 297

libace5-doc-5.4-2mdk.i586.rpm

<!-- page02.html,v 1.10 2000/03/19 20:09:32 jcej Exp -->
<HTML>
<HEAD>
   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
   <META NAME="Author" CONTENT="James CE Johnson">
   <TITLE>ACE Tutorial 017</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F">

<CENTER><B><FONT SIZE=+2>ACE Tutorial 017</FONT></B></CENTER>

<CENTER><B><FONT SIZE=+2>Using the ACE_Barrier synch object</FONT></B></CENTER>

<P>
<HR WIDTH="100%">
First, lets take a look at the main() routine and how it will use the
Barrier wrapper class.  A simple ACE_Task derivative is used so that
we can perform work in multiple threads.  These threads will use the
barrier to synch in a couple of places.
<P>
Obviously this isn't a very realistic example but you should be able
to get the idea of how to use a Barrier without getting hung up in
application-level details.
<HR>
<PRE>

<font color=red>// page02.html,v 1.10 2000/03/19 20:09:32 jcej Exp</font>

<font color=blue>#include</font> "<font color=green>Barrier_i.h</font>"
<font color=blue>#include</font> "<A HREF="../../../ace/Task.h">ace/Task.h</A>"

<font color=red>/* We'll use a simple Task&lt;> derivative to test our new Barrier
   object.
*/</font>
class Test : public ACE_Task&lt;ACE_NULL_SYNCH>
{
public:

        <font color=red>// Construct the object with a desired thread count</font>
    Test(int _threads);

        <font color=red>// Open/begin the test.  As usual, we have to match the</font>
        <font color=red>// ACE_Task signature.</font>
    int open(void * _unused = 0);

        <font color=red>// Change the threads_ value for the next invocation of open()</font>
    void threads(int _threads);

        <font color=red>// Get the current threads_ value.</font>
    int threads(void);

        <font color=red>// Perform the test</font>
    int svc(void);

protected:
        <font color=red>// How many threads the barrier will test.</font>
    int threads_;

        <font color=red>// The Barrier object we'll use in our tests below</font>
    Barrier barrier_;
};

<font color=red>/* Construct the object & initialize the threads value for open() to
   use.
*/</font>
<font color=#008888>Test::Test</font>(int _threads)
        : threads_(_threads)
{
}

<font color=red>/* As usual, our open() will create one or more threads where we'll do
   the interesting work.
*/</font>
int <font color=#008888>Test::open</font>(void * _unused)
{
    ACE_UNUSED_ARG(_unused);

        <font color=red>// One thing about the barrier:  You have to tell it how many</font>
        <font color=red>// threads it will be synching.  The threads() mutator on my</font>
        <font color=red>// Barrier class lets you do that and hides the implementation</font>
        <font color=red>// details at the same time.</font>
    barrier_.threads(threads_);

        <font color=red>// Activate the tasks as usual...  Like the other cases where</font>
        <font color=red>// we're joining (or waiting for) our threads, we can't use</font>
        <font color=red>// THR_DETACHED.</font>
    return this->activate(THR_NEW_LWP, threads_);
}

void <font color=#008888>Test::threads</font>(int _threads)
{
    threads_ = _threads;
}

int <font color=#008888>Test::threads</font>(void)
{
    return threads_;
}

<font color=red>/* svc() will execute in each thread & do a few things with the
   Barrier we have.
 */</font>
int <font color=#008888>Test::svc</font>(void)
{
    ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\<font color=#008888>tTest::svc</font>() Entry\n</font>"));

        <font color=red>// Initialize the random number generator.  We'll use this to</font>
        <font color=red>// create sleep() times in each thread.  This will help us see</font>
        <font color=red>// if the barrier synch is working.</font>
    ACE_Time_Value now(<font color=#008888>ACE_OS::gettimeofday</font>());
    ACE_RANDR_TYPE seed = now.usec();
    <font color=#008888>ACE_OS::srand</font>(seed);
    int delay;

        <font color=red>// After saying hello above, sleep for a random amount of time</font>
        <font color=red>// from 1 to 6 seconds.  That will cause the next message</font>
        <font color=red>// "<font color=green>Entering wait()</font>" to be staggered on the output as each</font>
        <font color=red>// thread's sleep() returns.</font>
    delay = <font color=#008888>ACE_OS::rand_r</font>(seed)%5;
    <font color=#008888>ACE_OS::sleep</font>(abs(delay)+1);

        <font color=red>// When executing the app you should see these messages</font>
        <font color=red>// staggered in an at-most 6 second window.  That is, you</font>
        <font color=red>// won't likely see them all at once.</font>
    ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\<font color=#008888>tTest::svc</font>() Entering wait()\n</font>"));

        <font color=red>// All of the threads will now wait at this point.  As each</font>
        <font color=red>// thread finishes the sleep() above it will join the waiters.</font>
    if( barrier_.wait() == -1 )
    {
        ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\tbarrier_.wait() failed!\n</font>"));
        return 0;
    }

        <font color=red>// When all threads have reached wait() they will give us this</font>
        <font color=red>// message.  If you execute this, you should see all of the</font>
        <font color=red>// "<font color=green>Everybody together</font>" messages at about the same time.</font>
    ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\<font color=#008888>tTest::svc</font>() Everybody together?\n</font>"));

        <font color=red>// Now we do the sleep() cycle again...</font>
    delay = <font color=#008888>ACE_OS::rand_r</font>(seed)%5;
    <font color=#008888>ACE_OS::sleep</font>(abs(delay)+1);

        <font color=red>// As before, these will trickle in over a few seconds.</font>
    ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\<font color=#008888>tTest::svc</font>() Entering done()\n</font>"));

        <font color=red>// This time we call done() instead of wait().  done()</font>
        <font color=red>// actually invokes wait() but before returning here, it will</font>
        <font color=red>// clean up a few resources.  The goal is to prevent carrying</font>
        <font color=red>// around objects you don't need.</font>
    if( barrier_.done() == -1 )
    {
        ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\tbarrier_.done() failed!\n</font>"));
        return 0;
    }

        <font color=red>// Since done() invokes wait() internally, we'll see this</font>
        <font color=red>// message from each thread simultaneously</font>
    ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\<font color=#008888>tTest::svc</font>() Is everyone still here?\n</font>"));

        <font color=red>// A final sleep()</font>
    delay = <font color=#008888>ACE_OS::rand_r</font>(seed)%5;
    <font color=#008888>ACE_OS::sleep</font>(abs(delay)+1);

        <font color=red>// These should be randomly spaced like all of the other</font>
        <font color=red>// post-sleep messages.</font>
    ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\<font color=#008888>tTest::svc</font>() Chaos and anarchy for all!\n</font>"));

    return(0);
}

<font color=red>/* Our test application...
 */</font>
int main(int, char**)
{
        <font color=red>// Create the test object with 10 threads</font>
    Test test(10);

        <font color=red>// and open it to test the barrier.</font>
    test.open();
        <font color=red>// Now wait for them all to exit.</font>
    test.wait();

        <font color=red>// Re-open the Test object with just 5 threads</font>
    test.threads(5);
    test.open();
        <font color=red>// and wait for them to complete also.</font>
    test.wait();

    return(0);
}
</PRE>
<P><HR WIDTH="100%">
<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page03.html">Continue This Tutorial</A>]</CENTER>