summaryrefslogtreecommitdiff
path: root/docs/tutorials/017/page02.html
blob: 47677ba8fa4f82cbc5882f36dcf55b7f1d496ce4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
<!-- $Id$ -->
<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>// $Id$</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>