summaryrefslogtreecommitdiff
path: root/docs/tutorials/010/page02.html
blob: 75d7b9984baeff1072054bb9f41fc1aafe8d5d41 (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
<HTML>
<HEAD>
   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
   <META NAME="Author" CONTENT="James CE Johnson">
   <TITLE>ACE Tutorial 010</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F">

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

<CENTER><B><FONT SIZE=+2>Passing chunks of data through an ACE_Message_Queue</FONT></B></CENTER>


<P>
<HR WIDTH="100%">

We'll look first at <A HREF="message_queue.cpp">main()</A>.
<P>

<HR WIDTH="100%">
<PRE>

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

<font color=red>/*
   To illustrate the ACE_Message_Queue, we use a derivative of ACE_Task&lt;>.  We
   also derive from ACE_Message_Block to show that we don't have memory leaks. 
 */</font>
<font color=blue>#include</font> "<font color=green>task.h</font>"
<font color=blue>#include</font> "<font color=green>block.h</font>"

int run_test( int iterations, int threads )
{
  <font color=red>/*
     Create and open an instance of our Task object.  I've overridden the
     open() method to make it look more like other ACE objects. 
   */</font>
  Task task;

  if (task.open (threads) == -1)
  {
    ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>open</font>"), -1);
  }

  <font color=red>/*
     Give the threads a moment to open.  This isn't really necessary but if we
     don't we find that all of our blocks are constructed and enqueued before
     any of the threads get created. Basically, the sleep() makes the output
     look more interesting.       
   */</font>
  <font color=#008888>ACE_OS::sleep</font> (ACE_Time_Value (1));

  int i;
  for (i = 0; i &lt; iterations; ++i)
  {
    <font color=red>/*
       Create a new message block to hold our data.  Here, we ask for a block
       that has 128 bytes of data space. 
     */</font>
    Block *message = new Block (128);

    <font color=red>/*
       Grab the "<font color=green>write pointer</font>".  This is a pointer into the data area where we 
       can write our data.  After writting the data you have to increment the
       wr_ptr() so that subsequent writes won't clobber what you've put there. 
     */</font>
    <font color=#008888>ACE_OS::sprintf</font> (message->wr_ptr (), "<font color=green>This is message %d.</font>", i);
    message->wr_ptr (strlen (message->rd_ptr ()));

    <font color=red>/*
       Put the message block into the queue.  One of the threads in the Task
       object will pick up the block and "<font color=green>do work</font>" on it. 
     */</font>
    if (task.putq (message) == -1)
    {
      break;
    }
  }

  <font color=red>/*
     Once we're done, we have to signal the Task objects to shut down. There
     are several choices including: - Send a message of zero length - Send a
     message with a special content I don't like these choices because they're
     likely to interfere with application logic.  Instead, I use the message
     type feature to send a message of type "<font color=green>hangup</font>".  The default type is
     MB_DATA, so when the tasks get a MB_HANGUP type, they know to go away. 
   */</font>
  Block *message = new Block ();
  message->msg_type (<font color=#008888>ACE_Message_Block::MB_HANGUP</font>);
  task.putq (message);

  <font color=red>/*
     Wait for the threads in our task object to go away. 
   */</font>
  task.wait ();
  
  return(0);
}

int main (int argc, char *argv[])
{
  <font color=red>/*
     Set the number of iterations through our putq() loop and the number of
     threads to use in our Task&lt;> derivative. 
   */</font>
  int iterations = argc > 1 ? atoi (argv[1]) : 9;
  int threads = argc > 2 ? atoi (argv[2]) : 2;
  
  (void)run_test(iterations,threads);

  ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Application exiting\n</font>"));
  
  return(0);
}
</PRE>
<HR WIDTH="100%">
<P>
This looks a lot like our thread-pool server and it even does some things
better.  In particular, I've scoped the Task object so that it's destructor
will have a chance to get called before the application exits.
Notice how we write actual data into the message block though.  In the thread-pool
server we just provided a pointer.  Writting the data is actually a more correct
way of doing things since you don't get into strange pointer casting situations.
What if you want to put complex objects into the message block though?  We'll do
that in the next tutorial, let's stick with the basics first.
<P>
On the next page we'll take a look at our Block object...
<P>
<P><HR WIDTH="100%">
<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page03.html">Continue This Tutorial</A>]</CENTER>