summaryrefslogtreecommitdiff
path: root/docs/tutorials
diff options
context:
space:
mode:
authorjcej <jcej@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1999-01-24 21:06:55 +0000
committerjcej <jcej@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1999-01-24 21:06:55 +0000
commitce853db6d67366ac2713201d9a5780b86b1f8bd0 (patch)
tree443d1796707a72c5168266c6e3a63f07326635e5 /docs/tutorials
parent918c01f502e675ed377bd8e2d94d659867ef86f7 (diff)
downloadATCD-ce853db6d67366ac2713201d9a5780b86b1f8bd0.tar.gz
*** empty log message ***
Diffstat (limited to 'docs/tutorials')
-rw-r--r--docs/tutorials/004/client.cpp12
-rw-r--r--docs/tutorials/004/combine.shar28
-rw-r--r--docs/tutorials/004/page01.html20
-rw-r--r--docs/tutorials/005/Makefile4
-rw-r--r--docs/tutorials/005/client_acceptor.h2
-rw-r--r--docs/tutorials/005/client_handler.cpp9
-rw-r--r--docs/tutorials/005/client_handler.h10
-rw-r--r--docs/tutorials/005/combine.shar30
-rw-r--r--docs/tutorials/005/page02.html4
-rw-r--r--docs/tutorials/005/page03.html4
-rw-r--r--docs/tutorials/005/page04.html10
-rw-r--r--docs/tutorials/005/page05.html9
-rw-r--r--docs/tutorials/005/page06.html4
-rw-r--r--docs/tutorials/005/server.cpp2
-rw-r--r--docs/tutorials/007/client_handler.cpp10
-rw-r--r--docs/tutorials/007/combine.shar31
-rw-r--r--docs/tutorials/007/page01.html6
-rw-r--r--docs/tutorials/007/page06.html10
-rw-r--r--docs/tutorials/007/page08.html2
-rw-r--r--docs/tutorials/007/thread_pool.cpp2
-rw-r--r--docs/tutorials/008/combine.shar33
-rw-r--r--docs/tutorials/008/page04.html7
-rw-r--r--docs/tutorials/009/page03.html3
-rw-r--r--docs/tutorials/010/Makefile11
-rw-r--r--docs/tutorials/010/block.h18
-rw-r--r--docs/tutorials/010/combine.shar534
-rw-r--r--docs/tutorials/010/page01.html35
-rw-r--r--docs/tutorials/010/page02.html78
-rw-r--r--docs/tutorials/010/page03.html37
-rw-r--r--docs/tutorials/010/page04.html62
-rw-r--r--docs/tutorials/010/page05.html114
-rw-r--r--docs/tutorials/010/page06.html14
-rw-r--r--docs/tutorials/010/page07.html12
-rw-r--r--docs/tutorials/011/Makefile11
-rw-r--r--docs/tutorials/011/combine.shar476
-rw-r--r--docs/tutorials/011/page01.html9
-rw-r--r--docs/tutorials/011/page02.html141
-rw-r--r--docs/tutorials/011/page03.html110
-rw-r--r--docs/tutorials/011/page04.html35
-rw-r--r--docs/tutorials/011/page05.html13
-rw-r--r--docs/tutorials/011/page06.html14
-rw-r--r--docs/tutorials/012/Makefile11
-rw-r--r--docs/tutorials/012/block.h (renamed from docs/tutorials/012/data.h)73
-rw-r--r--docs/tutorials/012/combine.shar451
-rw-r--r--docs/tutorials/012/message_queue.cpp3
-rw-r--r--docs/tutorials/012/page01.html8
-rw-r--r--docs/tutorials/012/page02.html51
-rw-r--r--docs/tutorials/012/page03.html45
-rw-r--r--docs/tutorials/012/page04.html76
-rw-r--r--docs/tutorials/012/page05.html142
-rw-r--r--docs/tutorials/012/page06.html11
-rw-r--r--docs/tutorials/012/task.cpp3
-rw-r--r--docs/tutorials/012/work.h76
53 files changed, 2256 insertions, 670 deletions
diff --git a/docs/tutorials/004/client.cpp b/docs/tutorials/004/client.cpp
index 90a40fafb79..88ddb0850ed 100644
--- a/docs/tutorials/004/client.cpp
+++ b/docs/tutorials/004/client.cpp
@@ -42,7 +42,7 @@ public:
/*
This is where the coolness lies. Most C++ folks are familiar
- with "cout << some-data". It's a very handy and easy way to
+ with "cout << some-data." It's a very handy and easy way to
toss data around. By adding these method calls, we're able
to do the same thing with a socket connection.
*/
@@ -223,13 +223,13 @@ int main (int argc, char *argv[])
/*
Use the basic constructor since the other isn't really very safe.
*/
- Client server;
+ Client peer;
/*
Open the server connection. Notice how this is simpler than Tutorial 3
since we only have to provide a host name and port value.
*/
- if( server.open(server_host,server_port) == -1 )
+ if( peer.open(server_host,server_port) == -1 )
{
ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), -1);
}
@@ -240,12 +240,12 @@ int main (int argc, char *argv[])
Tell the server which iteration we're on. No more mucking aroudn with
sprintf at this level! It's all hidden from us.
*/
- server << "message = " << i+1;
+ peer << "message = " << i+1;
/*
Everything OK?
*/
- if ( server.error() )
+ if ( peer.error() )
{
ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "send"), -1);
}
@@ -255,7 +255,7 @@ int main (int argc, char *argv[])
}
}
- if (server.close () == -1)
+ if (peer.close () == -1)
{
ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "close"), -1);
}
diff --git a/docs/tutorials/004/combine.shar b/docs/tutorials/004/combine.shar
index e77f85b0df4..ae15fa1d7d7 100644
--- a/docs/tutorials/004/combine.shar
+++ b/docs/tutorials/004/combine.shar
@@ -3,7 +3,7 @@
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
-# Made on 1999-01-17 14:31 EST by <jcej@chiroptera.tragus.org>.
+# Made on 1999-01-24 11:50 EST by <jcej@chiroptera.tragus.org>.
# Source directory was `/var/home/jcej/projects/ACE_wrappers/docs/tutorials/004'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
@@ -14,7 +14,7 @@
# 591 -rw-rw-r-- hdr
# 18 -rw-rw-r-- bodies
# 702 -rw-rw-r-- page01.pre
-# 963 -rw-rw-r-- page01.pst
+# 961 -rw-rw-r-- page01.pst
#
save_IFS="${IFS}"
IFS="${IFS}:"
@@ -61,7 +61,7 @@ else
fi
rm -f 1231235999 $$.touch
#
-if mkdir _sh00408; then
+if mkdir _sh21744; then
$echo 'x -' 'creating lock directory'
else
$echo 'failed to create lock directory'
@@ -146,21 +146,21 @@ was born.)
Kirthika says:
<UL>
The cool thing about this "cooler" client is how we use a C++ trick for
-streaming incoming data by using the operator<<() metod. Also the
+streaming incoming data by using the operator<<() method. Also the
Connector portion is wrapped in the open() method which now takes in the
-server hostname and port. The result is a cleaner-looking client which
-successfully interacts with the server, when connection is established.
+server hostname and port. The result is a cleaner looking client which
+successfully interacts with the server when connection is established.
</UL>
<HR WIDTH="100%">
SHAR_EOF
- $shar_touch -am 0117142999 'page01.pre' &&
+ $shar_touch -am 0124114799 'page01.pre' &&
chmod 0664 'page01.pre' ||
$echo 'restore of' 'page01.pre' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'page01.pre:' 'MD5 check failed'
-74d3999cd710b35c8e6c26e558a926cb page01.pre
+b1fef664f58233e14943041ed2765830 page01.pre
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`"
@@ -179,7 +179,7 @@ X
<P>Ok, now we're done with that. As you can see, it really isn't
so hard to create an object that makes sending data much more "natural"
than the typical send() or send_n() invocation. You can even build
-up arbitrary objects &amp; do some neat tricks with C++ templates to stream
+up arbitrary objects and do some neat tricks with C++ templates to stream
their data out as well. (We may go into that a little later.)
Of course, writting the full implementation such that these streams are
interchangable with the standard C++ ostreams is quite a bit more difficult.
@@ -197,20 +197,20 @@ settings</A>.
X
<P>
SHAR_EOF
- $shar_touch -am 0117142999 'page01.pst' &&
+ $shar_touch -am 0124114999 'page01.pst' &&
chmod 0664 'page01.pst' ||
$echo 'restore of' 'page01.pst' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'page01.pst:' 'MD5 check failed'
-c17e7bf6d06005bb1932f1790f8929fc page01.pst
+63a7bcf418c9dd35d92caa17a6a4af7b page01.pst
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pst'`"
- test 963 -eq "$shar_count" ||
- $echo 'page01.pst:' 'original size' '963,' 'current size' "$shar_count!"
+ test 961 -eq "$shar_count" ||
+ $echo 'page01.pst:' 'original size' '961,' 'current size' "$shar_count!"
fi
fi
-rm -fr _sh00408
+rm -fr _sh21744
exit 0
diff --git a/docs/tutorials/004/page01.html b/docs/tutorials/004/page01.html
index 1ed7799673e..71db5883d43 100644
--- a/docs/tutorials/004/page01.html
+++ b/docs/tutorials/004/page01.html
@@ -25,10 +25,10 @@ was born.)
Kirthika says:
<UL>
The cool thing about this "cooler" client is how we use a C++ trick for
-streaming incoming data by using the operator<<() metod. Also the
+streaming incoming data by using the operator<<() method. Also the
Connector portion is wrapped in the open() method which now takes in the
-server hostname and port. The result is a cleaner-looking client which
-successfully interacts with the server, when connection is established.
+server hostname and port. The result is a cleaner looking client which
+successfully interacts with the server when connection is established.
</UL>
<HR WIDTH="100%">
<PRE>
@@ -76,7 +76,7 @@ public:
<font color=red>/*
This is where the coolness lies. Most C++ folks are familiar
- with "<font color=green>cout &lt;&lt; some-data</font>". It's a very handy and easy way to
+ with "<font color=green>cout &lt;&lt; some-data.</font>" It's a very handy and easy way to
toss data around. By adding these method calls, we're able
to do the same thing with a socket connection.
*/</font>
@@ -257,13 +257,13 @@ int main (int argc, char *argv[])
<font color=red>/*
Use the basic constructor since the other isn't really very safe.
*/</font>
- Client server;
+ Client peer;
<font color=red>/*
Open the server connection. Notice how this is simpler than Tutorial 3
since we only have to provide a host name and port value.
*/</font>
- if( server.open(server_host,server_port) == -1 )
+ if( peer.open(server_host,server_port) == -1 )
{
ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>open</font>"), -1);
}
@@ -274,12 +274,12 @@ int main (int argc, char *argv[])
Tell the server which iteration we're on. No more mucking aroudn with
sprintf at this level! It's all hidden from us.
*/</font>
- server &lt;&lt; "<font color=green>message = </font>" &lt;&lt; i+1;
+ peer &lt;&lt; "<font color=green>message = </font>" &lt;&lt; i+1;
<font color=red>/*
Everything OK?
*/</font>
- if ( server.error() )
+ if ( peer.error() )
{
ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>send</font>"), -1);
}
@@ -289,7 +289,7 @@ int main (int argc, char *argv[])
}
}
- if (server.close () == -1)
+ if (peer.close () == -1)
{
ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>close</font>"), -1);
}
@@ -302,7 +302,7 @@ int main (int argc, char *argv[])
<P>Ok, now we're done with that. As you can see, it really isn't
so hard to create an object that makes sending data much more "natural"
than the typical send() or send_n() invocation. You can even build
-up arbitrary objects &amp; do some neat tricks with C++ templates to stream
+up arbitrary objects and do some neat tricks with C++ templates to stream
their data out as well. (We may go into that a little later.)
Of course, writting the full implementation such that these streams are
interchangable with the standard C++ ostreams is quite a bit more difficult.
diff --git a/docs/tutorials/005/Makefile b/docs/tutorials/005/Makefile
index 8c0f9a91a3c..2494e510f9c 100644
--- a/docs/tutorials/005/Makefile
+++ b/docs/tutorials/005/Makefile
@@ -82,6 +82,10 @@ Indent : #
# uncluttered. The perl script referenced here pulls the dependency
# stuff back out of the Makefile and into a file ".depend" which we then
# include just like the makefile components above.
+ #
+ # NOTE: The 'depend' target expects to have GCC available.
+ # You can do the same thing with other compilers but the ACE
+ # makefiles and utilities are only wired up to work with GCC.
Depend : depend
perl ../fix.Makefile
diff --git a/docs/tutorials/005/client_acceptor.h b/docs/tutorials/005/client_acceptor.h
index fa3d3b41be8..a25a3835235 100644
--- a/docs/tutorials/005/client_acceptor.h
+++ b/docs/tutorials/005/client_acceptor.h
@@ -8,8 +8,6 @@
The ACE_Acceptor<> template lives in the ace/Acceptor.h header file. You'll
find a very consitent naming convention between the ACE objects and the
headers where they can be found. In general, the ACE object ACE_Foobar will
-
-
be found in ace/Foobar.h.
*/
diff --git a/docs/tutorials/005/client_handler.cpp b/docs/tutorials/005/client_handler.cpp
index ca9d395c44f..8d669b8320f 100644
--- a/docs/tutorials/005/client_handler.cpp
+++ b/docs/tutorials/005/client_handler.cpp
@@ -35,7 +35,7 @@ Client_Handler::Client_Handler (void)
Client_Handler::~Client_Handler (void)
{
// Make sure that our peer closes when we're deleted. This
- // will probably happend when the peer is deleted but it
+ // will probably happened when the peer is deleted but it
// doesn't hurt to be explicit.
this->peer ().close ();
}
@@ -100,7 +100,7 @@ int Client_Handler::open (void *_acceptor)
/*
Our ACE_Svc_Handler baseclass gives us the peer() method as a way to
access our underlying ACE_SOCK_Stream. On that object, we can invoke the
- get_remote_addr() method to get get an ACE_INET_Addr having our client's
+ get_remote_addr() method to get an ACE_INET_Addr having our client's
address information. As with most ACE methods, we'll get back (and return)
a -1 if there was any kind of error. Once we have the ACE_INET_Addr, we
can query it to find out the clien's host name, TCP/IP address, TCP/IP
@@ -121,7 +121,7 @@ int Client_Handler::open (void *_acceptor)
any case, the test above should always be done to ensure that the
connection is worth keeping.
- Now, regiser ourselves with a reactor and tell that reactor that we want
+ Now, register ourselves with a reactor and tell that reactor that we want
to be notified when there is something to read. Remember, we took our
reactor value from the acceptor which created us in the first place.
Since we're exploring a single-threaded implementation, this is the
@@ -220,10 +220,13 @@ int Client_Handler::process (char *_rdbuf, int _rdbuf_len)
switch (this->peer ().recv (_rdbuf, _rdbuf_len))
{
case -1:
+ // Complain and leave
ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p bad read\n", "client"), -1);
case 0:
+ // Complain and leave
ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) closing daemon (fd = %d)\n", this->get_handle ()), -1);
default:
+ // Show the data
ACE_DEBUG ((LM_DEBUG, "(%P|%t) from client: %s", _rdbuf));
}
diff --git a/docs/tutorials/005/client_handler.h b/docs/tutorials/005/client_handler.h
index 7b228334226..d02ac73f0bd 100644
--- a/docs/tutorials/005/client_handler.h
+++ b/docs/tutorials/005/client_handler.h
@@ -50,7 +50,7 @@ public:
/*
Most ACE objects have an open() method. That's how you make them ready
to do work. ACE_Event_Handler has a virtual open() method which allows us
- to create this overrride. ACE_Acceptor<> will invoke this method after
+ to create an override. ACE_Acceptor<> will invoke this method after
creating a new Client_Handler when a client connects. Notice that the
parameter to open() is a void*. It just so happens that the pointer
points to the acceptor which created us. You would like for the parameter
@@ -80,12 +80,12 @@ protected:
/*
When we register with the reactor, we're going to tell it that we want to
be notified of READ events. When the reactor sees that there is read
- activity for us, our handle_input() will be invoked. The _handleg
+ activity for us, our handle_input() will be invoked. The _handle
provided is the handle (file descriptor in Unix) of the actual connection
causing the activity. Since we're derived from ACE_Svc_Handler<> and it
- maintains it's own peer (ACE_SOCK_Stream) object, this is redundant for
+ maintains its own peer (ACE_SOCK_Stream) object, this is redundant for
us. However, if we had been derived directly from ACE_Event_Handler, we
- may have chosen not to contain the peer. In that case, the _handleg
+ may have chosen not to contain the peer. In that case, the _handle
would be important to us for reading the client's data.
*/
int handle_input (ACE_HANDLE _handle);
@@ -93,7 +93,7 @@ protected:
/*
This has nothing at all to do with ACE. I've added this here as a worker
function which I will call from handle_input(). That allows me to
- introduce concurrencly in later tutorials with a no changes to the worker
+ introduce concurrency in later tutorials with no changes to the worker
function. You can think of process() as application-level code and
everything else as application-framework code.
*/
diff --git a/docs/tutorials/005/combine.shar b/docs/tutorials/005/combine.shar
index 8bdd7c46422..28175d7785e 100644
--- a/docs/tutorials/005/combine.shar
+++ b/docs/tutorials/005/combine.shar
@@ -3,7 +3,7 @@
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
-# Made on 1999-01-17 14:53 EST by <jcej@chiroptera.tragus.org>.
+# Made on 1999-01-24 14:30 EST by <jcej@chiroptera.tragus.org>.
# Source directory was `/var/home/jcej/projects/ACE_wrappers/docs/tutorials/005'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
@@ -14,8 +14,8 @@
# 598 -rw-rw-r-- hdr
# 97 -rw-rw-r-- bodies
# 628 -rw-rw-r-- page01.pre
-# 512 -rw-rw-r-- page02.pre
-# 686 -rw-rw-r-- page03.pre
+# 516 -rw-rw-r-- page02.pre
+# 685 -rw-rw-r-- page03.pre
# 464 -rw-rw-r-- page04.pre
# 218 -rw-rw-r-- page05.pre
# 98 -rw-rw-r-- page06.pre
@@ -67,7 +67,7 @@ else
fi
rm -f 1231235999 $$.touch
#
-if mkdir _sh00760; then
+if mkdir _sh22890; then
$echo 'x -' 'creating lock directory'
else
$echo 'failed to create lock directory'
@@ -192,7 +192,7 @@ This tutorial is a re-cap of the client-server hookup tutorial with much
X cleaner code (for instance: use of destroy() to delete objects and
process() which does the task of reading in data from the client).
<P>
-We again enroll the services of the reactor to handle events. Everything
+We again enroll the services of the ACE_Reactor to handle events. Everything
occurs in a single thread.
<P>
This tutorial is a stepping stone towards a mutithreaded server model.
@@ -200,19 +200,19 @@ This tutorial is a stepping stone towards a mutithreaded server model.
<P>
<HR WIDTH="100%">
SHAR_EOF
- $shar_touch -am 0117143899 'page02.pre' &&
+ $shar_touch -am 0124115599 'page02.pre' &&
chmod 0664 'page02.pre' ||
$echo 'restore of' 'page02.pre' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'page02.pre:' 'MD5 check failed'
-b8413e5ef19a9a56971d419e90f14b51 page02.pre
+c81f5251d4ec6de954b9d2f5a026525b page02.pre
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`"
- test 512 -eq "$shar_count" ||
- $echo 'page02.pre:' 'original size' '512,' 'current size' "$shar_count!"
+ test 516 -eq "$shar_count" ||
+ $echo 'page02.pre:' 'original size' '516,' 'current size' "$shar_count!"
fi
fi
# ============= page03.pre ==============
@@ -224,7 +224,7 @@ else
X
<P>Now, let's take a look at <I><A HREF="client_acceptor.h">client_acceptor.h</A></I>.&nbsp;
Since I went on about how it does all the work of letting clients connect
-to us, it must be rather complext.&nbsp; Right?&nbsp; Wrong.
+to us, it must be rather complex.&nbsp; Right?&nbsp; Wrong.
X
<P>The more you use ACE, the more you'll find that they've already taken
care of most details for you.&nbsp; With respect to the acceptance of client
@@ -236,19 +236,19 @@ X
<P>
<HR WIDTH="100%">
SHAR_EOF
- $shar_touch -am 0117143899 'page03.pre' &&
+ $shar_touch -am 0124115699 'page03.pre' &&
chmod 0664 'page03.pre' ||
$echo 'restore of' 'page03.pre' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'page03.pre:' 'MD5 check failed'
-e9d33d562522df5623cd6bcea010a9c6 page03.pre
+edb44ba6e3033259e60b4a83d0675b03 page03.pre
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`"
- test 686 -eq "$shar_count" ||
- $echo 'page03.pre:' 'original size' '686,' 'current size' "$shar_count!"
+ test 685 -eq "$shar_count" ||
+ $echo 'page03.pre:' 'original size' '685,' 'current size' "$shar_count!"
fi
fi
# ============= page04.pre ==============
@@ -419,5 +419,5 @@ SHAR_EOF
$echo 'page08.pre:' 'original size' '715,' 'current size' "$shar_count!"
fi
fi
-rm -fr _sh00760
+rm -fr _sh22890
exit 0
diff --git a/docs/tutorials/005/page02.html b/docs/tutorials/005/page02.html
index d3e87eb5873..d453146c0ca 100644
--- a/docs/tutorials/005/page02.html
+++ b/docs/tutorials/005/page02.html
@@ -24,7 +24,7 @@ This tutorial is a re-cap of the client-server hookup tutorial with much
cleaner code (for instance: use of destroy() to delete objects and
process() which does the task of reading in data from the client).
<P>
-We again enroll the services of the reactor to handle events. Everything
+We again enroll the services of the ACE_Reactor to handle events. Everything
occurs in a single thread.
<P>
This tutorial is a stepping stone towards a mutithreaded server model.
@@ -135,7 +135,7 @@ int main (int argc, char *argv[])
signal handler catches something, the finished flag will be set and we'll
exit. Conveniently enough, handle_events() is also interrupted by signals
and will exit back to the while() loop. (If you want your event loop to
- not be interrupted by signals, checkout the &lt;i>restart&lt;/i> flag on the
+ not be interrupted by signals, checkout the 'restart' flag on the
open() method of ACE_Reactor if you're interested.)
*/</font>
while (!finished)
diff --git a/docs/tutorials/005/page03.html b/docs/tutorials/005/page03.html
index 20c80328703..74f9624864f 100644
--- a/docs/tutorials/005/page03.html
+++ b/docs/tutorials/005/page03.html
@@ -18,7 +18,7 @@
<P>Now, let's take a look at <I><A HREF="client_acceptor.h">client_acceptor.h</A></I>.&nbsp;
Since I went on about how it does all the work of letting clients connect
-to us, it must be rather complext.&nbsp; Right?&nbsp; Wrong.
+to us, it must be rather complex.&nbsp; Right?&nbsp; Wrong.
<P>The more you use ACE, the more you'll find that they've already taken
care of most details for you.&nbsp; With respect to the acceptance of client
@@ -40,8 +40,6 @@ with an object type to instantiate when a new connection arrives.
The ACE_Acceptor&lt;> template lives in the ace/Acceptor.h header file. You'll
find a very consitent naming convention between the ACE objects and the
headers where they can be found. In general, the ACE object ACE_Foobar will
-
-
be found in ace/Foobar.h.
*/</font>
diff --git a/docs/tutorials/005/page04.html b/docs/tutorials/005/page04.html
index c5eb21cda31..4856284e895 100644
--- a/docs/tutorials/005/page04.html
+++ b/docs/tutorials/005/page04.html
@@ -80,7 +80,7 @@ public:
<font color=red>/*
Most ACE objects have an open() method. That's how you make them ready
to do work. ACE_Event_Handler has a virtual open() method which allows us
- to create this overrride. ACE_Acceptor&lt;> will invoke this method after
+ to create an override. ACE_Acceptor&lt;> will invoke this method after
creating a new Client_Handler when a client connects. Notice that the
parameter to open() is a void*. It just so happens that the pointer
points to the acceptor which created us. You would like for the parameter
@@ -110,12 +110,12 @@ protected:
<font color=red>/*
When we register with the reactor, we're going to tell it that we want to
be notified of READ events. When the reactor sees that there is read
- activity for us, our handle_input() will be invoked. The _handleg
+ activity for us, our handle_input() will be invoked. The _handle
provided is the handle (file descriptor in Unix) of the actual connection
causing the activity. Since we're derived from ACE_Svc_Handler&lt;> and it
- maintains it's own peer (ACE_SOCK_Stream) object, this is redundant for
+ maintains its own peer (ACE_SOCK_Stream) object, this is redundant for
us. However, if we had been derived directly from ACE_Event_Handler, we
- may have chosen not to contain the peer. In that case, the _handleg
+ may have chosen not to contain the peer. In that case, the _handle
would be important to us for reading the client's data.
*/</font>
int handle_input (ACE_HANDLE _handle);
@@ -123,7 +123,7 @@ protected:
<font color=red>/*
This has nothing at all to do with ACE. I've added this here as a worker
function which I will call from handle_input(). That allows me to
- introduce concurrencly in later tutorials with a no changes to the worker
+ introduce concurrency in later tutorials with no changes to the worker
function. You can think of process() as application-level code and
everything else as application-framework code.
*/</font>
diff --git a/docs/tutorials/005/page05.html b/docs/tutorials/005/page05.html
index 198b2d737ce..4b33f063980 100644
--- a/docs/tutorials/005/page05.html
+++ b/docs/tutorials/005/page05.html
@@ -60,7 +60,7 @@ rest of the application all together.
<font color=#008888>Client_Handler::~Client_Handler</font> (void)
{
<font color=red>// Make sure that our peer closes when we're deleted. This</font>
- <font color=red>// will probably happend when the peer is deleted but it</font>
+ <font color=red>// will probably happened when the peer is deleted but it</font>
<font color=red>// doesn't hurt to be explicit.</font>
this->peer ().close ();
}
@@ -125,7 +125,7 @@ int <font color=#008888>Client_Handler::open</font> (void *_acceptor)
<font color=red>/*
Our ACE_Svc_Handler baseclass gives us the peer() method as a way to
access our underlying ACE_SOCK_Stream. On that object, we can invoke the
- get_remote_addr() method to get get an ACE_INET_Addr having our client's
+ get_remote_addr() method to get an ACE_INET_Addr having our client's
address information. As with most ACE methods, we'll get back (and return)
a -1 if there was any kind of error. Once we have the ACE_INET_Addr, we
can query it to find out the clien's host name, TCP/IP address, TCP/IP
@@ -146,7 +146,7 @@ int <font color=#008888>Client_Handler::open</font> (void *_acceptor)
any case, the test above should always be done to ensure that the
connection is worth keeping.
- Now, regiser ourselves with a reactor and tell that reactor that we want
+ Now, register ourselves with a reactor and tell that reactor that we want
to be notified when there is something to read. Remember, we took our
reactor value from the acceptor which created us in the first place.
Since we're exploring a single-threaded implementation, this is the
@@ -245,10 +245,13 @@ int <font color=#008888>Client_Handler::process</font> (char *_rdbuf, int _rdbuf
switch (this->peer ().recv (_rdbuf, _rdbuf_len))
{
case -1:
+ <font color=red>// Complain and leave</font>
ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) %p bad read\n</font>", "<font color=green>client</font>"), -1);
case 0:
+ <font color=red>// Complain and leave</font>
ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) closing daemon (fd = %d)\n</font>", this->get_handle ()), -1);
default:
+ <font color=red>// Show the data</font>
ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) from client: %s</font>", _rdbuf));
}
diff --git a/docs/tutorials/005/page06.html b/docs/tutorials/005/page06.html
index 76c545e5cf8..d3c6e91e80a 100644
--- a/docs/tutorials/005/page06.html
+++ b/docs/tutorials/005/page06.html
@@ -105,6 +105,10 @@ Indent : #
# uncluttered. The perl script referenced here pulls the dependency
# stuff back out of the Makefile and into a file "<font color=green>.depend</font>" which we then
# include just like the makefile components above.
+ #
+ # NOTE: The 'depend' target expects to have GCC available.
+ # You can do the same thing with other compilers but the ACE
+ # makefiles and utilities are only wired up to work with GCC.
Depend : depend
perl ../fix.Makefile
diff --git a/docs/tutorials/005/server.cpp b/docs/tutorials/005/server.cpp
index 991e441e0b3..56991761c14 100644
--- a/docs/tutorials/005/server.cpp
+++ b/docs/tutorials/005/server.cpp
@@ -101,7 +101,7 @@ int main (int argc, char *argv[])
signal handler catches something, the finished flag will be set and we'll
exit. Conveniently enough, handle_events() is also interrupted by signals
and will exit back to the while() loop. (If you want your event loop to
- not be interrupted by signals, checkout the <i>restart</i> flag on the
+ not be interrupted by signals, checkout the 'restart' flag on the
open() method of ACE_Reactor if you're interested.)
*/
while (!finished)
diff --git a/docs/tutorials/007/client_handler.cpp b/docs/tutorials/007/client_handler.cpp
index 647739e34e2..849cf44bf58 100644
--- a/docs/tutorials/007/client_handler.cpp
+++ b/docs/tutorials/007/client_handler.cpp
@@ -158,6 +158,12 @@ int Client_Handler::handle_input (ACE_HANDLE _handle)
Remove ourselves from the reactor and ask to be put into the thread pool's
queue of work. (You should be able to use suspend_handler() but I've had
problems with that.)
+
+ By removing ourselves from the reactor, we're guaranteed
+ that we won't be called back until the thread pool picks us
+ up out of the queue. If we didn't remove ourselves, then
+ the reactor would continue to invoke handle_input() and we
+ don't want that to happen.
*/
this->reactor()->remove_handler( this, REMOVE_MASK );
return this->thread_pool()->enqueue(this);
@@ -188,6 +194,10 @@ int Client_Handler::handle_input (ACE_HANDLE _handle)
{
if( rval != -1 )
{
+ /*
+ If we don't remember to re-register ourselves, then we won't
+ be able to respond to any future client requests.
+ */
this->reactor()->register_handler( this, REGISTER_MASK );
}
}
diff --git a/docs/tutorials/007/combine.shar b/docs/tutorials/007/combine.shar
index e0a98ea39db..3c01098a177 100644
--- a/docs/tutorials/007/combine.shar
+++ b/docs/tutorials/007/combine.shar
@@ -3,17 +3,17 @@
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
-# Made on 1999-01-21 15:59 EST by <jcej@beta.mobsec.com>.
-# Source directory was `/projects/home/jcej/projects/ACE_wrappers/docs/tutorials/007'.
+# Made on 1999-01-24 15:37 EST by <jcej@chiroptera.tragus.org>.
+# Source directory was `/var/home/jcej/projects/ACE_wrappers/docs/tutorials/007'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
-# 575 -rw-rw-r-- hdr
+# 576 -rw-rw-r-- hdr
# 123 -rw-rw-r-- bodies
-# 3153 -rw-rw-r-- page01.pre
+# 3385 -rw-rw-r-- page01.pre
# 87 -rw-rw-r-- page02.pre
# 120 -rw-rw-r-- page03.pre
# 171 -rw-rw-r-- page04.pre
@@ -74,7 +74,7 @@ else
fi
rm -f 1231235999 $$.touch
#
-if mkdir _sh32671; then
+if mkdir _sh24460; then
$echo 'x -' 'creating lock directory'
else
$echo 'failed to create lock directory'
@@ -108,12 +108,12 @@ SHAR_EOF
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'hdr:' 'MD5 check failed'
-8c1e8f73c777567099ea4e11a860ea56 hdr
+151b1b4bda96cc1e3ef55356e819ca42 hdr
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`"
- test 575 -eq "$shar_count" ||
- $echo 'hdr:' 'original size' '575,' 'current size' "$shar_count!"
+ test 576 -eq "$shar_count" ||
+ $echo 'hdr:' 'original size' '576,' 'current size' "$shar_count!"
fi
fi
# ============= bodies ==============
@@ -214,20 +214,25 @@ This tutorial gives us a flavour of implementing a server with a
thread-pool strategy and how it can be managed using the ACE_Task class,
which provides an OO approach to thread-creation and implementation.
</UL>
+<font size=-1>* The additions to this tutorial make use of
+ACE_Message_Queue which is discussed in depth in
+<A HREF="../010/page01.html">Tutorial 10</A>. Feel free to read ahead
+if you get lost in the message queue stuff.
+</font>
SHAR_EOF
- $shar_touch -am 0121153399 'page01.pre' &&
+ $shar_touch -am 0124153799 'page01.pre' &&
chmod 0664 'page01.pre' ||
$echo 'restore of' 'page01.pre' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'page01.pre:' 'MD5 check failed'
-ec4906ec2d89c587a2f8b520fa2b6edb page01.pre
+555176fa726c723dda37c4256f29165b page01.pre
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`"
- test 3153 -eq "$shar_count" ||
- $echo 'page01.pre:' 'original size' '3153,' 'current size' "$shar_count!"
+ test 3385 -eq "$shar_count" ||
+ $echo 'page01.pre:' 'original size' '3385,' 'current size' "$shar_count!"
fi
fi
# ============= page02.pre ==============
@@ -672,5 +677,5 @@ SHAR_EOF
$echo 'page07.pst:' 'original size' '97,' 'current size' "$shar_count!"
fi
fi
-rm -fr _sh32671
+rm -fr _sh24460
exit 0
diff --git a/docs/tutorials/007/page01.html b/docs/tutorials/007/page01.html
index c69d9678172..e2585c7b3de 100644
--- a/docs/tutorials/007/page01.html
+++ b/docs/tutorials/007/page01.html
@@ -73,5 +73,9 @@ This tutorial gives us a flavour of implementing a server with a
thread-pool strategy and how it can be managed using the ACE_Task class,
which provides an OO approach to thread-creation and implementation.
</UL>
-<P><HR WIDTH="100%">
+<font size=-1>* The additions to this tutorial make use of
+ACE_Message_Queue which is discussed in depth in
+<A HREF="../010/page01.html">Tutorial 10</A>. Feel free to read ahead
+if you get lost in the message queue stuff.
+</font><P><HR WIDTH="100%">
<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page02.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/007/page06.html b/docs/tutorials/007/page06.html
index acfcb950bf1..5781faa76c4 100644
--- a/docs/tutorials/007/page06.html
+++ b/docs/tutorials/007/page06.html
@@ -180,6 +180,12 @@ int <font color=#008888>Client_Handler::handle_input</font> (ACE_HANDLE _handle)
Remove ourselves from the reactor and ask to be put into the thread pool's
queue of work. (You should be able to use suspend_handler() but I've had
problems with that.)
+
+ By removing ourselves from the reactor, we're guaranteed
+ that we won't be called back until the thread pool picks us
+ up out of the queue. If we didn't remove ourselves, then
+ the reactor would continue to invoke handle_input() and we
+ don't want that to happen.
*/</font>
this->reactor()->remove_handler( this, REMOVE_MASK );
return this->thread_pool()->enqueue(this);
@@ -210,6 +216,10 @@ int <font color=#008888>Client_Handler::handle_input</font> (ACE_HANDLE _handle)
{
if( rval != -1 )
{
+ <font color=red>/*
+ If we don't remember to re-register ourselves, then we won't
+ be able to respond to any future client requests.
+ */</font>
this->reactor()->register_handler( this, REGISTER_MASK );
}
}
diff --git a/docs/tutorials/007/page08.html b/docs/tutorials/007/page08.html
index 5563fdb252f..dbbfdb76a15 100644
--- a/docs/tutorials/007/page08.html
+++ b/docs/tutorials/007/page08.html
@@ -85,7 +85,7 @@ int <font color=#008888>Thread_Pool::close</font>( u_long flags )
<font color=red>/*
When an object wants to do work in the pool, it should call the enqueue() method.
- We introduce the ACE_Message_Block here but, unfortunately, we seriously missuse it.
+ We introduce the ACE_Message_Block here but, unfortunately, we seriously misuse it.
*/</font>
int <font color=#008888>Thread_Pool::enqueue</font>( ACE_Event_Handler * _handler )
{
diff --git a/docs/tutorials/007/thread_pool.cpp b/docs/tutorials/007/thread_pool.cpp
index c70d0995f53..ef7b4a0a250 100644
--- a/docs/tutorials/007/thread_pool.cpp
+++ b/docs/tutorials/007/thread_pool.cpp
@@ -64,7 +64,7 @@ int Thread_Pool::close( u_long flags )
/*
When an object wants to do work in the pool, it should call the enqueue() method.
- We introduce the ACE_Message_Block here but, unfortunately, we seriously missuse it.
+ We introduce the ACE_Message_Block here but, unfortunately, we seriously misuse it.
*/
int Thread_Pool::enqueue( ACE_Event_Handler * _handler )
{
diff --git a/docs/tutorials/008/combine.shar b/docs/tutorials/008/combine.shar
index 26e729f68b3..a9156df99ad 100644
--- a/docs/tutorials/008/combine.shar
+++ b/docs/tutorials/008/combine.shar
@@ -3,7 +3,7 @@
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
-# Made on 1999-01-21 20:42 EST by <jcej@chiroptera.tragus.org>.
+# Made on 1999-01-24 15:11 EST by <jcej@chiroptera.tragus.org>.
# Source directory was `/var/home/jcej/projects/ACE_wrappers/docs/tutorials/008'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
@@ -16,11 +16,11 @@
# 2769 -rw-rw-r-- page01.pre
# 416 -rw-rw-r-- page02.pre
# 345 -rw-rw-r-- page03.pre
-# 486 -rw-rw-r-- page04.pre
+# 481 -rw-rw-r-- page04.pre
# 578 -rw-rw-r-- page05.pre
# 952 -rw-rw-r-- page02.pst
# 367 -rw-rw-r-- page03.pst
-# 987 -rw-rw-r-- page04.pst
+# 1173 -rw-rw-r-- page04.pst
#
save_IFS="${IFS}"
IFS="${IFS}:"
@@ -67,7 +67,7 @@ else
fi
rm -f 1231235999 $$.touch
#
-if mkdir _sh23902; then
+if mkdir _sh23993; then
$echo 'x -' 'creating lock directory'
else
$echo 'failed to create lock directory'
@@ -286,25 +286,25 @@ In <A HREF="broadcast_client.cpp">broadcast_client.cpp</A> we
find out how to send a single datagram to every host on our (sub)network.&nbsp;
I have to say <I>(sub)network</I> because broadcast datagrams typically
are not passed through routers.&nbsp; So, if your network admin has divided
-up your network into subnets, your broadcasts will likey only stay on the
+up your network into subnets, your broadcasts will likey stay on the
subnet you're a part of.
X
<P>I've only commented the parts that are different from the directed_client.
<HR WIDTH="100%">
SHAR_EOF
- $shar_touch -am 0121154099 'page04.pre' &&
+ $shar_touch -am 0124144899 'page04.pre' &&
chmod 0664 'page04.pre' ||
$echo 'restore of' 'page04.pre' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'page04.pre:' 'MD5 check failed'
-3578f6334323b7eb43c473661a2d38df page04.pre
+8811bded669a7a7be85a4878d5076190 page04.pre
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`"
- test 486 -eq "$shar_count" ||
- $echo 'page04.pre:' 'original size' '486,' 'current size' "$shar_count!"
+ test 481 -eq "$shar_count" ||
+ $echo 'page04.pre:' 'original size' '481,' 'current size' "$shar_count!"
fi
fi
# ============= page05.pre ==============
@@ -439,22 +439,27 @@ like this:&nbsp; <I>ACE_SOCK_Dgram_Bcast::mk_broadcast: Broadcast is not
enable for this interface.: Unknown error</I>.&nbsp; There are some interfaces
(ppp, slip) that don't support broadcast datagrams.&nbsp; That's what you're
seeing here.</BLOCKQUOTE>
+Ok, one more warning:
+<blockquote>If you happen to have multiple servers running on your
+network when you invoke this client, the resopnse could come from any
+one of them.
+</blockquote>
X
SHAR_EOF
- $shar_touch -am 0121153899 'page04.pst' &&
+ $shar_touch -am 0124145199 'page04.pst' &&
chmod 0664 'page04.pst' ||
$echo 'restore of' 'page04.pst' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'page04.pst:' 'MD5 check failed'
-af9341d0c565a98b7e752efe92b10fac page04.pst
+0f46660ee6a9e96fe30b7d4901fbdbbe page04.pst
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pst'`"
- test 987 -eq "$shar_count" ||
- $echo 'page04.pst:' 'original size' '987,' 'current size' "$shar_count!"
+ test 1173 -eq "$shar_count" ||
+ $echo 'page04.pst:' 'original size' '1173,' 'current size' "$shar_count!"
fi
fi
-rm -fr _sh23902
+rm -fr _sh23993
exit 0
diff --git a/docs/tutorials/008/page04.html b/docs/tutorials/008/page04.html
index d5392ce9edd..883240e997c 100644
--- a/docs/tutorials/008/page04.html
+++ b/docs/tutorials/008/page04.html
@@ -19,7 +19,7 @@ In <A HREF="broadcast_client.cpp">broadcast_client.cpp</A> we
find out how to send a single datagram to every host on our (sub)network.&nbsp;
I have to say <I>(sub)network</I> because broadcast datagrams typically
are not passed through routers.&nbsp; So, if your network admin has divided
-up your network into subnets, your broadcasts will likey only stay on the
+up your network into subnets, your broadcasts will likey stay on the
subnet you're a part of.
<P>I've only commented the parts that are different from the directed_client.
@@ -115,6 +115,11 @@ like this:&nbsp; <I>ACE_SOCK_Dgram_Bcast::mk_broadcast: Broadcast is not
enable for this interface.: Unknown error</I>.&nbsp; There are some interfaces
(ppp, slip) that don't support broadcast datagrams.&nbsp; That's what you're
seeing here.</BLOCKQUOTE>
+Ok, one more warning:
+<blockquote>If you happen to have multiple servers running on your
+network when you invoke this client, the resopnse could come from any
+one of them.
+</blockquote>
<P><HR WIDTH="100%">
<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page05.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/009/page03.html b/docs/tutorials/009/page03.html
index e0cd345e9e9..9da926e3ce5 100644
--- a/docs/tutorials/009/page03.html
+++ b/docs/tutorials/009/page03.html
@@ -21,7 +21,8 @@ addition of a timeout to the recv() call so that we can exit somewhat gracefully
if the server doesn't like what we have to say.
<P>
-<HR WIDTH="100%"><PRE>
+<HR WIDTH="100%">
+<PRE>
<font color=red>// $Id$</font>
diff --git a/docs/tutorials/010/Makefile b/docs/tutorials/010/Makefile
index 683e82cbcda..3493d9486a1 100644
--- a/docs/tutorials/010/Makefile
+++ b/docs/tutorials/010/Makefile
@@ -52,6 +52,17 @@ Depend : depend
.depend : #
touch .depend
+HTML : #
+ [ -f hdr ] || $(MAKE) UNSHAR
+ perl ../combine *.pre ; chmod +r *.html
+
+SHAR : #
+ [ ! -f combine.shar ] || exit 1
+ shar -T hdr bodies *.pre *.pst > combine.shar && rm -f hdr bodies *.pre *.pst
+
+UNSHAR : #
+ sh combine.shar
+
#----------------------------------------------------------------------------
# Dependencies
#----------------------------------------------------------------------------
diff --git a/docs/tutorials/010/block.h b/docs/tutorials/010/block.h
index 583886872cb..83c5c497b0e 100644
--- a/docs/tutorials/010/block.h
+++ b/docs/tutorials/010/block.h
@@ -36,21 +36,3 @@ public:
};
#endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/tutorials/010/combine.shar b/docs/tutorials/010/combine.shar
new file mode 100644
index 00000000000..543b0883550
--- /dev/null
+++ b/docs/tutorials/010/combine.shar
@@ -0,0 +1,534 @@
+#!/bin/sh
+# This is a shell archive (produced by GNU sharutils 4.2).
+# To extract the files from this archive, save it to some FILE, remove
+# everything before the `!/bin/sh' line above, then type `sh FILE'.
+#
+# Made on 1999-01-24 15:41 EST by <jcej@chiroptera.tragus.org>.
+# Source directory was `/var/home/jcej/projects/ACE_wrappers/docs/tutorials/010'.
+#
+# Existing files will *not* be overwritten unless `-c' is specified.
+#
+# This shar contains:
+# length mode name
+# ------ ---------- ------------------------------------------
+# 440 -rw-rw-r-- hdr
+# 49 -rw-rw-r-- bodies
+# 2245 -rw-rw-r-- page01.pre
+# 84 -rw-rw-r-- page02.pre
+# 231 -rw-rw-r-- page03.pre
+# 138 -rw-rw-r-- page04.pre
+# 75 -rw-rw-r-- page05.pre
+# 1493 -rw-rw-r-- page06.pre
+# 444 -rw-rw-r-- page07.pre
+# 689 -rw-rw-r-- page02.pst
+# 236 -rw-rw-r-- page03.pst
+# 387 -rw-rw-r-- page04.pst
+# 366 -rw-rw-r-- page05.pst
+#
+save_IFS="${IFS}"
+IFS="${IFS}:"
+gettext_dir=FAILED
+locale_dir=FAILED
+first_param="$1"
+for dir in $PATH
+do
+ if test "$gettext_dir" = FAILED && test -f $dir/gettext \
+ && ($dir/gettext --version >/dev/null 2>&1)
+ then
+ set `$dir/gettext --version 2>&1`
+ if test "$3" = GNU
+ then
+ gettext_dir=$dir
+ fi
+ fi
+ if test "$locale_dir" = FAILED && test -f $dir/shar \
+ && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
+ then
+ locale_dir=`$dir/shar --print-text-domain-dir`
+ fi
+done
+IFS="$save_IFS"
+if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
+then
+ echo=echo
+else
+ TEXTDOMAINDIR=$locale_dir
+ export TEXTDOMAINDIR
+ TEXTDOMAIN=sharutils
+ export TEXTDOMAIN
+ echo="$gettext_dir/gettext -s"
+fi
+touch -am 1231235999 $$.touch >/dev/null 2>&1
+if test ! -f 1231235999 && test -f $$.touch; then
+ shar_touch=touch
+else
+ shar_touch=:
+ echo
+ $echo 'WARNING: not restoring timestamps. Consider getting and'
+ $echo "installing GNU \`touch', distributed in GNU File Utilities..."
+ echo
+fi
+rm -f 1231235999 $$.touch
+#
+if mkdir _sh24521; then
+ $echo 'x -' 'creating lock directory'
+else
+ $echo 'failed to create lock directory'
+ exit 1
+fi
+# ============= hdr ==============
+if test -f 'hdr' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'hdr' '(file already exists)'
+else
+ $echo 'x -' extracting 'hdr' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'hdr' &&
+<HTML>
+<HEAD>
+X <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+X <META NAME="Author" CONTENT="James CE Johnson">
+X <TITLE>ACE Tutorial 010</TITLE>
+</HEAD>
+<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F">
+X
+<CENTER><B><FONT SIZE=+2>ACE Tutorial 010</FONT></B></CENTER>
+X
+<CENTER><B><FONT SIZE=+2>Passing chunks of data through an ACE_Message_Queue</FONT></B></CENTER>
+X
+X
+<P>
+<HR WIDTH="100%">
+SHAR_EOF
+ $shar_touch -am 0124153399 'hdr' &&
+ chmod 0664 'hdr' ||
+ $echo 'restore of' 'hdr' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'hdr:' 'MD5 check failed'
+e3d97df3787127f8678ec95f024c44c6 hdr
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`"
+ test 440 -eq "$shar_count" ||
+ $echo 'hdr:' 'original size' '440,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= bodies ==============
+if test -f 'bodies' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'bodies' '(file already exists)'
+else
+ $echo 'x -' extracting 'bodies' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'bodies' &&
+PAGE=2
+message_queue.cpp
+block.h
+task.h
+task.cpp
+SHAR_EOF
+ $shar_touch -am 0124153399 'bodies' &&
+ chmod 0664 'bodies' ||
+ $echo 'restore of' 'bodies' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'bodies:' 'MD5 check failed'
+888c8b85427980776f703176da1f9ee4 bodies
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`"
+ test 49 -eq "$shar_count" ||
+ $echo 'bodies:' 'original size' '49,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page01.pre ==============
+if test -f 'page01.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page01.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page01.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page01.pre' &&
+<P>
+In an earlier tutorial we briefly introduced ACE_Message_Queue. In this
+tutorial we'll go into a bit more detail.
+<P>
+ACE_Message_Queue is modeled after Unix System V IPC mechanisms. The basic
+idea is that you put a block of data into one end of the Queue and take it
+out of the other end. Your basic FIFO in other words. The SysV mechanism
+works great for passing these blocks of data between processes on the same
+host but it's a bit overkill for moving blocks between threads. You could
+use a pipe, socket or similar mechanism but that still has more overhead than
+we really want just for moving data between threads. Process-global memory
+is a good technique but then you need a way to signal the "listening" threads.
+The ACE_Message_Queue is a better approach: Create blocks of data and enqueue
+them in one thread while another thread (or threads) dequeue and perform work.
+<P>
+Kirthika's Abstract:
+<UL>
+The Message Queue is a FIFO accessible from multiple threads.
+That is, a thread puts the produced blocks of data on the message queue
+to be consumed by some other thread/threads and processed. In this
+tutorial, we see how effectively the Message Queue in a ACE_Task can be
+used to pass data among threads in the thread pool.
+(this is very similar to
+<A HREF="../007/page01.html">Tutorial 7</A>
+X wherein we implemented a
+thread-pool server).Here, actual data is passed between the threads and
+also an ACE_Barrier has been used to provide synchronisation among
+multiple threads.
+<P>
+The Message Queue consists of Message Blocks, each of which has a read
+and write pointer. Using these pointers the message blocks can be
+accessed for reading and writing operations. The ACE_Task::svc() method
+will put the block onto the queue without bothering about the existence
+of a consumer for that block. A thread from the thread pool obtains the
+block from the queue, and checks to see whether the block_type is
+MB_HANGUP. If so, it puts the block back on the queue for its
+peers and exits. Otherwise, it reads the block and processes it before
+releasing it.
+<P>
+This simple tutorial makes us aware of the usage and importance of the
+Message Queue which could be used to our advantage especially for
+multithreaded applications.
+</UL>
+SHAR_EOF
+ $shar_touch -am 0124153899 'page01.pre' &&
+ chmod 0664 'page01.pre' ||
+ $echo 'restore of' 'page01.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page01.pre:' 'MD5 check failed'
+976beee5fb40e6328b6e85ea66ad24c7 page01.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`"
+ test 2245 -eq "$shar_count" ||
+ $echo 'page01.pre:' 'original size' '2245,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page02.pre ==============
+if test -f 'page02.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page02.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page02.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page02.pre' &&
+X
+We'll look first at <A HREF="message_queue.cpp">main()</A>.
+<P>
+X
+<HR WIDTH="100%">
+SHAR_EOF
+ $shar_touch -am 0124153399 'page02.pre' &&
+ chmod 0664 'page02.pre' ||
+ $echo 'restore of' 'page02.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page02.pre:' 'MD5 check failed'
+166bf09c6c4474767e95ef4a7be20a03 page02.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`"
+ test 84 -eq "$shar_count" ||
+ $echo 'page02.pre:' 'original size' '84,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page03.pre ==============
+if test -f 'page03.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page03.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page03.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page03.pre' &&
+Our <A HREF="block.h">Block</A> object is a very simple derivative
+of the ACE_Message_Block. The only reason I created it was to prove
+that the message blocks to, indeed, get freed when we're done with 'em.
+<P>
+X
+<HR WIDTH="100%">
+SHAR_EOF
+ $shar_touch -am 0124153399 'page03.pre' &&
+ chmod 0664 'page03.pre' ||
+ $echo 'restore of' 'page03.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page03.pre:' 'MD5 check failed'
+3164732c254de8d97fac8fd52071ae32 page03.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`"
+ test 231 -eq "$shar_count" ||
+ $echo 'page03.pre:' 'original size' '231,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page04.pre ==============
+if test -f 'page04.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page04.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page04.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page04.pre' &&
+Our <A HREF="task.h">Task</A> object executes in one or more threads
+and reads from the message queue it contains.
+<P>
+X
+<HR WIDTH="100%">
+SHAR_EOF
+ $shar_touch -am 0124153399 'page04.pre' &&
+ chmod 0664 'page04.pre' ||
+ $echo 'restore of' 'page04.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page04.pre:' 'MD5 check failed'
+fec9a7b5b9b2a8f61c0178aaf1b78a91 page04.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`"
+ test 138 -eq "$shar_count" ||
+ $echo 'page04.pre:' 'original size' '138,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page05.pre ==============
+if test -f 'page05.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page05.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page05.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page05.pre' &&
+X
+Our <A HREF="task.cpp">Task</A> object definition:
+<P>
+X
+<HR WIDTH="100%">
+SHAR_EOF
+ $shar_touch -am 0124153399 'page05.pre' &&
+ chmod 0664 'page05.pre' ||
+ $echo 'restore of' 'page05.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page05.pre:' 'MD5 check failed'
+4d210e58ac8c908096af0bf9bf118847 page05.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`"
+ test 75 -eq "$shar_count" ||
+ $echo 'page05.pre:' 'original size' '75,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page06.pre ==============
+if test -f 'page06.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page06.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page06.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page06.pre' &&
+X
+Since I added Block just to give us output, let's take a look at that output.
+X
+<P>
+<HR WIDTH="100%">
+<PRE>
+[jcej@chiroptera 010]$./message_queue 4 2
+(8910|1024) Task ctor 0xbffff9c4
+(8910|2050) Task 0xbffff9c4 starts in thread 2050
+(8910|1025) Task 0xbffff9c4 starts in thread 1025
+(8910|1024) Block ctor 0x8052398
+(8910|1024) Block ctor 0x8052488
+(8910|1024) Block ctor 0x8052578
+(8910|1024) Block ctor 0x8052668
+(8910|1024) Block ctor 0x8052758
+(8910|1025) Block 0x8052398 contains (This is message 0.)
+(8910|2050) Block 0x8052488 contains (This is message 1.)
+(8910|1025) Block dtor 0x8052398
+(8910|1025) Block 0x8052578 contains (This is message 2.)
+(8910|2050) Block dtor 0x8052488
+(8910|2050) Block 0x8052668 contains (This is message 3.)
+(8910|1025) Block dtor 0x8052578
+(8910|1025) Task close 0xbffff9c4
+(8910|2050) Block dtor 0x8052668
+(8910|2050) Task close 0xbffff9c4
+(8910|1024) Task dtor 0xbffff9c4
+(8910|1024) Block dtor 0x8052758
+(8910|1024) Application exiting
+[jcej@chiroptera 010]$
+</PRE>
+<HR WIDTH="100%">
+<P>
+Notice that each <i>Block ctor</i> has a corresponding <i>Block dtor</i>.
+We've proven the point that all memory gets cleaned up. We also see that
+both threads get to do some work and that both close as expected.
+<P>
+It's also worth mentioning that it's just an accident that all of the blocks
+are created and enqueued before any are processed. Run the test on a multi-processor
+or with more iterations and you'll see some get processed before all are created.
+SHAR_EOF
+ $shar_touch -am 0124153299 'page06.pre' &&
+ chmod 0664 'page06.pre' ||
+ $echo 'restore of' 'page06.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page06.pre:' 'MD5 check failed'
+d2a471df09308f89a611a7aa0218737f page06.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page06.pre'`"
+ test 1493 -eq "$shar_count" ||
+ $echo 'page06.pre:' 'original size' '1493,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page07.pre ==============
+if test -f 'page07.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page07.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page07.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page07.pre' &&
+X
+That's it for Tutorial 10. There are some esoteric changes between the thread-pool server
+and this application but it's basically the same. In the next tutorial I'll modify this just
+a bit to move non-trivial data through the queue.
+<P>
+X
+<UL>
+<LI><A HREF="Makefile">Makefile</A>
+<LI><A HREF="block.h">block.h</A>
+<LI><A HREF="message_queue.cpp">message_queue.cpp</A>
+<LI><A HREF="task.cpp">task.cpp</A>
+<LI><A HREF="task.h">task.h</A>
+</UL>
+SHAR_EOF
+ $shar_touch -am 0124153299 'page07.pre' &&
+ chmod 0664 'page07.pre' ||
+ $echo 'restore of' 'page07.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page07.pre:' 'MD5 check failed'
+07ae8f9b2a400e46ab102ab8c40a8b81 page07.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page07.pre'`"
+ test 444 -eq "$shar_count" ||
+ $echo 'page07.pre:' 'original size' '444,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page02.pst ==============
+if test -f 'page02.pst' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page02.pst' '(file already exists)'
+else
+ $echo 'x -' extracting 'page02.pst' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page02.pst' &&
+<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>
+SHAR_EOF
+ $shar_touch -am 0124153399 'page02.pst' &&
+ chmod 0664 'page02.pst' ||
+ $echo 'restore of' 'page02.pst' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page02.pst:' 'MD5 check failed'
+10957f28adbff16015bd94bdc01cd779 page02.pst
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pst'`"
+ test 689 -eq "$shar_count" ||
+ $echo 'page02.pst:' 'original size' '689,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page03.pst ==============
+if test -f 'page03.pst' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page03.pst' '(file already exists)'
+else
+ $echo 'x -' extracting 'page03.pst' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page03.pst' &&
+<HR WIDTH="100%">
+<P>
+Ok, nothing really magic there. Some folks just feel a little uncomfortable
+not doing an explicit <i>delete</i> on objects they've <i>new</i>'d so I
+wanted to show you that the memory really does get cleaned up.
+X
+SHAR_EOF
+ $shar_touch -am 0124153399 'page03.pst' &&
+ chmod 0664 'page03.pst' ||
+ $echo 'restore of' 'page03.pst' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page03.pst:' 'MD5 check failed'
+c822867adfcc3d40e4997e7bd68d6404 page03.pst
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pst'`"
+ test 236 -eq "$shar_count" ||
+ $echo 'page03.pst:' 'original size' '236,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page04.pst ==============
+if test -f 'page04.pst' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page04.pst' '(file already exists)'
+else
+ $echo 'x -' extracting 'page04.pst' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page04.pst' &&
+<HR WIDTH="100%">
+<P>
+The only thing here that we didn't see in the thread-pool server is the
+ACE_Barrier. The application logic really doesn't need it but it is a
+handy way to synchronize the threads at the beginning of svc(). In testing
+I found that if I didn't sync svc(), the first thread to get activated would
+tend to get all of the messages before the other threads came alive.
+SHAR_EOF
+ $shar_touch -am 0124153399 'page04.pst' &&
+ chmod 0664 'page04.pst' ||
+ $echo 'restore of' 'page04.pst' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page04.pst:' 'MD5 check failed'
+2212efef5c096791808b00a5212c4376 page04.pst
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pst'`"
+ test 387 -eq "$shar_count" ||
+ $echo 'page04.pst:' 'original size' '387,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page05.pst ==============
+if test -f 'page05.pst' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page05.pst' '(file already exists)'
+else
+ $echo 'x -' extracting 'page05.pst' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page05.pst' &&
+<HR WIDTH="100%">
+<P>
+This is all pretty straight-forward too. One gottcha we avoided was a memory leak
+due to our shutdown message. Notice that svc() enqueues that block without bothering
+to see if there are any more threads to dequeue it. Thats why our dtor can call getq()
+without worrying about blocking infinitely: it knows the message block will be there.
+SHAR_EOF
+ $shar_touch -am 0124153399 'page05.pst' &&
+ chmod 0664 'page05.pst' ||
+ $echo 'restore of' 'page05.pst' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page05.pst:' 'MD5 check failed'
+54b2e8e21aa451c7a3a227da8069bdf7 page05.pst
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pst'`"
+ test 366 -eq "$shar_count" ||
+ $echo 'page05.pst:' 'original size' '366,' 'current size' "$shar_count!"
+ fi
+fi
+rm -fr _sh24521
+exit 0
diff --git a/docs/tutorials/010/page01.html b/docs/tutorials/010/page01.html
index 144f7454fea..d1ce107b6e2 100644
--- a/docs/tutorials/010/page01.html
+++ b/docs/tutorials/010/page01.html
@@ -28,9 +28,32 @@ is a good technique but then you need a way to signal the "listening" threads.
The ACE_Message_Queue is a better approach: Create blocks of data and enqueue
them in one thread while another thread (or threads) dequeue and perform work.
<P>
-<HR WIDTH="100%">
-<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page02.html">Continue
-This Tutorial</A>]</CENTER>
-
-</BODY>
-</HTML>
+Kirthika's Abstract:
+<UL>
+The Message Queue is a FIFO accessible from multiple threads.
+That is, a thread puts the produced blocks of data on the message queue
+to be consumed by some other thread/threads and processed. In this
+tutorial, we see how effectively the Message Queue in a ACE_Task can be
+used to pass data among threads in the thread pool.
+(this is very similar to
+<A HREF="../007/page01.html">Tutorial 7</A>
+ wherein we implemented a
+thread-pool server).Here, actual data is passed between the threads and
+also an ACE_Barrier has been used to provide synchronisation among
+multiple threads.
+<P>
+The Message Queue consists of Message Blocks, each of which has a read
+and write pointer. Using these pointers the message blocks can be
+accessed for reading and writing operations. The ACE_Task::svc() method
+will put the block onto the queue without bothering about the existence
+of a consumer for that block. A thread from the thread pool obtains the
+block from the queue, and checks to see whether the block_type is
+MB_HANGUP. If so, it puts the block back on the queue for its
+peers and exits. Otherwise, it reads the block and processes it before
+releasing it.
+<P>
+This simple tutorial makes us aware of the usage and importance of the
+Message Queue which could be used to our advantage especially for
+multithreaded applications.
+</UL><P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page02.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/010/page02.html b/docs/tutorials/010/page02.html
index 91ce0792147..75d7b9984ba 100644
--- a/docs/tutorials/010/page02.html
+++ b/docs/tutorials/010/page02.html
@@ -11,84 +11,87 @@
<CENTER><B><FONT SIZE=+2>Passing chunks of data through an ACE_Message_Queue</FONT></B></CENTER>
-<HR WIDTH="100%">
<P>
+<HR WIDTH="100%">
We'll look first at <A HREF="message_queue.cpp">main()</A>.
<P>
<HR WIDTH="100%">
<PRE>
-/*
- To illustrate the ACE_Message_Queue, we use a derivative of ACE_Task<>. We
+
+<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.
- */
-#include "task.h"
-#include "block.h"
+ */</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, "%p\n", "open"), -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.
- */
- ACE_OS::sleep (ACE_Time_Value (1));
+ */</font>
+ <font color=#008888>ACE_OS::sleep</font> (ACE_Time_Value (1));
int i;
- for (i = 0; i < iterations; ++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);
- /*
- Grab the "write pointer". This is a pointer into the data area where we
+ <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.
- */
- ACE_OS::sprintf (message->wr_ptr (), "This is message %d.", i);
+ */</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 "do work" on it.
- */
+ 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 "hangup". The default type is
+ 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 (ACE_Message_Block::MB_HANGUP);
+ 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);
@@ -96,18 +99,18 @@ int run_test( int iterations, int threads )
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<> derivative.
- */
+ 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, "(%P|%t) Application exiting\n"));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Application exiting\n</font>"));
- exit(0);
+ return(0);
}
</PRE>
<HR WIDTH="100%">
@@ -123,10 +126,5 @@ 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>
-<HR WIDTH="100%">
-
-<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page03.html">Continue
-This Tutorial</A>]</CENTER>
-
-</BODY>
-</HTML>
+<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page03.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/010/page03.html b/docs/tutorials/010/page03.html
index 566c1eb5b21..b0c618ef8be 100644
--- a/docs/tutorials/010/page03.html
+++ b/docs/tutorials/010/page03.html
@@ -11,9 +11,8 @@
<CENTER><B><FONT SIZE=+2>Passing chunks of data through an ACE_Message_Queue</FONT></B></CENTER>
-<HR WIDTH="100%">
<P>
-
+<HR WIDTH="100%">
Our <A HREF="block.h">Block</A> object is a very simple derivative
of the ACE_Message_Block. The only reason I created it was to prove
that the message blocks to, indeed, get freed when we're done with 'em.
@@ -22,44 +21,48 @@ that the message blocks to, indeed, get freed when we're done with 'em.
<HR WIDTH="100%">
<PRE>
-#include "ace/Message_Block.h"
+<font color=red>// $Id$</font>
+
+<font color=blue>#ifndef</font> <font color=purple>BLOCK_H</font>
+<font color=blue>#define</font> <font color=purple>BLOCK_H</font>
+
+<font color=blue>#include</font> "<font color=green>ace/Message_Block.h</font>"
-/*
- This simple ACE_Message_Block derivative will inform us of it's construction
+<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>)
+# pragma once
+<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font>
+
+<font color=red>/*
+ This simple ACE_Message_Block derivative will inform us of it's construction
and destruction. We'll use this to assure ourselves that we don't have any
memory leaks. In a real application, of course, this isn't necessary.
- */
+ */</font>
class Block : public ACE_Message_Block
{
public:
Block (void)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Block ctor 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Block ctor 0x%x\n</font>", (void *) this));
}
Block (size_t size)
: ACE_Message_Block (size)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Block ctor 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Block ctor 0x%x\n</font>", (void *) this));
}
virtual ~ Block (void)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Block dtor 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Block dtor 0x%x\n</font>", (void *) this));
}
};
+<font color=blue>#endif</font>
</PRE>
<HR WIDTH="100%">
<P>
Ok, nothing really magic there. Some folks just feel a little uncomfortable
not doing an explicit <i>delete</i> on objects they've <i>new</i>'d so I
wanted to show you that the memory really does get cleaned up.
-<P>
-<HR WIDTH="100%">
-
-<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page04.html">Continue
-This Tutorial</A>]</CENTER>
-
-</BODY>
-</HTML>
+ <P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page04.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/010/page04.html b/docs/tutorials/010/page04.html
index c0602095cba..c4d7c5706c7 100644
--- a/docs/tutorials/010/page04.html
+++ b/docs/tutorials/010/page04.html
@@ -11,9 +11,8 @@
<CENTER><B><FONT SIZE=+2>Passing chunks of data through an ACE_Message_Queue</FONT></B></CENTER>
-<HR WIDTH="100%">
<P>
-
+<HR WIDTH="100%">
Our <A HREF="task.h">Task</A> object executes in one or more threads
and reads from the message queue it contains.
<P>
@@ -21,51 +20,62 @@ and reads from the message queue it contains.
<HR WIDTH="100%">
<PRE>
-#include "ace/Task.h"
+<font color=red>// $Id$</font>
+
+<font color=blue>#ifndef</font> <font color=purple>TASK_H</font>
+<font color=blue>#define</font> <font color=purple>TASK_H</font>
+
+<font color=blue>#include</font> "<font color=green>ace/Task.h</font>"
+
+<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>)
+# pragma once
+<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font>
-/*
- Like the thread-pool server tutorial, we'll derive from ACE_Task<>.
+<font color=red>/*
+ Like the thread-pool server tutorial, we'll derive from ACE_Task&lt;>.
Our goal here is to show off the ACE_Message_Queue and the best way
to do that is to use one to pass data between threads. The easiest
- way to create threads is with ACE_Task<>
- */
-class Task : public ACE_Task < ACE_MT_SYNCH >
+ way to create threads is with ACE_Task&lt;>
+ */</font>
+class Task : public ACE_Task &lt; ACE_MT_SYNCH >
{
public:
- typedef ACE_Task < ACE_MT_SYNCH > inherited;
-
- /*
+ typedef ACE_Task &lt; ACE_MT_SYNCH > inherited;
+
+ <font color=red>/*
The constructor/destructor are simple but take care of some
necessary housekeeping.
- */
+ */</font>
Task (void);
~Task (void);
- /*
- To make our Task<> derivative look more like other ACE objects
+ <font color=red>/*
+ To make our Task&lt;> derivative look more like other ACE objects
I've added an open() method. It will take care of activate()ing
the object.
- */
+ */</font>
int open (int threads = 1);
- /*
+ <font color=red>/*
Our worker method
- */
+ */</font>
int svc (void);
- /*
+ <font color=red>/*
All we'll do here is print a message to the user.
- */
+ */</font>
int close (u_long flags = 0);
protected:
- /*
+ <font color=red>/*
Just to be clever, I'll use an ACE_Barrier to cause the threads
to sync in svc() before doing any real work.
- */
+ */</font>
ACE_Barrier *barrier_;
};
+
+<font color=blue>#endif</font>
</PRE>
<HR WIDTH="100%">
<P>
@@ -74,11 +84,5 @@ ACE_Barrier. The application logic really doesn't need it but it is a
handy way to synchronize the threads at the beginning of svc(). In testing
I found that if I didn't sync svc(), the first thread to get activated would
tend to get all of the messages before the other threads came alive.
-<P>
-<HR WIDTH="100%">
-
-<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page05.html">Continue
-This Tutorial</A>]</CENTER>
-
-</BODY>
-</HTML>
+<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page05.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/010/page05.html b/docs/tutorials/010/page05.html
index afcb23f1f1a..ea55a7b1847 100644
--- a/docs/tutorials/010/page05.html
+++ b/docs/tutorials/010/page05.html
@@ -11,8 +11,8 @@
<CENTER><B><FONT SIZE=+2>Passing chunks of data through an ACE_Message_Queue</FONT></B></CENTER>
-<HR WIDTH="100%">
<P>
+<HR WIDTH="100%">
Our <A HREF="task.cpp">Task</A> object definition:
<P>
@@ -20,28 +20,30 @@ Our <A HREF="task.cpp">Task</A> object definition:
<HR WIDTH="100%">
<PRE>
-#include "task.h"
-#include "block.h"
+<font color=red>// $Id$</font>
-/*
+<font color=blue>#include</font> "<font color=green>task.h</font>"
+<font color=blue>#include</font> "<font color=green>block.h</font>"
+
+<font color=red>/*
Set our housekeeping pointer to NULL and tell the user we exist.
- */
-Task::Task (void)
+ */</font>
+<font color=#008888>Task::Task</font> (void)
: barrier_ (0)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task ctor 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Task ctor 0x%x\n</font>", (void *) this));
}
-/*
+<font color=red>/*
Take care of cleanup & tell the user we're going away.
-*/
-Task::~Task (void)
+*/</font>
+<font color=#008888>Task::~Task</font> (void)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task dtor 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Task dtor 0x%x\n</font>", (void *) this));
- /*
+ <font color=red>/*
Get our shutdown notification out of the queue and release it.
- */
+ */</font>
ACE_Message_Block * message;
this->getq(message);
message->release();
@@ -49,103 +51,103 @@ Task::~Task (void)
delete barrier_;
}
-/*
+<font color=red>/*
Open the object to do work. We create the Barrier object and tell
it how many threads we'll be using. Next, we activate the Task
into the number of requested threads.
-*/
-int Task::open (int threads)
+*/</font>
+int <font color=#008888>Task::open</font> (int threads)
{
barrier_ = new ACE_Barrier (threads);
return this->activate (THR_NEW_LWP, threads);
}
-/*
+<font color=red>/*
Tell the user we're closing and invoke the baseclass' close() to
take care of things.
-*/
-int Task::close (u_long flags)
+*/</font>
+int <font color=#008888>Task::close</font> (u_long flags)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task close 0x%x\n", (void *) this));
- return inherited::close (flags);
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Task close 0x%x\n</font>", (void *) this));
+ return <font color=#008888>inherited::close</font> (flags);
}
-/*
+<font color=red>/*
Our svc() method waits for work on the queue and then processes that work.
- */
-int Task::svc (void)
+ */</font>
+int <font color=#008888>Task::svc</font> (void)
{
- /*
+ <font color=red>/*
This will cause all of the threads to wait on this line until all
have invoked this method. The net result is that no thread in the
Task will get a shot at the queue until all of the threads are active.
There's no real need to do this but it's an easy intro into the use
of ACE_Barrier.
- */
+ */</font>
this->barrier_->wait ();
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task 0x%x starts in thread %d\n", (void *) this, ACE_Thread::self ()));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Task 0x%x starts in thread %d\n</font>", (void *) this, <font color=#008888>ACE_Thread::self</font> ()));
- /*
+ <font color=red>/*
Remember that get() needs a reference to a pointer. To save stack
thrashing we'll go ahead and create a pointer outside of the almost-
infinite loop.
- */
+ */</font>
ACE_Message_Block *message;
while (1)
{
- /*
+ <font color=red>/*
Get a message from the queue.
- */
+ */</font>
if (this->getq (message) == -1)
{
- ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "getq"), -1);
+ ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>getq</font>"), -1);
}
- /*
+ <font color=red>/*
If we got the shutdown request, we need to go away.
- */
- if (message->msg_type () == ACE_Message_Block::MB_HANGUP)
+ */</font>
+ if (message->msg_type () == <font color=#008888>ACE_Message_Block::MB_HANGUP</font>)
{
- /*
+ <font color=red>/*
Forward the request to any peer threads.
- */
+ */</font>
this->putq (message);
- /*
+ <font color=red>/*
Leave the infinite loop so that the thread exits.
- */
+ */</font>
break;
}
- /*
+ <font color=red>/*
The message queue stores char* data. We use rd_ptr() to get to
the beginning of the data.
- */
+ */</font>
const char *cp = message->rd_ptr ();
- /*
+ <font color=red>/*
Move the rd_ptr() past the data we read. This isn't real useful
here since we won't be reading any more from the block but it's
a good habit to get into.
- */
+ */</font>
message->rd_ptr( strlen(cp) );
- /*
+ <font color=red>/*
Display the block's address and data to the user.
- */
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Block 0x%x contains (%s)\n", (void *) message, cp));
+ */</font>
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Block 0x%x contains (%s)\n</font>", (void *) message, cp));
- /*
+ <font color=red>/*
Pretend that it takes a while to process the data.
- */
- ACE_OS::sleep (ACE_Time_Value (0, 5000));
+ */</font>
+ <font color=#008888>ACE_OS::sleep</font> (ACE_Time_Value (0, 5000));
- /*
+ <font color=red>/*
Release the message block. Notice that we never delete a message block.
Blocks are reference counted & the release() method will take care of
the delete when there are no more references to the data.
- */
+ */</font>
message->release ();
}
@@ -158,11 +160,5 @@ This is all pretty straight-forward too. One gottcha we avoided was a memory le
due to our shutdown message. Notice that svc() enqueues that block without bothering
to see if there are any more threads to dequeue it. Thats why our dtor can call getq()
without worrying about blocking infinitely: it knows the message block will be there.
-<P>
-<HR WIDTH="100%">
-
-<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page06.html">Continue
-This Tutorial</A>]</CENTER>
-
-</BODY>
-</HTML>
+<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page06.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/010/page06.html b/docs/tutorials/010/page06.html
index 657e05b9d4c..9e50e08c41f 100644
--- a/docs/tutorials/010/page06.html
+++ b/docs/tutorials/010/page06.html
@@ -11,8 +11,8 @@
<CENTER><B><FONT SIZE=+2>Passing chunks of data through an ACE_Message_Queue</FONT></B></CENTER>
-<HR WIDTH="100%">
<P>
+<HR WIDTH="100%">
Since I added Block just to give us output, let's take a look at that output.
@@ -52,13 +52,5 @@ both threads get to do some work and that both close as expected.
It's also worth mentioning that it's just an accident that all of the blocks
are created and enqueued before any are processed. Run the test on a multi-processor
or with more iterations and you'll see some get processed before all are created.
-<P>
-<HR WIDTH="100%">
-
-
-<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>][<A HREF="page07.html">Continue
-This Tutorial</A>]</CENTER>
-</CENTER>
-
-</BODY>
-</HTML>
+<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page07.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/010/page07.html b/docs/tutorials/010/page07.html
index 4df9c0e155e..130fa539f60 100644
--- a/docs/tutorials/010/page07.html
+++ b/docs/tutorials/010/page07.html
@@ -11,8 +11,8 @@
<CENTER><B><FONT SIZE=+2>Passing chunks of data through an ACE_Message_Queue</FONT></B></CENTER>
-<HR WIDTH="100%">
<P>
+<HR WIDTH="100%">
That's it for Tutorial 10. There are some esoteric changes between the thread-pool server
and this application but it's basically the same. In the next tutorial I'll modify this just
@@ -26,11 +26,5 @@ a bit to move non-trivial data through the queue.
<LI><A HREF="task.cpp">task.cpp</A>
<LI><A HREF="task.h">task.h</A>
</UL>
-<HR WIDTH="100%">
-
-
-<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>]</CENTER>
-
-</BODY>
-</HTML>
-
+<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER>
diff --git a/docs/tutorials/011/Makefile b/docs/tutorials/011/Makefile
index 683e82cbcda..3493d9486a1 100644
--- a/docs/tutorials/011/Makefile
+++ b/docs/tutorials/011/Makefile
@@ -52,6 +52,17 @@ Depend : depend
.depend : #
touch .depend
+HTML : #
+ [ -f hdr ] || $(MAKE) UNSHAR
+ perl ../combine *.pre ; chmod +r *.html
+
+SHAR : #
+ [ ! -f combine.shar ] || exit 1
+ shar -T hdr bodies *.pre *.pst > combine.shar && rm -f hdr bodies *.pre *.pst
+
+UNSHAR : #
+ sh combine.shar
+
#----------------------------------------------------------------------------
# Dependencies
#----------------------------------------------------------------------------
diff --git a/docs/tutorials/011/combine.shar b/docs/tutorials/011/combine.shar
new file mode 100644
index 00000000000..9ad5f87a06e
--- /dev/null
+++ b/docs/tutorials/011/combine.shar
@@ -0,0 +1,476 @@
+#!/bin/sh
+# This is a shell archive (produced by GNU sharutils 4.2).
+# To extract the files from this archive, save it to some FILE, remove
+# everything before the `!/bin/sh' line above, then type `sh FILE'.
+#
+# Made on 1999-01-24 15:53 EST by <jcej@chiroptera.tragus.org>.
+# Source directory was `/var/home/jcej/projects/ACE_wrappers/docs/tutorials/011'.
+#
+# Existing files will *not* be overwritten unless `-c' is specified.
+#
+# This shar contains:
+# length mode name
+# ------ ---------- ------------------------------------------
+# 442 -rw-rw-r-- hdr
+# 48 -rw-rw-r-- bodies
+# 439 -rw-rw-r-- page01.pre
+# 164 -rw-rw-r-- page02.pre
+# 174 -rw-rw-r-- page03.pre
+# 127 -rw-rw-r-- page04.pre
+# 2691 -rw-rw-r-- page05.pre
+# 706 -rw-rw-r-- page06.pre
+# 351 -rw-rw-r-- page02.pst
+# 208 -rw-rw-r-- page03.pst
+# 129 -rw-rw-r-- page04.pst
+#
+save_IFS="${IFS}"
+IFS="${IFS}:"
+gettext_dir=FAILED
+locale_dir=FAILED
+first_param="$1"
+for dir in $PATH
+do
+ if test "$gettext_dir" = FAILED && test -f $dir/gettext \
+ && ($dir/gettext --version >/dev/null 2>&1)
+ then
+ set `$dir/gettext --version 2>&1`
+ if test "$3" = GNU
+ then
+ gettext_dir=$dir
+ fi
+ fi
+ if test "$locale_dir" = FAILED && test -f $dir/shar \
+ && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
+ then
+ locale_dir=`$dir/shar --print-text-domain-dir`
+ fi
+done
+IFS="$save_IFS"
+if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
+then
+ echo=echo
+else
+ TEXTDOMAINDIR=$locale_dir
+ export TEXTDOMAINDIR
+ TEXTDOMAIN=sharutils
+ export TEXTDOMAIN
+ echo="$gettext_dir/gettext -s"
+fi
+touch -am 1231235999 $$.touch >/dev/null 2>&1
+if test ! -f 1231235999 && test -f $$.touch; then
+ shar_touch=touch
+else
+ shar_touch=:
+ echo
+ $echo 'WARNING: not restoring timestamps. Consider getting and'
+ $echo "installing GNU \`touch', distributed in GNU File Utilities..."
+ echo
+fi
+rm -f 1231235999 $$.touch
+#
+if mkdir _sh24921; then
+ $echo 'x -' 'creating lock directory'
+else
+ $echo 'failed to create lock directory'
+ exit 1
+fi
+# ============= hdr ==============
+if test -f 'hdr' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'hdr' '(file already exists)'
+else
+ $echo 'x -' extracting 'hdr' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'hdr' &&
+<HTML>
+<HEAD>
+X <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+X <META NAME="Author" CONTENT="James CE Johnson">
+X <TITLE>ACE Tutorial 011</TITLE>
+</HEAD>
+<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F">
+X
+<CENTER><B><FONT SIZE=+2>ACE Tutorial 011</FONT></B></CENTER>
+X
+<CENTER><B><FONT SIZE=+2>Passing non-trivial data through an ACE_Message_Queue</FONT></B></CENTER>
+X
+X
+<P>
+<HR WIDTH="100%">
+SHAR_EOF
+ $shar_touch -am 0124154699 'hdr' &&
+ chmod 0664 'hdr' ||
+ $echo 'restore of' 'hdr' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'hdr:' 'MD5 check failed'
+cf10a170c9ca8512b7051526e2dcf83c hdr
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`"
+ test 442 -eq "$shar_count" ||
+ $echo 'hdr:' 'original size' '442,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= bodies ==============
+if test -f 'bodies' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'bodies' '(file already exists)'
+else
+ $echo 'x -' extracting 'bodies' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'bodies' &&
+PAGE=2
+message_queue.cpp
+task.h task.cpp
+data.h
+SHAR_EOF
+ $shar_touch -am 0124155199 'bodies' &&
+ chmod 0664 'bodies' ||
+ $echo 'restore of' 'bodies' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'bodies:' 'MD5 check failed'
+db3ba3829b49952c833adb921acd3d3f bodies
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`"
+ test 48 -eq "$shar_count" ||
+ $echo 'bodies:' 'original size' '48,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page01.pre ==============
+if test -f 'page01.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page01.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page01.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page01.pre' &&
+<P>
+In the previous tutorial we learned how to put text into a message queue.
+While that may be useful, it isn't very exciting or realistic. In most
+cases you'll need to move complex data structures between your threads.
+<P>
+In this tutorial I'll expand the previous by moving not only a text string
+but also a more complex object. In the next tutorial I'll change things
+again so that we move the complex object a bit more efficiently.
+SHAR_EOF
+ $shar_touch -am 0124154699 'page01.pre' &&
+ chmod 0664 'page01.pre' ||
+ $echo 'restore of' 'page01.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page01.pre:' 'MD5 check failed'
+b6861097131264d54a36a9a204a4da82 page01.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`"
+ test 439 -eq "$shar_count" ||
+ $echo 'page01.pre:' 'original size' '439,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page02.pre ==============
+if test -f 'page02.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page02.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page02.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page02.pre' &&
+We'll look first at <A HREF="message_queue.cpp">main()</A>. A large part of this is
+the same as before, so I've only commented the changes.
+<P>
+X
+<HR WIDTH="100%">
+SHAR_EOF
+ $shar_touch -am 0124154699 'page02.pre' &&
+ chmod 0664 'page02.pre' ||
+ $echo 'restore of' 'page02.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page02.pre:' 'MD5 check failed'
+ccd60d44cf4f9730aa16ff042f324c8e page02.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`"
+ test 164 -eq "$shar_count" ||
+ $echo 'page02.pre:' 'original size' '164,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page03.pre ==============
+if test -f 'page03.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page03.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page03.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page03.pre' &&
+X
+Our Task object <A HREF="task.h">declaration</a> and <A HREF="task.cpp">definition</a>.
+X As with message_queue.cpp,
+I've only commented the changes.
+<P>
+X
+<HR WIDTH="100%">
+SHAR_EOF
+ $shar_touch -am 0124155099 'page03.pre' &&
+ chmod 0664 'page03.pre' ||
+ $echo 'restore of' 'page03.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page03.pre:' 'MD5 check failed'
+e99896d191834752e7e07317af06ea0c page03.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`"
+ test 174 -eq "$shar_count" ||
+ $echo 'page03.pre:' 'original size' '174,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page04.pre ==============
+if test -f 'page04.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page04.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page04.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page04.pre' &&
+X
+Before we go further, let's look at this <A HREF="data.h">Data</A> object
+that's causing all the fuss.
+X
+<P>
+<HR WIDTH="100%">
+SHAR_EOF
+ $shar_touch -am 0124154699 'page04.pre' &&
+ chmod 0664 'page04.pre' ||
+ $echo 'restore of' 'page04.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page04.pre:' 'MD5 check failed'
+4fe23822fef63921fa81cbf97e25bd5e page04.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`"
+ test 127 -eq "$shar_count" ||
+ $echo 'page04.pre:' 'original size' '127,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page05.pre ==============
+if test -f 'page05.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page05.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page05.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page05.pre' &&
+X
+Let's take a look at this new program's output:
+X
+<P>
+<HR WIDTH="100%">
+<PRE>
+[jcej@chiroptera 011]$./message_queue 4 2
+(12108|1024) Task ctor 0xbffff9c8
+(12108|2050) Task 0xbffff9c8 starts in thread 2050
+(12108|1025) Task 0xbffff9c8 starts in thread 1025
+(12108|1024) DataBase ctor 0xbffff9c0
+(12108|1024) Data ctor 0xbffff9c0 for message 0
+(12108|1024) Block ctor 0x8052d08
+(12108|1024) Data dtor 0xbffff9c0
+(12108|1024) DataBase dtor 0xbffff9c0
+(12108|1024) DataBase ctor 0xbffff9c0
+(12108|1024) Data ctor 0xbffff9c0 for message 1
+(12108|1024) Block ctor 0x8052e00
+(12108|1024) Data dtor 0xbffff9c0
+(12108|1024) DataBase dtor 0xbffff9c0
+(12108|1024) DataBase ctor 0xbffff9c0
+(12108|1024) Data ctor 0xbffff9c0 for message 2
+(12108|1024) Block ctor 0x8052ef8
+(12108|1024) Data dtor 0xbffff9c0
+(12108|1024) DataBase dtor 0xbffff9c0
+(12108|1024) DataBase ctor 0xbffff9c0
+(12108|1024) Data ctor 0xbffff9c0 for message 3
+(12108|1024) Block ctor 0x8052ff0
+(12108|1024) Data dtor 0xbffff9c0
+(12108|1024) DataBase dtor 0xbffff9c0
+(12108|1024) Block ctor 0x80530e8
+(12108|1025) Block 0x8052d08 contains (This is message 0.)
+(12108|1025) DataBase ctor 0xbf9ffe20
+(12108|1025) Data ctor 0xbf9ffe20
+(12108|1025) DataBase instance 0xbf9ffe20
+(12108|1025) I am a Data object for message 0
+(12108|1025) Block dtor 0x8052d08
+(12108|1025) Data dtor 0xbf9ffe20
+(12108|1025) DataBase dtor 0xbf9ffe20
+(12108|1025) Block 0x8052e00 contains (This is message 1.)
+(12108|1025) DataBase ctor 0xbf9ffe20
+(12108|1025) Data ctor 0xbf9ffe20
+(12108|1025) DataBase instance 0xbf9ffe20
+(12108|1025) I am a Data object for message 1
+(12108|1025) Block dtor 0x8052e00
+(12108|1025) Data dtor 0xbf9ffe20
+(12108|1025) DataBase dtor 0xbf9ffe20
+(12108|1025) Block 0x8052ef8 contains (This is message 2.)
+(12108|1025) DataBase ctor 0xbf9ffe20
+(12108|1025) Data ctor 0xbf9ffe20
+(12108|1025) DataBase instance 0xbf9ffe20
+(12108|1025) I am a Data object for message 2
+(12108|1025) Block dtor 0x8052ef8
+(12108|1025) Data dtor 0xbf9ffe20
+(12108|1025) DataBase dtor 0xbf9ffe20
+(12108|1025) Block 0x8052ff0 contains (This is message 3.)
+(12108|1025) DataBase ctor 0xbf9ffe20
+(12108|1025) Data ctor 0xbf9ffe20
+(12108|1025) DataBase instance 0xbf9ffe20
+(12108|1025) I am a Data object for message 3
+(12108|2050) Task close 0xbffff9c8
+(12108|1025) Block dtor 0x8052ff0
+(12108|1025) Data dtor 0xbf9ffe20
+(12108|1025) DataBase dtor 0xbf9ffe20
+(12108|1025) Task close 0xbffff9c8
+(12108|1024) Task dtor 0xbffff9c8
+(12108|1024) Block dtor 0x80530e8
+(12108|1024) Application exiting
+[jcej@chiroptera 011]$
+</PRE>
+<HR WIDTH="100%">
+<P>
+Other than being more verbose because of the Data object, this shows us
+the same thing we've seen before.
+<P>
+SHAR_EOF
+ $shar_touch -am 0124154699 'page05.pre' &&
+ chmod 0664 'page05.pre' ||
+ $echo 'restore of' 'page05.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page05.pre:' 'MD5 check failed'
+b95ed571240b8383db0e0c0b07d04971 page05.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`"
+ test 2691 -eq "$shar_count" ||
+ $echo 'page05.pre:' 'original size' '2691,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page06.pre ==============
+if test -f 'page06.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page06.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page06.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page06.pre' &&
+So, this time we stuffed an object into the message queue instead of just text
+data. Each time required two object constructions (and subsequent destructions)
+and two "deep" copy operations on the object. There might actually be times when
+this is OK for your application but I prefer to keep those things down to a
+minimum. In the next tutorial I'll show you a way to do that.
+<P>
+X
+<UL>
+<LI><A HREF="Makefile">Makefile</A>
+<LI><A HREF="block.h">block.h</A>
+<LI><A HREF="data.h">data.h</A>*
+<LI><A HREF="message_queue.cpp">message_queue.cpp</A>
+<LI><A HREF="task.cpp">task.cpp</A>
+<LI><A HREF="task.h">task.h</A>
+</UL>
+X
+* data.h hasn't changed at all from Tutorial 7 so I didn't devote a
+X page to it.
+SHAR_EOF
+ $shar_touch -am 0124155399 'page06.pre' &&
+ chmod 0664 'page06.pre' ||
+ $echo 'restore of' 'page06.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page06.pre:' 'MD5 check failed'
+9b6fcd60df274cb70fc8334580f3ccbc page06.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page06.pre'`"
+ test 706 -eq "$shar_count" ||
+ $echo 'page06.pre:' 'original size' '706,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page02.pst ==============
+if test -f 'page02.pst' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page02.pst' '(file already exists)'
+else
+ $echo 'x -' extracting 'page02.pst' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page02.pst' &&
+<HR WIDTH="100%">
+<P>
+The new trick here is the use of copy() to copy our abstract data object
+into the message block memory. Notice that it's OK to let the Data object
+go out of scope at that point since we've got a separate copy. If you've
+got something with a non-trivial ctor/dtor then this won't work. We'll address
+that in the next tutorial.
+SHAR_EOF
+ $shar_touch -am 0124154699 'page02.pst' &&
+ chmod 0664 'page02.pst' ||
+ $echo 'restore of' 'page02.pst' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page02.pst:' 'MD5 check failed'
+89fa13e74842bc65092e0e6f61fdd889 page02.pst
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pst'`"
+ test 351 -eq "$shar_count" ||
+ $echo 'page02.pst:' 'original size' '351,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page03.pst ==============
+if test -f 'page03.pst' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page03.pst' '(file already exists)'
+else
+ $echo 'x -' extracting 'page03.pst' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page03.pst' &&
+<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>
+SHAR_EOF
+ $shar_touch -am 0124154699 'page03.pst' &&
+ chmod 0664 'page03.pst' ||
+ $echo 'restore of' 'page03.pst' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page03.pst:' 'MD5 check failed'
+82c846e0d43ceb12c5d47686d7f69715 page03.pst
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pst'`"
+ test 208 -eq "$shar_count" ||
+ $echo 'page03.pst:' 'original size' '208,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page04.pst ==============
+if test -f 'page04.pst' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page04.pst' '(file already exists)'
+else
+ $echo 'x -' extracting 'page04.pst' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page04.pst' &&
+<HR WIDTH="100%">
+<P>
+Ok, no mysterious magic on this one. Just a simple object and derivative
+that report their existence.
+<P>
+SHAR_EOF
+ $shar_touch -am 0124154699 'page04.pst' &&
+ chmod 0664 'page04.pst' ||
+ $echo 'restore of' 'page04.pst' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page04.pst:' 'MD5 check failed'
+777ab8789fb82b1e280b9e127983c4b0 page04.pst
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pst'`"
+ test 129 -eq "$shar_count" ||
+ $echo 'page04.pst:' 'original size' '129,' 'current size' "$shar_count!"
+ fi
+fi
+rm -fr _sh24921
+exit 0
diff --git a/docs/tutorials/011/page01.html b/docs/tutorials/011/page01.html
index 26e764d3f84..78fc4cf5e35 100644
--- a/docs/tutorials/011/page01.html
+++ b/docs/tutorials/011/page01.html
@@ -21,10 +21,5 @@ cases you'll need to move complex data structures between your threads.
In this tutorial I'll expand the previous by moving not only a text string
but also a more complex object. In the next tutorial I'll change things
again so that we move the complex object a bit more efficiently.
-<P>
-<HR WIDTH="100%">
-<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page02.html">Continue
-This Tutorial</A>]</CENTER>
-
-</BODY>
-</HTML>
+<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page02.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/011/page02.html b/docs/tutorials/011/page02.html
index 116dcde4d26..1302cf7149d 100644
--- a/docs/tutorials/011/page02.html
+++ b/docs/tutorials/011/page02.html
@@ -11,93 +11,98 @@
<CENTER><B><FONT SIZE=+2>Passing non-trivial data through an ACE_Message_Queue</FONT></B></CENTER>
-<HR WIDTH="100%">
<P>
-
+<HR WIDTH="100%">
We'll look first at <A HREF="message_queue.cpp">main()</A>. A large part of this is
the same as before, so I've only commented the changes.
<P>
<HR WIDTH="100%">
-<P>
<PRE>
-#include "task.h"
-#include "block.h"
-#include "data.h"
+
+<font color=red>// $Id$</font>
+
+<font color=red>/*
+ Most of this is the same as the previous tutorial, so I'll just point out
+ the differences.
+ */</font>
+<font color=blue>#include</font> "<font color=green>task.h</font>"
+<font color=blue>#include</font> "<font color=green>block.h</font>"
+<font color=blue>#include</font> "<font color=green>data.h</font>"
int run_test (int iterations, int threads)
{
- Task task;
-
- if (task.open (threads) == -1)
- {
- ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), -1);
- }
-
- ACE_OS::sleep (ACE_Time_Value (1));
-
- int i;
- for (i = 0; i < iterations; ++i)
- {
- /*
- Construct a Data object that we'll put into the Queue.
- */
- Data data (i);
-
- /*
- Create a block large enough for our Data object as well
- as a text message.
- */
- Block *message = new Block (sizeof (data) + 128);
-
- /*
- As before, put a text message into the block.
- */
- ACE_OS::sprintf (message->wr_ptr (), "This is message %d.", i);
- message->wr_ptr (strlen (message->rd_ptr ()));
-
- *(message->wr_ptr()) = 0; // Null-terminate the string we just wrote
- message->wr_ptr(1); // Move beyond the NULL
-
- /*
- To copy arbitrary data into a message block, we use the copy() method.
- Since it wants a 'const char*', we have to cast our Data
- pointer.
-
- Note that copy() will advance the wr_ptr() for us. This means
- we don't have to do it ourselves! If you do advance it, it
- will be way beyond what you want.
- */
- message->copy ((const char *) &data, sizeof (data));
-
- if (task.putq (message) == -1)
+ 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=#008888>ACE_OS::sleep</font> (ACE_Time_Value (1));
+
+ int i;
+ for (i = 0; i &lt; iterations; ++i)
{
- break;
+ <font color=red>/*
+ Construct a Data object that we'll put into the Queue.
+ */</font>
+ Data data (i);
+
+ <font color=red>/*
+ Create a block large enough for our Data object as well as a text
+ message.
+ */</font>
+ Block *message = new Block (sizeof (data) + 128);
+
+ <font color=red>/*
+ As before, put a text message into the block.
+ */</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 ()));
+
+ *(message->wr_ptr ()) = 0; <font color=red>// Null-terminate the string we just wrote</font>
+
+ message->wr_ptr (1); <font color=red>// Move beyond the NULL</font>
+
+ <font color=red>/*
+ To copy arbitrary data into a message block, we use the copy() method.
+ Since it wants a 'const char*', we have to cast our Data
+ pointer.
+
+ Note that copy() will advance the wr_ptr() for us. This means
+ we don't have to do it ourselves! If you do advance it, it
+ will be way beyond what you want.
+ */</font>
+ message->copy ((const char *) &data, sizeof (data));
+
+ if (task.putq (message) == -1)
+ {
+ break;
+ }
}
- }
- Block *message = new Block ();
- message->msg_type (ACE_Message_Block::MB_HANGUP);
- task.putq (message);
+ Block *message = new Block ();
+ message->msg_type (<font color=#008888>ACE_Message_Block::MB_HANGUP</font>);
+ task.putq (message);
- task.wait ();
+ task.wait ();
- return (0);
+ return (0);
}
int main (int argc, char *argv[])
{
- int iterations = argc > 1 ? atoi (argv[1]) : 4;
- int threads = argc > 2 ? atoi (argv[2]) : 2;
+ int iterations = argc > 1 ? atoi (argv[1]) : 4;
+ int threads = argc > 2 ? atoi (argv[2]) : 2;
- (void) run_test (iterations, threads);
+ (void) run_test (iterations, threads);
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Application exiting\n"));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Application exiting\n</font>"));
- exit (0);
+ return (0);
}
</PRE>
-
<HR WIDTH="100%">
<P>
The new trick here is the use of copy() to copy our abstract data object
@@ -105,11 +110,5 @@ into the message block memory. Notice that it's OK to let the Data object
go out of scope at that point since we've got a separate copy. If you've
got something with a non-trivial ctor/dtor then this won't work. We'll address
that in the next tutorial.
-<P>
-<HR WIDTH="100%">
-
-<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page03.html">Continue
-This Tutorial</A>]</CENTER>
-
-</BODY>
-</HTML>
+<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page03.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/011/page03.html b/docs/tutorials/011/page03.html
index 12d121e0834..515b50763e4 100644
--- a/docs/tutorials/011/page03.html
+++ b/docs/tutorials/011/page03.html
@@ -11,29 +11,68 @@
<CENTER><B><FONT SIZE=+2>Passing non-trivial data through an ACE_Message_Queue</FONT></B></CENTER>
-<HR WIDTH="100%">
<P>
+<HR WIDTH="100%">
-Our <A HREF="task.cpp">Task</A> object definition. As with message_queue.cpp,
+Our Task object <A HREF="task.h">declaration</a> and <A HREF="task.cpp">definition</a>.
+ As with message_queue.cpp,
I've only commented the changes.
<P>
<HR WIDTH="100%">
+<HR width=50%><P><center>task.h</center><HR width=50%>
<PRE>
-#include "task.h"
-#include "block.h"
-#include "data.h"
+<font color=red>// $Id$</font>
+
+<font color=blue>#ifndef</font> <font color=purple>TASK_H</font>
+<font color=blue>#define</font> <font color=purple>TASK_H</font>
+
+<font color=blue>#include</font> "<font color=green>ace/Task.h</font>"
+
+<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>)
+# pragma once
+<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font>
+
+class Task : public ACE_Task &lt; ACE_MT_SYNCH >
+{
+public:
+
+ typedef ACE_Task &lt; ACE_MT_SYNCH > inherited;
+
+ Task (void);
+ ~Task (void);
+
+ int open (int threads = 1);
+
+ int svc (void);
-Task::Task (void)
+ int close (u_long flags = 0);
+
+protected:
+ ACE_Barrier * barrier_;
+};
+
+<font color=blue>#endif</font>
+</PRE>
+<HR width=50%><P><center>task.cpp</center><HR width=50%>
+<PRE>
+
+<font color=red>// $Id$</font>
+
+<font color=blue>#include</font> "<font color=green>task.h</font>"
+<font color=blue>#include</font> "<font color=green>block.h</font>"
+<font color=blue>#include</font> "<font color=green>data.h</font>"
+
+<font color=#008888>Task::Task</font> (void)
: barrier_ (0)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task ctor 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Task ctor 0x%x\n</font>", (void *) this));
}
-Task::~Task (void)
+<font color=#008888>Task::~Task</font> (void)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task dtor 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Task dtor 0x%x\n</font>", (void *) this));
ACE_Message_Block *message;
this->getq (message);
@@ -42,32 +81,32 @@ Task::~Task (void)
delete barrier_;
}
-int Task::open (int threads)
+int <font color=#008888>Task::open</font> (int threads)
{
barrier_ = new ACE_Barrier (threads);
return this->activate (THR_NEW_LWP, threads);
}
-int Task::close (u_long flags)
+int <font color=#008888>Task::close</font> (u_long flags)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task close 0x%x\n", (void *) this));
- return inherited::close (flags);
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Task close 0x%x\n</font>", (void *) this));
+ return <font color=#008888>inherited::close</font> (flags);
}
-int Task::svc (void)
+int <font color=#008888>Task::svc</font> (void)
{
this->barrier_->wait ();
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task 0x%x starts in thread %d\n", (void *) this, ACE_Thread::self ()));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Task 0x%x starts in thread %d\n</font>", (void *) this, <font color=#008888>ACE_Thread::self</font> ()));
ACE_Message_Block *message;
while (1)
{
if (this->getq (message) == -1)
{
- ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "getq"), -1);
+ ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>getq</font>"), -1);
}
- if (message->msg_type () == ACE_Message_Block::MB_HANGUP)
+ if (message->msg_type () == <font color=#008888>ACE_Message_Block::MB_HANGUP</font>)
{
this->putq (message);
@@ -75,30 +114,30 @@ int Task::svc (void)
}
const char *cp = message->rd_ptr ();
- message->rd_ptr (strlen (cp) + 1); // Don't forget to skip the NULL we
- // inserted
+ message->rd_ptr (strlen (cp) + 1); <font color=red>// Don't forget to skip the NULL we</font>
+ <font color=red>// inserted</font>
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Block 0x%x contains (%s)\n", (void *) message, cp));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Block 0x%x contains (%s)\n</font>", (void *) message, cp));
- /*
+ <font color=red>/*
Create a Data object into which we can extract the message block
contents.
- */
+ */</font>
Data data;
- /*
+ <font color=red>/*
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.
+ */</font>
+ <font color=#008888>ACE_OS::memmove</font> ((char *) &data, message->rd_ptr (), sizeof (data));
+ message->rd_ptr (sizeof (data)); <font color=red>// Move the rd_ptr() beyond the data.</font>
- /*
+ <font color=red>/*
Invoke a couple of method calls on the object we constructed.
- */
+ */</font>
data.who_am_i ();
data.what_am_i ();
- /*
+ <font color=red>/*
An alternate approach:
Data * data;
@@ -110,10 +149,10 @@ int Task::svc (void)
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...
- */
+ */</font>
- ACE_OS::sleep (ACE_Time_Value (0, 5000));
+ <font color=#008888>ACE_OS::sleep</font> (ACE_Time_Value (0, 5000));
message->release ();
}
@@ -127,10 +166,5 @@ 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="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page04.html">Continue
-This Tutorial</A>]</CENTER>
-
-</BODY>
-</HTML>
+<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page04.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/011/page04.html b/docs/tutorials/011/page04.html
index 9d1178d924c..2b612b29a16 100644
--- a/docs/tutorials/011/page04.html
+++ b/docs/tutorials/011/page04.html
@@ -11,8 +11,8 @@
<CENTER><B><FONT SIZE=+2>Passing non-trivial data through an ACE_Message_Queue</FONT></B></CENTER>
-<HR WIDTH="100%">
<P>
+<HR WIDTH="100%">
Before we go further, let's look at this <A HREF="data.h">Data</A> object
that's causing all the fuss.
@@ -21,26 +21,31 @@ that's causing all the fuss.
<HR WIDTH="100%">
<PRE>
+<font color=red>// $Id$</font>
+
+<font color=blue>#ifndef</font> <font color=purple>DATA_H</font>
+<font color=blue>#define</font> <font color=purple>DATA_H</font>
+
class DataBase
{
public:
DataBase (void)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) DataBase ctor 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) DataBase ctor 0x%x\n</font>", (void *) this));
}
virtual ~ DataBase (void)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) DataBase dtor 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) DataBase dtor 0x%x\n</font>", (void *) this));
}
void who_am_i (void)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) DataBase instance 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) DataBase instance 0x%x\n</font>", (void *) this));
}
virtual void what_am_i (void)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) I am a DataBase object\n"));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) I am a DataBase object\n</font>"));
}
};
@@ -51,22 +56,22 @@ public:
Data (void)
: message_ (-1)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Data ctor 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Data ctor 0x%x\n</font>", (void *) this));
}
Data (int message)
: message_ (message)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Data ctor 0x%x for message %d\n", (void *) this, message_));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Data ctor 0x%x for message %d\n</font>", (void *) this, message_));
}
virtual ~ Data (void)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Data dtor 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Data dtor 0x%x\n</font>", (void *) this));
}
void what_am_i (void)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) I am a Data object for message %d\n", message_));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) I am a Data object for message %d\n</font>", message_));
}
protected:
@@ -74,18 +79,12 @@ protected:
};
+<font color=blue>#endif</font>
</PRE>
<HR WIDTH="100%">
<P>
Ok, no mysterious magic on this one. Just a simple object and derivative
that report their existence.
<P>
-<HR WIDTH="100%">
-
-
-<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>][<A HREF="page05.html">Continue
-This Tutorial</A>]</CENTER>
-</CENTER>
-
-</BODY>
-</HTML>
+<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page05.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/011/page05.html b/docs/tutorials/011/page05.html
index 921991f4bc2..51689bf5e04 100644
--- a/docs/tutorials/011/page05.html
+++ b/docs/tutorials/011/page05.html
@@ -11,8 +11,8 @@
<CENTER><B><FONT SIZE=+2>Passing non-trivial data through an ACE_Message_Queue</FONT></B></CENTER>
-<HR WIDTH="100%">
<P>
+<HR WIDTH="100%">
Let's take a look at this new program's output:
@@ -88,12 +88,5 @@ Let's take a look at this new program's output:
Other than being more verbose because of the Data object, this shows us
the same thing we've seen before.
<P>
-<HR WIDTH="100%">
-
-
-<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>][<A HREF="page06.html">Continue
-This Tutorial</A>]</CENTER>
-</CENTER>
-
-</BODY>
-</HTML>
+<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page06.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/011/page06.html b/docs/tutorials/011/page06.html
index 306575747b6..36621e53210 100644
--- a/docs/tutorials/011/page06.html
+++ b/docs/tutorials/011/page06.html
@@ -11,8 +11,8 @@
<CENTER><B><FONT SIZE=+2>Passing non-trivial data through an ACE_Message_Queue</FONT></B></CENTER>
-<HR WIDTH="100%">
<P>
+<HR WIDTH="100%">
So, this time we stuffed an object into the message queue instead of just text
data. Each time required two object constructions (and subsequent destructions)
and two "deep" copy operations on the object. There might actually be times when
@@ -23,16 +23,12 @@ minimum. In the next tutorial I'll show you a way to do that.
<UL>
<LI><A HREF="Makefile">Makefile</A>
<LI><A HREF="block.h">block.h</A>
-<LI><A HREF="data.h">data.h</A>
+<LI><A HREF="data.h">data.h</A>*
<LI><A HREF="message_queue.cpp">message_queue.cpp</A>
<LI><A HREF="task.cpp">task.cpp</A>
<LI><A HREF="task.h">task.h</A>
</UL>
-<HR WIDTH="100%">
-
-
-<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>]</CENTER>
-
-</BODY>
-</HTML>
+* data.h hasn't changed at all from Tutorial 7 so I didn't devote a
+ page to it.<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER>
diff --git a/docs/tutorials/012/Makefile b/docs/tutorials/012/Makefile
index 683e82cbcda..3493d9486a1 100644
--- a/docs/tutorials/012/Makefile
+++ b/docs/tutorials/012/Makefile
@@ -52,6 +52,17 @@ Depend : depend
.depend : #
touch .depend
+HTML : #
+ [ -f hdr ] || $(MAKE) UNSHAR
+ perl ../combine *.pre ; chmod +r *.html
+
+SHAR : #
+ [ ! -f combine.shar ] || exit 1
+ shar -T hdr bodies *.pre *.pst > combine.shar && rm -f hdr bodies *.pre *.pst
+
+UNSHAR : #
+ sh combine.shar
+
#----------------------------------------------------------------------------
# Dependencies
#----------------------------------------------------------------------------
diff --git a/docs/tutorials/012/data.h b/docs/tutorials/012/block.h
index 54e8e55e87c..06179af2757 100644
--- a/docs/tutorials/012/data.h
+++ b/docs/tutorials/012/block.h
@@ -1,77 +1,10 @@
// $Id$
-#ifndef DATA_H
-#define DATA_H
+#ifndef BLOCK_H
+#define BLOCK_H
-#include "ace/Message_Block.h"
-
-#if !defined (ACE_LACKS_PRAGMA_ONCE)
-# pragma once
-#endif /* ACE_LACKS_PRAGMA_ONCE */
-
-/*
- We'll start by defining a basic unit of work that can be put into
- the message queue. The threads in the pool will expect to find one
- of these in each message block and will invoke a method or two.
-*/
-class Unit_Of_Work
-{
-public:
- Unit_Of_Work (void)
- {
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Unit_Of_Work ctor 0x%x\n", (void *) this));
- }
- virtual ~ Unit_Of_Work (void)
- {
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Unit_Of_Work dtor 0x%x\n", (void *) this));
- }
-
- void who_am_i (void)
- {
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Unit_Of_Work instance 0x%x\n", (void *) this));
- }
-
- virtual void what_am_i (void)
- {
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) I am a Unit_Of_Work object\n"));
- }
-
-};
-
-/*
- Now, we specialize the Unit_Of_Work object to do something
- different. By overriding the virtual methods, we can do whatever
- "real work" is needed but the thread pool doesn't have to know the specifics.
-*/
-class Work : public Unit_Of_Work
-{
-public:
- Work (void)
- : message_ (-1)
- {
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Work ctor 0x%x\n", (void *) this));
- }
-
- Work (int message)
- : message_ (message)
- {
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Work ctor 0x%x for message %d\n", (void *) this, message_));
- }
- virtual ~ Work (void)
- {
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Work dtor 0x%x\n", (void *) this));
- }
-
- void what_am_i (void)
- {
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) I am a Work object for message %d\n", message_));
- }
-
-protected:
- int message_;
-
-};
+#include "work.h"
/*
We derive a Message_Block from ACE_Message_Block and teach it about
diff --git a/docs/tutorials/012/combine.shar b/docs/tutorials/012/combine.shar
new file mode 100644
index 00000000000..860a94f3ce5
--- /dev/null
+++ b/docs/tutorials/012/combine.shar
@@ -0,0 +1,451 @@
+#!/bin/sh
+# This is a shell archive (produced by GNU sharutils 4.2).
+# To extract the files from this archive, save it to some FILE, remove
+# everything before the `!/bin/sh' line above, then type `sh FILE'.
+#
+# Made on 1999-01-24 16:08 EST by <jcej@chiroptera.tragus.org>.
+# Source directory was `/var/home/jcej/projects/ACE_wrappers/docs/tutorials/012'.
+#
+# Existing files will *not* be overwritten unless `-c' is specified.
+#
+# This shar contains:
+# length mode name
+# ------ ---------- ------------------------------------------
+# 430 -rw-rw-r-- hdr
+# 56 -rw-rw-r-- bodies
+# 487 -rw-rw-r-- page01.pre
+# 263 -rw-rw-r-- page02.pre
+# 397 -rw-rw-r-- page03.pre
+# 154 -rw-rw-r-- page04.pre
+# 183 -rw-rw-r-- page05.pre
+# 448 -rw-rw-r-- page06.pre
+# 395 -rw-rw-r-- page02.pst
+# 399 -rw-rw-r-- page03.pst
+# 162 -rw-rw-r-- page04.pst
+# 449 -rw-rw-r-- page05.pst
+#
+save_IFS="${IFS}"
+IFS="${IFS}:"
+gettext_dir=FAILED
+locale_dir=FAILED
+first_param="$1"
+for dir in $PATH
+do
+ if test "$gettext_dir" = FAILED && test -f $dir/gettext \
+ && ($dir/gettext --version >/dev/null 2>&1)
+ then
+ set `$dir/gettext --version 2>&1`
+ if test "$3" = GNU
+ then
+ gettext_dir=$dir
+ fi
+ fi
+ if test "$locale_dir" = FAILED && test -f $dir/shar \
+ && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
+ then
+ locale_dir=`$dir/shar --print-text-domain-dir`
+ fi
+done
+IFS="$save_IFS"
+if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
+then
+ echo=echo
+else
+ TEXTDOMAINDIR=$locale_dir
+ export TEXTDOMAINDIR
+ TEXTDOMAIN=sharutils
+ export TEXTDOMAIN
+ echo="$gettext_dir/gettext -s"
+fi
+touch -am 1231235999 $$.touch >/dev/null 2>&1
+if test ! -f 1231235999 && test -f $$.touch; then
+ shar_touch=touch
+else
+ shar_touch=:
+ echo
+ $echo 'WARNING: not restoring timestamps. Consider getting and'
+ $echo "installing GNU \`touch', distributed in GNU File Utilities..."
+ echo
+fi
+rm -f 1231235999 $$.touch
+#
+if mkdir _sh25217; then
+ $echo 'x -' 'creating lock directory'
+else
+ $echo 'failed to create lock directory'
+ exit 1
+fi
+# ============= hdr ==============
+if test -f 'hdr' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'hdr' '(file already exists)'
+else
+ $echo 'x -' extracting 'hdr' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'hdr' &&
+<HTML>
+<HEAD>
+X <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+X <META NAME="Author" CONTENT="James CE Johnson">
+X <TITLE>ACE Tutorial 012</TITLE>
+</HEAD>
+<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F">
+X
+<CENTER><B><FONT SIZE=+2>ACE Tutorial 012</FONT></B></CENTER>
+X
+<CENTER><B><FONT SIZE=+2>Passing classes through ACE_Message_Queue</FONT></B></CENTER>
+X
+X
+<P>
+<HR WIDTH="100%">
+SHAR_EOF
+ $shar_touch -am 0124160599 'hdr' &&
+ chmod 0664 'hdr' ||
+ $echo 'restore of' 'hdr' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'hdr:' 'MD5 check failed'
+1acf94beccfa9e953b2f55e02a0bb2e6 hdr
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`"
+ test 430 -eq "$shar_count" ||
+ $echo 'hdr:' 'original size' '430,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= bodies ==============
+if test -f 'bodies' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'bodies' '(file already exists)'
+else
+ $echo 'x -' extracting 'bodies' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'bodies' &&
+PAGE=2
+work.h
+block.h
+message_queue.cpp
+task.h task.cpp
+SHAR_EOF
+ $shar_touch -am 0124160199 'bodies' &&
+ chmod 0664 'bodies' ||
+ $echo 'restore of' 'bodies' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'bodies:' 'MD5 check failed'
+3ad29f0a25bfe156b37630c9ee9f715c bodies
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`"
+ test 56 -eq "$shar_count" ||
+ $echo 'bodies:' 'original size' '56,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page01.pre ==============
+if test -f 'page01.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page01.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page01.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page01.pre' &&
+<P>
+Last time around we put an object into a message queue by using the
+copy() method to create a duplicate of the object. That's probably OK
+for simple objects that aren't very large. However, if you have an
+object that contains pointers or tons of data then that approach is
+going to cause problems.
+<P>
+What we'll do in this tutorial is specialize the ACE_Message_Block
+object so that it can carry our data more efficiently. As you'll see,
+this isn't very difficult at all.
+<P>
+SHAR_EOF
+ $shar_touch -am 0124160599 'page01.pre' &&
+ chmod 0664 'page01.pre' ||
+ $echo 'restore of' 'page01.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page01.pre:' 'MD5 check failed'
+9c50f824bc7cf43d3c8c33fe007a9288 page01.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`"
+ test 487 -eq "$shar_count" ||
+ $echo 'page01.pre:' 'original size' '487,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page02.pre ==============
+if test -f 'page02.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page02.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page02.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page02.pre' &&
+We normally start by looking at main() and work our way out from
+there. This time, I want to start by showing you the ACE_Message_Block
+derivative but before that, I have to introduce you to the Work object
+and it's baseclass Unit_Of_Work
+<P>
+<HR WIDTH="100%">
+SHAR_EOF
+ $shar_touch -am 0124160599 'page02.pre' &&
+ chmod 0664 'page02.pre' ||
+ $echo 'restore of' 'page02.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page02.pre:' 'MD5 check failed'
+67c405a8085b9ad581912c2aec135ed4 page02.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`"
+ test 263 -eq "$shar_count" ||
+ $echo 'page02.pre:' 'original size' '263,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page03.pre ==============
+if test -f 'page03.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page03.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page03.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page03.pre' &&
+<P>
+In the previous tutorial we moved our complex data into the queue by
+copy()ing it directly into the message block's data area. I hope that
+most readers got a queasy feeling when I did that. It just isn't a
+good idea...
+<P>
+A better idea would be to teach the message queue about our data types
+(or at least a baseclass) so that it can more efficiently handle things:
+<P>
+<HR WIDTH="100%">
+SHAR_EOF
+ $shar_touch -am 0124160599 'page03.pre' &&
+ chmod 0664 'page03.pre' ||
+ $echo 'restore of' 'page03.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page03.pre:' 'MD5 check failed'
+d8f77e8098d5086c71c164de8a78c29c page03.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`"
+ test 397 -eq "$shar_count" ||
+ $echo 'page03.pre:' 'original size' '397,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page04.pre ==============
+if test -f 'page04.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page04.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page04.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page04.pre' &&
+<P>
+Ok, finally we get to main(). Sorry for the diversion but it was
+important to lay some of that groundwork before getting here.
+<P>
+<HR WIDTH="100%">
+SHAR_EOF
+ $shar_touch -am 0124160599 'page04.pre' &&
+ chmod 0664 'page04.pre' ||
+ $echo 'restore of' 'page04.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page04.pre:' 'MD5 check failed'
+8989e75934f20e9b74d38a2d3687613a page04.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`"
+ test 154 -eq "$shar_count" ||
+ $echo 'page04.pre:' 'original size' '154,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page05.pre ==============
+if test -f 'page05.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page05.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page05.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page05.pre' &&
+<P>
+The Task is the only object we've not been through yet. I'll go ahead
+and show both the header and cpp on this one page since the header
+isn't very large.
+<P>
+<HR WIDTH="100%">
+SHAR_EOF
+ $shar_touch -am 0124160599 'page05.pre' &&
+ chmod 0664 'page05.pre' ||
+ $echo 'restore of' 'page05.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page05.pre:' 'MD5 check failed'
+499934db529597846d10ca45610bc52e page05.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`"
+ test 183 -eq "$shar_count" ||
+ $echo 'page05.pre:' 'original size' '183,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page06.pre ==============
+if test -f 'page06.pre' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page06.pre' '(file already exists)'
+else
+ $echo 'x -' extracting 'page06.pre' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page06.pre' &&
+<P>
+Once again, we come to the end of a tutorial. By creating a simple
+specialization of ACE_Message_Block, we've been able to remove a lot
+of complexity and erorr potential from our previous implementation.
+<UL>
+<LI><A HREF="Makefile">Makefile</A>
+<LI><A HREF="message_queue.cpp">message_queue.cpp</A>
+<LI><A HREF="work.h">work.h</A>
+<LI><A HREF="block.h">block.h</A>
+<LI><A HREF="task.h">task.h</A>
+<LI><A HREF="task.cpp">task.cpp</A>
+</UL>
+<P>
+SHAR_EOF
+ $shar_touch -am 0124160599 'page06.pre' &&
+ chmod 0664 'page06.pre' ||
+ $echo 'restore of' 'page06.pre' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page06.pre:' 'MD5 check failed'
+64afabb236ea02927914d03f258e620b page06.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page06.pre'`"
+ test 448 -eq "$shar_count" ||
+ $echo 'page06.pre:' 'original size' '448,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page02.pst ==============
+if test -f 'page02.pst' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page02.pst' '(file already exists)'
+else
+ $echo 'x -' extracting 'page02.pst' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page02.pst' &&
+<HR WIDTH="100%">
+<P>
+This is basically the same as the <i>DataBase</i> in the previous
+tutorial but I've changed the name to be more generic. The feeling is
+that a <i>Data</i> object would be a C struct but an <i>Work</i>
+object would be a class with methods.
+<P>
+Now that you know what we'll be putting into the queue, lets go to the
+next page where I specialize the ACE_Message_Block.
+<P>
+SHAR_EOF
+ $shar_touch -am 0124160599 'page02.pst' &&
+ chmod 0664 'page02.pst' ||
+ $echo 'restore of' 'page02.pst' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page02.pst:' 'MD5 check failed'
+961a6ad181e25a24b2500abe013b5379 page02.pst
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pst'`"
+ test 395 -eq "$shar_count" ||
+ $echo 'page02.pst:' 'original size' '395,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page03.pst ==============
+if test -f 'page03.pst' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page03.pst' '(file already exists)'
+else
+ $echo 'x -' extracting 'page03.pst' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page03.pst' &&
+<HR WIDTH="100%">
+<P>
+Ok, this looks pretty good. We just construct our specialized
+Message_Block instead of the generic ACE_Message_Block and let it
+carry our data along. When our application is done with the message
+block and release()es it, we know that our work object will also be
+taken care of.
+<P>
+Let's now go to main() and see what we had to change there to use this
+specialization.
+<P>
+SHAR_EOF
+ $shar_touch -am 0124160599 'page03.pst' &&
+ chmod 0664 'page03.pst' ||
+ $echo 'restore of' 'page03.pst' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page03.pst:' 'MD5 check failed'
+282e52e360c416f48db0dc454354bfda page03.pst
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pst'`"
+ test 399 -eq "$shar_count" ||
+ $echo 'page03.pst:' 'original size' '399,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page04.pst ==============
+if test -f 'page04.pst' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page04.pst' '(file already exists)'
+else
+ $echo 'x -' extracting 'page04.pst' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page04.pst' &&
+<HR WIDTH="100%">
+<P>
+That certainly looks cleaner than the previous approach! If you
+blink, you'll miss the part where the Work object goes into the Queue.
+<P>
+SHAR_EOF
+ $shar_touch -am 0124160599 'page04.pst' &&
+ chmod 0664 'page04.pst' ||
+ $echo 'restore of' 'page04.pst' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page04.pst:' 'MD5 check failed'
+245db1d5e74203bf085369bb47d646db page04.pst
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pst'`"
+ test 162 -eq "$shar_count" ||
+ $echo 'page04.pst:' 'original size' '162,' 'current size' "$shar_count!"
+ fi
+fi
+# ============= page05.pst ==============
+if test -f 'page05.pst' && test "$first_param" != -c; then
+ $echo 'x -' SKIPPING 'page05.pst' '(file already exists)'
+else
+ $echo 'x -' extracting 'page05.pst' '(text)'
+ sed 's/^X//' << 'SHAR_EOF' > 'page05.pst' &&
+<HR WIDTH="100%">
+<P>
+Like main() this is actually simpler than the previous tutorial. It's
+much cleaner to carry around a pointer to the object we're working
+with than to try copying data.
+<P>
+The only complication is the new ACE_Barrier. It's a pretty simple
+object that makes it easy for you to synch threads in this way. You
+could do some fancy tricks with mutexes, counters & semaphores but why
+bother when the Barrier already exists.
+<P>
+SHAR_EOF
+ $shar_touch -am 0124160599 'page05.pst' &&
+ chmod 0664 'page05.pst' ||
+ $echo 'restore of' 'page05.pst' 'failed'
+ if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+ && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+ md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+ || $echo 'page05.pst:' 'MD5 check failed'
+1db9b33059c7da0ee0b30f0d077bd443 page05.pst
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pst'`"
+ test 449 -eq "$shar_count" ||
+ $echo 'page05.pst:' 'original size' '449,' 'current size' "$shar_count!"
+ fi
+fi
+rm -fr _sh25217
+exit 0
diff --git a/docs/tutorials/012/message_queue.cpp b/docs/tutorials/012/message_queue.cpp
index 140931ba1de..53870076378 100644
--- a/docs/tutorials/012/message_queue.cpp
+++ b/docs/tutorials/012/message_queue.cpp
@@ -1,7 +1,8 @@
// $Id$
-#include "data.h"
+#include "block.h"
+#include "work.h"
#include "task.h"
/*
diff --git a/docs/tutorials/012/page01.html b/docs/tutorials/012/page01.html
index 21b540cece4..c2c2021b217 100644
--- a/docs/tutorials/012/page01.html
+++ b/docs/tutorials/012/page01.html
@@ -24,9 +24,5 @@ What we'll do in this tutorial is specialize the ACE_Message_Block
object so that it can carry our data more efficiently. As you'll see,
this isn't very difficult at all.
<P>
-<HR WIDTH="100%">
-<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page02.html">Continue
-This Tutorial</A>]</CENTER>
-
-</BODY>
-</HTML>
+<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page02.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/012/page02.html b/docs/tutorials/012/page02.html
index cfe4eb8df3b..2742e9954d2 100644
--- a/docs/tutorials/012/page02.html
+++ b/docs/tutorials/012/page02.html
@@ -13,7 +13,6 @@
<P>
<HR WIDTH="100%">
-<P>
We normally start by looking at main() and work our way out from
there. This time, I want to start by showing you the ACE_Message_Block
derivative but before that, I have to introduce you to the Work object
@@ -22,68 +21,81 @@ and it's baseclass Unit_Of_Work
<HR WIDTH="100%">
<PRE>
-/*
+<font color=red>// $Id$</font>
+
+<font color=blue>#ifndef</font> <font color=purple>WORK_H</font>
+<font color=blue>#define</font> <font color=purple>WORK_H</font>
+
+<font color=blue>#include</font> "<font color=green>ace/Message_Block.h</font>"
+
+<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>)
+# pragma once
+<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font>
+
+<font color=red>/*
We'll start by defining a basic unit of work that can be put into
the message queue. The threads in the pool will expect to find one
of these in each message block and will invoke a method or two.
-*/
+*/</font>
class Unit_Of_Work
{
public:
Unit_Of_Work (void)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Unit_Of_Work ctor 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Unit_Of_Work ctor 0x%x\n</font>", (void *) this));
}
virtual ~ Unit_Of_Work (void)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Unit_Of_Work dtor 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Unit_Of_Work dtor 0x%x\n</font>", (void *) this));
}
void who_am_i (void)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Unit_Of_Work instance 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Unit_Of_Work instance 0x%x\n</font>", (void *) this));
}
virtual void what_am_i (void)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) I am a Unit_Of_Work object\n"));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) I am a Unit_Of_Work object\n</font>"));
}
};
-/*
+<font color=red>/*
Now, we specialize the Unit_Of_Work object to do something
- different. By overriding the virtual method, we can do whatever
- "real work" is needed but the thread pool doesn't have to know the specifics.
-*/
+ different. By overriding the virtual methods, we can do whatever
+ "<font color=green>real work</font>" is needed but the thread pool doesn't have to know the specifics.
+*/</font>
class Work : public Unit_Of_Work
{
public:
Work (void)
: message_ (-1)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Work ctor 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Work ctor 0x%x\n</font>", (void *) this));
}
Work (int message)
: message_ (message)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Work ctor 0x%x for message %d\n", (void *) this, message_));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Work ctor 0x%x for message %d\n</font>", (void *) this, message_));
}
virtual ~ Work (void)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Work dtor 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Work dtor 0x%x\n</font>", (void *) this));
}
void what_am_i (void)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) I am a Work object for message %d\n", message_));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) I am a Work object for message %d\n</font>", message_));
}
protected:
int message_;
};
+
+<font color=blue>#endif</font>
</PRE>
<HR WIDTH="100%">
<P>
@@ -95,10 +107,5 @@ object would be a class with methods.
Now that you know what we'll be putting into the queue, lets go to the
next page where I specialize the ACE_Message_Block.
<P>
-<HR WIDTH="100%">
-<P>
-<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page03.html">Continue
-This Tutorial</A>]</CENTER>
-
-</BODY>
-</HTML>
+<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page03.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/012/page03.html b/docs/tutorials/012/page03.html
index 2a952a114fa..cff54395ec2 100644
--- a/docs/tutorials/012/page03.html
+++ b/docs/tutorials/012/page03.html
@@ -24,43 +24,51 @@ A better idea would be to teach the message queue about our data types
<P>
<HR WIDTH="100%">
<PRE>
-/*
+
+<font color=red>// $Id$</font>
+
+<font color=blue>#ifndef</font> <font color=purple>BLOCK_H</font>
+<font color=blue>#define</font> <font color=purple>BLOCK_H</font>
+
+<font color=blue>#include</font> "<font color=green>work.h</font>"
+
+<font color=red>/*
We derive a Message_Block from ACE_Message_Block and teach it about
- our Unit_Of_Work object. When our task's svc() method pulls a block
- out of the queue, it can then invoke the virtual methods of the work
+ our Unit_Of_Work object. When our task's svc() method pulls a block
+ out of the queue, it can then invoke the virtual methods of the work
object safely. In this implementation we've also retained the
original ACE_Message_Block functionallity so that we can use the
underlying ACE_Data_Block objects to store data other than our
Unit_Of_Work.
-*/
+*/</font>
class Message_Block : public ACE_Message_Block
{
public:
typedef ACE_Message_Block inherited;
- /*
+ <font color=red>/*
Construct our underlying ACE_Message_Block with the requested
data size and initialize our Unit_Of_Work pointer with the
given object instance. Note that this Message_Block instance
now assumes ownership of the Unit_Of_Work and will delete it
when the Message_Block is deleted.
- */
+ */</font>
Message_Block( size_t size, Unit_Of_Work * _data )
: inherited(size), data_(_data)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Message_Block ctor 0x%x for 0x%x\n", (void *) this, data_));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Message_Block ctor 0x%x for 0x%x\n</font>", (void *) this, data_));
}
- ~Message_Block(void)
+ ~Message_Block(void)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Message_Block dtor 0x%x for 0x%x\n", (void *) this, data_));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Message_Block dtor 0x%x for 0x%x\n</font>", (void *) this, data_));
delete data_;
}
- /*
+ <font color=red>/*
Return the Unit_Of_Work so that the task can invoke methods on
it.
- */
+ */</font>
Unit_Of_Work * data(void)
{
return this->data_;
@@ -69,16 +77,18 @@ public:
protected:
Unit_Of_Work * data_;
- /*
+ <font color=red>/*
Disallow these very dangerous operations.
If we were to copy a Message_Block object then the data_
pointer would get copied and we would eventually end up
deleting the same object multiple times! That's not good. By
preventing the copy, we can avoid this.
- */
+ */</font>
Message_Block &operator= (const Message_Block &);
Message_Block (const Message_Block &);
};
+
+<font color=blue>#endif</font>
</PRE>
<HR WIDTH="100%">
<P>
@@ -91,10 +101,5 @@ taken care of.
Let's now go to main() and see what we had to change there to use this
specialization.
<P>
-<HR WIDTH="100%">
-<P>
-<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page04.html">Continue
-This Tutorial</A>]</CENTER>
-
-</BODY>
-</HTML>
+<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page04.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/012/page04.html b/docs/tutorials/012/page04.html
index b83dd9e6ca2..bd503680338 100644
--- a/docs/tutorials/012/page04.html
+++ b/docs/tutorials/012/page04.html
@@ -19,71 +19,78 @@ important to lay some of that groundwork before getting here.
<P>
<HR WIDTH="100%">
<PRE>
-/*
+
+<font color=red>// $Id$</font>
+
+<font color=blue>#include</font> "<font color=green>block.h</font>"
+<font color=blue>#include</font> "<font color=green>work.h</font>"
+<font color=blue>#include</font> "<font color=green>task.h</font>"
+
+<font color=red>/*
I want to be sure that our Task object gets destructed correctly, so
I'll do most of the application 'work' in run_test() instead of
main()
-*/
+*/</font>
int run_test (int iterations, int threads)
{
- /*
+ <font color=red>/*
Create the Task which is our thread pool for doing work
- */
+ */</font>
Task task;
if (task.open (threads) == -1)
{
- ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), -1);
+ ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>open</font>"), -1);
}
- /*
+ <font color=red>/*
Give the Task a chance to enter it's svc() method. This isn't
really necessary and you probably wouldn't do it in a real
application but it makes the output more interesting.
- */
- ACE_OS::sleep (ACE_Time_Value (1));
+ */</font>
+ <font color=#008888>ACE_OS::sleep</font> (ACE_Time_Value (1));
- for (int i = 0; i < iterations; ++i)
+ for (int i = 0; i &lt; iterations; ++i)
{
- /*
+ <font color=red>/*
Construct a Work object that we'll put into the Queue. Give it
the iteration number so that it can identify itself in the output.
- */
+ */</font>
Work * data = new Work(i);
- /*
+ <font color=red>/*
Create a block that contains our Work object but also has
enough room for a text message.
- */
+ */</font>
Message_Block *message = new Message_Block (128, data);
- /*
+ <font color=red>/*
As before, put a text message into the block.
- */
- ACE_OS::sprintf (message->wr_ptr (), "This is message %d.", i);
+ */</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 ())+1);
- /*
+ <font color=red>/*
Add the work to our thread pool
- */
+ */</font>
if (task.putq (message) == -1)
{
break;
}
}
- /*
+ <font color=red>/*
Insert a HANGUP message block to tell the thread pool to shut
itself down.
- */
+ */</font>
Message_Block *message = new Message_Block (0,0);
- message->msg_type (ACE_Message_Block::MB_HANGUP);
+ message->msg_type (<font color=#008888>ACE_Message_Block::MB_HANGUP</font>);
task.putq (message);
- /*
+ <font color=red>/*
Wait for the all threads of the Task to exit. It is rather rude
to let the Task go out of scope without doing this first.
- */
+ */</font>
task.wait ();
return (0);
@@ -91,23 +98,23 @@ int run_test (int iterations, int threads)
int main (int argc, char *argv[])
{
- /*
+ <font color=red>/*
Give the user a chance to override the default number of
iterations and pool threads.
- */
+ */</font>
int iterations = argc > 1 ? atoi (argv[1]) : 4;
int threads = argc > 2 ? atoi (argv[2]) : 2;
- /*
+ <font color=red>/*
Use the function above to do the actual test. As I said, this
lets us see the Task go out of scope and destruct before our
- "exiting" message below.
- */
+ "<font color=green>exiting</font>" message below.
+ */</font>
(void) run_test (iterations, threads);
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Application exiting\n"));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Application exiting\n</font>"));
- exit (0);
+ return (0);
}
</PRE>
<HR WIDTH="100%">
@@ -115,10 +122,5 @@ int main (int argc, char *argv[])
That certainly looks cleaner than the previous approach! If you
blink, you'll miss the part where the Work object goes into the Queue.
<P>
-<HR WIDTH="100%">
-<P>
-<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page05.html">Continue
-This Tutorial</A>]</CENTER>
-
-</BODY>
-</HTML>
+<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page05.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/012/page05.html b/docs/tutorials/012/page05.html
index 236100f5c82..593fda6615b 100644
--- a/docs/tutorials/012/page05.html
+++ b/docs/tutorials/012/page05.html
@@ -19,23 +19,35 @@ and show both the header and cpp on this one page since the header
isn't very large.
<P>
<HR WIDTH="100%">
+<HR width=50%><P><center>task.h</center><HR width=50%>
<PRE>
-/*
+<font color=red>// $Id$</font>
+
+<font color=blue>#ifndef</font> <font color=purple>TASK_H</font>
+<font color=blue>#define</font> <font color=purple>TASK_H</font>
+
+<font color=blue>#include</font> "<font color=green>ace/Task.h</font>"
+
+<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>)
+# pragma once
+<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font>
+
+<font color=red>/*
This is our basic thread-pool Task. We have a choice of pool size
on the open() and the usual svc() and close() methods.
A new addition is the ACE_Barrier object. This will allow the
synchronization of our svc() methods so that they all start at the
- "same" time. The normal case may allow one thread to start working
+ "<font color=green>same</font>" time. The normal case may allow one thread to start working
earlier than others. There's no real harm in it but you can get
- better "work by thread" statistics if they start out together.
-*/
-class Task : public ACE_Task < ACE_MT_SYNCH >
+ better "<font color=green>work by thread</font>" statistics if they start out together.
+*/</font>
+class Task : public ACE_Task &lt; ACE_MT_SYNCH >
{
public:
- typedef ACE_Task < ACE_MT_SYNCH > inherited;
+ typedef ACE_Task &lt; ACE_MT_SYNCH > inherited;
Task (void);
~Task (void);
@@ -49,20 +61,29 @@ public:
protected:
ACE_Barrier * barrier_;
};
+
+<font color=blue>#endif</font>
</PRE>
-<HR WIDTH="50%">
+<HR width=50%><P><center>task.cpp</center><HR width=50%>
<PRE>
-/*
+
+<font color=red>// $Id$</font>
+
+<font color=blue>#include</font> "<font color=green>task.h</font>"
+<font color=blue>#include</font> "<font color=green>block.h</font>"
+<font color=blue>#include</font> "<font color=green>work.h</font>"
+
+<font color=red>/*
Boring default constructor. Be sure our barrier_ is initialized in
case we get destructed before opened.
-*/
-Task::Task (void)
+*/</font>
+<font color=#008888>Task::Task</font> (void)
: barrier_ (0)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task ctor 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Task ctor 0x%x\n</font>", (void *) this));
}
-/*
+<font color=red>/*
You'll see in the svc() method that when we get a shutdown request,
we always putq() it back into our message queue. The last thread in
the pool will do this also and result in there always being one
@@ -71,10 +92,10 @@ Task::Task (void)
We also delete the barrier_ object we used to synch the svc()
methods.
-*/
-Task::~Task (void)
+*/</font>
+<font color=#008888>Task::~Task</font> (void)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task dtor 0x%x\n", (void *) this));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Task dtor 0x%x\n</font>", (void *) this));
ACE_Message_Block *message;
this->getq (message);
@@ -83,108 +104,108 @@ Task::~Task (void)
delete barrier_;
}
-/*
+<font color=red>/*
The ACE_Barrier needs to know how many threads it will be working
for. For that reason, we have to put off it's construction until we
get here. We then pass the thread count through to our base class'
activate().
-*/
-int Task::open (int threads)
+*/</font>
+int <font color=#008888>Task::open</font> (int threads)
{
barrier_ = new ACE_Barrier (threads);
return this->activate (THR_NEW_LWP, threads);
}
-/*
+<font color=red>/*
We don't really do anything here but I wanted to provide a message
in the output.
-*/
-int Task::close (u_long flags)
+*/</font>
+int <font color=#008888>Task::close</font> (u_long flags)
{
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task close 0x%x\n", (void *) this));
- return inherited::close (flags);
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Task close 0x%x\n</font>", (void *) this));
+ return <font color=#008888>inherited::close</font> (flags);
}
-/*
+<font color=red>/*
Now the svc() method where everything interesting happens.
-*/
-int Task::svc (void)
+*/</font>
+int <font color=#008888>Task::svc</font> (void)
{
- /*
+ <font color=red>/*
All of the threads will block here until the last thread
arrives. They will all then be free to begin doing work.
- */
+ */</font>
this->barrier_->wait ();
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task 0x%x starts in thread %u\n", (void *) this, ACE_Thread::self ()));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Task 0x%x starts in thread %u\n</font>", (void *) this, <font color=#008888>ACE_Thread::self</font> ()));
- // Where we getq() the message
+ <font color=red>// Where we getq() the message</font>
ACE_Message_Block *message;
- // What we really put into the queue is a Message_Block, so we'll
- // cast the 'message' to 'message_block' after getting it. I'm
- // going through some extra steps here just to be explicit
+ <font color=red>// What we really put into the queue is a Message_Block, so we'll</font>
+ <font color=red>// cast the 'message' to 'message_block' after getting it. I'm</font>
+ <font color=red>// going through some extra steps here just to be explicit</font>
Message_Block * message_block;
- // The baseclass of the work object we put into the queue. Notice
- // that we can use this and not bother with the Work object at all.
+ <font color=red>// The baseclass of the work object we put into the queue. Notice</font>
+ <font color=red>// that we can use this and not bother with the Work object at all.</font>
Unit_Of_Work * unit_of_work;
while (1)
{
- // Get the message...
+ <font color=red>// Get the message...</font>
if (this->getq (message) == -1)
{
- ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "getq"), -1);
+ ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>getq</font>"), -1);
}
- // Is it a shutdown request?
- if (message->msg_type () == ACE_Message_Block::MB_HANGUP)
+ <font color=red>// Is it a shutdown request?</font>
+ if (message->msg_type () == <font color=#008888>ACE_Message_Block::MB_HANGUP</font>)
{
- // Send the shutdown to all of our pool peers
+ <font color=red>// Send the shutdown to all of our pool peers</font>
this->putq (message);
break;
}
- // Cast the pointer to our specialized Message_Block. We could
- // have done this at the getq() call but I wanted to be explicit
- // about what we're doing here
+ <font color=red>// Cast the pointer to our specialized Message_Block. We could</font>
+ <font color=red>// have done this at the getq() call but I wanted to be explicit</font>
+ <font color=red>// about what we're doing here</font>
message_block = (Message_Block*)message;
- /*
+ <font color=red>/*
Since we left alone the ACE_Data_Block used by the
Message_Block we have chosen to use it to send arbitrary data
as well.
- */
+ */</font>
const char *cp = message_block->rd_ptr ();
- // Don't forget to skip the NULL we inserted
+ <font color=red>// Don't forget to skip the NULL we inserted</font>
message_block->rd_ptr (strlen (cp) + 1);
- /*
+ <font color=red>/*
Get the Unit_Of_Work pointer out of our specialized
Message_Block. Since the methods of interest are virtual, we
don't have to know what kind of work we're to do.
- */
+ */</font>
unit_of_work = message_block->data();
- /*
+ <font color=red>/*
Invoke a couple of method calls on the object we constructed.
- */
+ */</font>
unit_of_work->who_am_i ();
unit_of_work->what_am_i ();
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Block 0x%x contains (%s)\n", (void *) message, cp));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Block 0x%x contains (%s)\n</font>", (void *) message, cp));
- /*
+ <font color=red>/*
Pretend that the work takes a little time to process. This
prevents one thread from getting all of the action. In a real
system you wouldn't need to do this since the work really
would take time to complete.
- */
- ACE_OS::sleep (ACE_Time_Value (0, 5000));
+ */</font>
+ <font color=#008888>ACE_OS::sleep</font> (ACE_Time_Value (0, 5000));
- /*
+ <font color=red>/*
Release the message block and allow the unit of work to also go
away.
- */
+ */</font>
message->release ();
}
@@ -202,10 +223,5 @@ object that makes it easy for you to synch threads in this way. You
could do some fancy tricks with mutexes, counters & semaphores but why
bother when the Barrier already exists.
<P>
-<HR WIDTH="100%">
-<P>
-<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page06.html">Continue
-This Tutorial</A>]</CENTER>
-
-</BODY>
-</HTML>
+<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page06.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/012/page06.html b/docs/tutorials/012/page06.html
index f7282da57c9..76f28616cd0 100644
--- a/docs/tutorials/012/page06.html
+++ b/docs/tutorials/012/page06.html
@@ -20,14 +20,11 @@ of complexity and erorr potential from our previous implementation.
<UL>
<LI><A HREF="Makefile">Makefile</A>
<LI><A HREF="message_queue.cpp">message_queue.cpp</A>
-<LI><A HREF="data.h">data.h</A>
+<LI><A HREF="work.h">work.h</A>
+<LI><A HREF="block.h">block.h</A>
<LI><A HREF="task.h">task.h</A>
<LI><A HREF="task.cpp">task.cpp</A>
</UL>
<P>
-<HR WIDTH="100%">
-<P>
-<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>]</CENTER>
-
-</BODY>
-</HTML>
+<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER>
diff --git a/docs/tutorials/012/task.cpp b/docs/tutorials/012/task.cpp
index 5c7a382db16..06231e309b0 100644
--- a/docs/tutorials/012/task.cpp
+++ b/docs/tutorials/012/task.cpp
@@ -2,7 +2,8 @@
// $Id$
#include "task.h"
-#include "data.h"
+#include "block.h"
+#include "work.h"
/*
Boring default constructor. Be sure our barrier_ is initialized in
diff --git a/docs/tutorials/012/work.h b/docs/tutorials/012/work.h
new file mode 100644
index 00000000000..9523fe80b37
--- /dev/null
+++ b/docs/tutorials/012/work.h
@@ -0,0 +1,76 @@
+
+// $Id$
+
+#ifndef WORK_H
+#define WORK_H
+
+#include "ace/Message_Block.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/*
+ We'll start by defining a basic unit of work that can be put into
+ the message queue. The threads in the pool will expect to find one
+ of these in each message block and will invoke a method or two.
+*/
+class Unit_Of_Work
+{
+public:
+ Unit_Of_Work (void)
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) Unit_Of_Work ctor 0x%x\n", (void *) this));
+ }
+ virtual ~ Unit_Of_Work (void)
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) Unit_Of_Work dtor 0x%x\n", (void *) this));
+ }
+
+ void who_am_i (void)
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) Unit_Of_Work instance 0x%x\n", (void *) this));
+ }
+
+ virtual void what_am_i (void)
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) I am a Unit_Of_Work object\n"));
+ }
+
+};
+
+/*
+ Now, we specialize the Unit_Of_Work object to do something
+ different. By overriding the virtual methods, we can do whatever
+ "real work" is needed but the thread pool doesn't have to know the specifics.
+*/
+class Work : public Unit_Of_Work
+{
+public:
+ Work (void)
+ : message_ (-1)
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) Work ctor 0x%x\n", (void *) this));
+ }
+
+ Work (int message)
+ : message_ (message)
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) Work ctor 0x%x for message %d\n", (void *) this, message_));
+ }
+ virtual ~ Work (void)
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) Work dtor 0x%x\n", (void *) this));
+ }
+
+ void what_am_i (void)
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) I am a Work object for message %d\n", message_));
+ }
+
+protected:
+ int message_;
+
+};
+
+#endif