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

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

<CENTER><B><FONT SIZE=+2>Passing non-trivial data through an ACE_Message_Queue</FONT></B></CENTER>


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

Our <A HREF="task.cpp">Task</A> object definition.  As with message_queue.cpp,
I've only commented the changes.
<P>

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

#include "task.h"
#include "block.h"
#include "data.h"

Task::Task (void)
: barrier_ (0)
{
  ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task ctor 0x%x\n", (void *) this));
}

Task::~Task (void)
{
  ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task dtor 0x%x\n", (void *) this));

  ACE_Message_Block *message;
  this->getq (message);
  message->release ();

  delete barrier_;
}

int Task::open (int threads)
{
  barrier_ = new ACE_Barrier (threads);
  return this->activate (THR_NEW_LWP, threads);
}
int Task::close (u_long flags)
{
  ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task close 0x%x\n", (void *) this));
  return inherited::close (flags);
}

int Task::svc (void)
{
  this->barrier_->wait ();

  ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task 0x%x starts in thread %d\n", (void *) this, ACE_Thread::self ()));

  ACE_Message_Block *message;
  while (1)
  {
    if (this->getq (message) == -1)
    {
      ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "getq"), -1);
    }

    if (message->msg_type () == ACE_Message_Block::MB_HANGUP)
    {
      this->putq (message);

      break;
    }

    const char *cp = message->rd_ptr ();
    message->rd_ptr (strlen (cp) + 1);  // Don't forget to skip the NULL we
                                        // inserted

    ACE_DEBUG ((LM_DEBUG, "(%P|%t) Block 0x%x contains (%s)\n", (void *) message, cp));

    /*
       Create a Data object into which we can extract the message block
       contents. 
     */
    Data data;
    /*
       Use the rd_ptr() to access the message block data.  Note that we've
       already moved it past the text string in the block. 
     */
    ACE_OS::memmove ((char *) &data, message->rd_ptr (), sizeof (data));
    message->rd_ptr (sizeof (data));  // Move the rd_ptr() beyond the data.

    /*
       Invoke a couple of method calls on the object we constructed. 
     */
    data.who_am_i ();
    data.what_am_i ();

    /*
       An alternate approach:

       Data * data;
       data = (Data *)message->rd_ptr();
       data->who_am_i();
       data->what_am_i();
       message->rd_ptr(sizeof(Data));

       Even though this cuts down on the number of copies & constructions, I'm
       not real fond of it.  You can get into trouble in a hurry by treating
       memory blocks as multiple data types... 
     */


    ACE_OS::sleep (ACE_Time_Value (0, 5000));

    message->release ();
  }

  return (0);
}
</PRE>
<HR WIDTH="100%">
<P>
Notice how we had to create a temporary Data object to copy the stuff out
of the message block?  Again, if there were non-trivial ctor/dtors involved
then this wouldn't work at all.
<P>
<HR WIDTH="100%">

<CENTER>[<A HREF="..">Tutorial Index</A>] [<A HREF="page04.html">Continue
This Tutorial</A>]</CENTER>

</BODY>
</HTML>