summaryrefslogtreecommitdiff
path: root/docs/tutorials/018/page03.html
blob: c11e0e5b972e503c2af5470728cd3caa9c581f47 (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
<!-- $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 018</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F">

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

<CENTER><B><FONT SIZE=+2>The FIFO Nature of ACE_Token</FONT></B></CENTER>

<P>
<HR WIDTH="100%">
Our Test object is a simple derivative of ACE_Task.  Although we've
certainly used templates in other tutorials, this is the first time
we've created one of our own.
<P>
In a lot of ways, you can think of templates as the sophisticated
cousin of the old C-style pre-processor macros.  With templates,
however, you get better type-checking and much easier debugging.  There
are certainly other benefits but these are my favorites.
<P>
Our template's MUTEX parameter is used to set the mutex type
<i>mutex_t</i>.  That'll be used in svc() so that we can protect
shared resources needed during the processing of data received on our
message queue.
<P>
Note at the bottom how we have to include the <i>cpp</i> file
associated with us.  Most compilers have to see the definition of
templated classes along with their declaration.  You might be tempted,
therefore, to just put the definitions in the header file.  Resist
that temptation because templates are one of the fastest growing areas
of compilers.  Including the definition like we do here leads to long
compile times and overly-large binaries.  With luck, the compilers
will get smarter in the future and we won't need definition
inclusion.  If you've already got them broken out then you'll save
yourself a lot of time!
<HR>
<PRE>
<font color=red>// $Id$</font>

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

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

<font color=red>/* We'll create a simple ACE_Task derivative for testing a couple of
   different locking mechanisms.  We've hidden the open() method to
   force our client into using the run() method instead.

   The naming convention *_T is fairly typical for ACE.  The _T suffix
   on the object name (and it's source files) indicates that this is a
   templated class.  Generally, there is a non-templated class defined
   also such as foobar.h that would be included instead of foobar_T.h.
 */</font>

template &lt;class MUTEX>
class Test_T : public ACE_Task&lt;ACE_MT_SYNCH>
{
public:
  <font color=red>// Allow our derivative to name the class so that we can tell the</font>
  <font color=red>// user what's going on as we test the lock.</font>
  Test_T (const char *name);

  <font color=red>// This will run the entire test.  open() will be called to activate</font>
  <font color=red>// the task's threads.  We then add a number of messages to the</font>
  <font color=red>// queue for svc() to process.</font>
  int run (void);

protected:

  <font color=red>// Activate a few threads</font>
  int open (void *arg = 0);

  <font color=red>// Read some things from the message queue and exercise the lock.</font>
  int svc (void);

  <font color=red>// Send a message block to svc().  If _message is 0 then send a</font>
  <font color=red>// shutdown request (e.g., MB_HANGUP)</font>
  int send (ACE_Message_Block * message = 0);

  <font color=red>// The object's name.  Typically provided by a derivative.</font>
  const char *name_;

  <font color=red>// We want to barrier the svc() methods to give all of the threads a</font>
  <font color=red>// fair chance</font>
  ACE_Barrier barrier_;

  <font color=red>// As each thread enters svc() it will increment this.  While we</font>
  <font color=red>// have a thread id available to us, I wanted a simple value to</font>
  <font color=red>// display in debug messages.</font>
  ACE_Atomic_Op&lt;ACE_Mutex,int> thread_num_;

  <font color=red>// Set our mutex type based on the template parameter.  We then</font>
  <font color=red>// build a guard type based on that type.</font>
  typedef MUTEX mutex_t;
  typedef ACE_Guard&lt;mutex_t> guard_t;

  <font color=red>// Our mutex.  We'll use this in svc() to protect imaginary shared</font>
  <font color=red>// resources.</font>
  mutex_t mutex_;
};

<font color=red>/* Although different compilers differ in their details, almost all of
   them require that you provide the definition of the templated
   object along with the declaration.  With any luck, this will change
   someday & we'll have smaller object files.  Until then, the lines
   below will take care of you.
 */</font>

<font color=blue>#if defined</font> (<font color=purple>ACE_TEMPLATES_REQUIRE_SOURCE</font>)
<font color=blue>#include</font> "<font color=green>Test_T.cpp</font>"
<font color=blue>#endif</font> <font color=red>/* ACE_TEMPLATES_REQUIRE_SOURCE */</font>

<font color=blue>#if defined</font> (<font color=purple>ACE_TEMPLATES_REQUIRE_PRAGMA</font>)
<font color=blue>#pragma</font> <font color=purple>implementation</font> ("<font color=green>Test_T.cpp</font>")
<font color=blue>#endif</font> <font color=red>/* ACE_TEMPLATES_REQUIRE_PRAGMA */</font>

<font color=blue>#endif</font> <font color=red>/* TEST_T_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>