summaryrefslogtreecommitdiff
path: root/docs/tutorials/018/page03.html
blob: e94b8b9c84494469d8836ad37c57c46ffa75e751 (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
<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> "<font color=green>ace/Task.h</font>"

<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</font>
        <font color=red>// the 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</font>
        <font color=red>// activate the task's threads.  We then add a number of</font>
        <font color=red>// messages to the 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</font>
        <font color=red>// lock.</font>
    int svc( void );
        <font color=red>// Send a message block to svc().  If _message is 0 then send</font>
        <font color=red>// a 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</font>
        <font color=red>// threads a fair chance</font>
    ACE_Barrier  barrier_;

        <font color=red>// As each thread enters svc() it will increment this.  While</font>
        <font color=red>// we have a thread id available to us, I wanted a simple</font>
        <font color=red>// value to 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</font>
        <font color=red>// then 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</font>
        <font color=red>// shared 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>