summaryrefslogtreecommitdiff
path: root/docs/tutorials/017/page03.html
blob: ee86eed3a761f614cdae309da58a102fafa1e3de (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
<!-- $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%">
The Barrier class used by the test task is a simple wrapper around
ACE_Barrier.  One of the things about ACE_Barrier is that you have to
tell it how many threads it will be managing.  Since that number
usually isn't known when you create your Task derivative, you have to
dynamically allocate the ACE_Barrier.  My Barrier wrapper takes care
of that for you and even provides for a clean way to delete the
ACE_Barrier instance if you want to save a few bytes.
<P>
An interesting extension of this Barrier class would be to wrap it up
in a smart pointer.  You could then have the Barrier destructor invoke
wait() as a now-protected method.  The result would allow you to treat
the Barrier object almost as a "synchronization guard".
<HR>
<PRE>
<font color=red>// $Id$</font>

<font color=blue>#ifndef</font> <font color=purple>BARRIER_H</font>
<font color=blue>#define</font> <font color=purple>BARRIER_H</font>

<font color=blue>#include</font> "<A HREF="../../../ace/Synch.h">ace/Synch.h</A>"

<font color=red>/* Barrier is a simple wrapper for the ACE_Barrier synchronization
   class.  The ACE_Barrier is already pretty easy to use but I thought
   I'd wrap it up to create just a bit more abstraction at the
   application level.  */</font>

class Barrier
{
public:
  <font color=red>// Basic constructor and destructor.  If you only need to synch the</font>
  <font color=red>// start of your threads, you can safely delete your Barrier object</font>
  <font color=red>// after invoking done().  Of course, you should be careful to only</font>
  <font color=red>// delete the object once!</font>
  Barrier (void);
  ~Barrier (void);

  <font color=red>// Set and get the number of threads that the barrier will manage.</font>
  <font color=red>// If you add or remove threads to your application at run-time you</font>
  <font color=red>// can use the mutator to reflect that change.  Note, however, that</font>
  <font color=red>// you can only do that from the thread which first created the</font>
  <font color=red>// Barrier.  (This is a limitation of my Barrier object, not the</font>
  <font color=red>// ACE_Barrier.)  The optional _wait parameter will cause wait() to</font>
  <font color=red>// be invoked if there is already a valid threads value.</font>
  int threads (u_int threads, int wait = 0);
  u_int threads (void);

  <font color=red>// Wait for all threads to reach the point where this is invoked.</font>
  <font color=red>// Because of the snappy way in which ACE_Barrier is implemented,</font>
  <font color=red>// you can invoke these back-to-back with no ill-effects.</font>
  int wait (void);

  <font color=red>// done() will invoke wait().  Before returning though, it will</font>
  <font color=red>// delete the barrier_ pointer below to reclaim some memory.</font>
  int done (void);

  <font color=red>// Reset the owning thread of the barrier.</font>
  void owner( ACE_thread_t _owner );

protected:
  <font color=red>// The number of threads we're synching</font>
  ACE_Atomic_Op&lt;ACE_Mutex, u_int> threads_;

  <font color=red>// The ACE_Barrier that does all of the work</font>
  ACE_Barrier *barrier_;

  <font color=red>// If we mutate the number of threads we have to do some black magic </font>
  <font color=red>// to make sure there isn't a memory leak.  These two member</font>
  <font color=red>// variables are a part of that magic.</font>
  ACE_Barrier *new_barrier_;
  ACE_Mutex    barrier_mutex_;

  <font color=red>// The thread which created the Barrier in the first place.  Only</font>
  <font color=red>// this thread can change the threads_ value.</font>
  ACE_thread_t owner_;

  <font color=red>// An internal method that constructs the barrier_ as needed.</font>
  int make_barrier (int wait);
};

<font color=blue>#endif</font> <font color=red>/* BARRIER_H */</font>
</PRE>
<P><HR WIDTH="100%">
<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page04.html">Continue This Tutorial</A>]</CENTER>