summaryrefslogtreecommitdiff
path: root/docs/tutorials/017/page04.html
blob: aced1b672174c0682f1f9935f494acadbb849212 (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
<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%">
The Barrier implementation is quite simple.  The threads() mutator
took a couple of tries to get right.  In particular, be sure you know
when to apply the _wait paramter and when not to!  In fact, the
requirement that only the "owning" thread can change the thread count
is rather limiting.  A more appropriate solution would allow any
thread to safely change the count but that would require more complex
locking that is just a bit more than what I wanted to present here.
<HR>
<PRE>

<font color=red>// $Id$</font>

<font color=blue>#include</font> "<font color=green>Barrier_i.h</font>"

<font color=red>/* Initialize the threads_ count to zero and the barrier_ pointer to a
   safe value.  At the same time, we remember the thread that created
   us so that we can allow it to change the thread count.
*/</font>
<font color=#008888>Barrier::Barrier</font>(void)
   : threads_(0)
    ,barrier_(0)
{
    owner_ = <font color=#008888>ACE_OS::thr_self</font>();
}

<font color=red>/* Ensure that barrier_ get's deleted so that we don't have a memory leak.
 */</font>
<font color=#008888>Barrier::~Barrier</font>(void)
{
    delete barrier_;
}

<font color=red>// Report on the number of threads.</font>
u_int <font color=#008888>Barrier::threads</font>(void)
{
    return threads_.value();
}

<font color=red>/* Allow the owning thread to (re)set the number of threads.
   make_barrier() is called because it will wait() if we were already
   configured.  Typical usage would be for the worker threads to
   wait() while the primary (eg -- owner) thread adjusts the thread
   count.

   For instance:
       In the worker threads:
           if( myBarrier.threads() != current_thread_count )
               myBarrier.wait();

       In the primary thread:
           if( myBarrier.threads() != current_thread_count )
               myBarrier.threads( current_thread_count, 1 );
 */</font>
int <font color=#008888>Barrier::threads</font>( u_int _threads, int _wait )
{
    if( <font color=#008888>ACE_OS::thr_self</font>() != owner_ )
    {
        return -1;
    }

    threads_ = _threads;
    
    return make_barrier(_wait);
}

<font color=red>/* Wait for all threads to synch if the thread count is valid.  Note
   that barrier_ will be 0 if the threads() mutator has not been
   invoked.
*/</font>
int <font color=#008888>Barrier::wait</font>(void)
{
    if( ! barrier_ )
    {
        return -1;
    }

    return barrier_->wait();
}

<font color=red>/* Wait for all threads to synch.  As each thread passes wait(), it
   will decrement our thread counter.  (That is why we had to make
   threads_ an atomic op.)  When the last thread decrements the
   counter it will also delete the ACE_Barrier & free up a little
   memory.
*/</font>
int <font color=#008888>Barrier::done</font>(void)
{
    if( this->wait() == -1 )
    {
        return -1;
    }

    --threads_;

    if( ! threads_.value() )
    {
        delete barrier_;
        barrier_ = 0;
    }

    return 0;
}

<font color=red>/* This will build the actual barrier.  I broke this code out of the
   threads() mutator in case it might be useful elsewhere.
   If a barrier already exists, we will wait for all threads before
   creating a new one.  This trait is what allows the threads mutator
   to be used as shown above.
 */</font>
int <font color=#008888>Barrier::make_barrier</font>( int _wait )
{
        <font color=red>// Wait for and delete any existing barrier.</font>
    if( barrier_ )
    {
        if( _wait )
        {
            barrier_->wait();
        }
        delete barrier_;
    }

        <font color=red>// Ensure we have a valid thread count.</font>
    if( ! threads_.value() )
    {
        return -1;
    }

        <font color=red>// Create the actual barrier.  Note that we initialize it with </font>
        <font color=red>// threads_.value() to set its internal thread count.  If the</font>
        <font color=red>// 'new' fails we will return -1 to the caller.</font>
    ACE_NEW_RETURN(barrier_,ACE_Barrier(threads_.value()),-1);

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