summaryrefslogtreecommitdiff
path: root/docs/tutorials
diff options
context:
space:
mode:
authorjcej <jcej@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1999-01-19 01:30:46 +0000
committerjcej <jcej@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1999-01-19 01:30:46 +0000
commit6e40b6f889f6702e9a9b729fd8bbe21bde9b77dd (patch)
tree8f9fc5fea90882ebdf8063ea56e3ad16d03a0af6 /docs/tutorials
parent642a0e08e922a476f8a3b1f64214f239c376978d (diff)
downloadATCD-6e40b6f889f6702e9a9b729fd8bbe21bde9b77dd.tar.gz
*** empty log message ***
Diffstat (limited to 'docs/tutorials')
-rw-r--r--docs/tutorials/006/Makefile12
-rw-r--r--docs/tutorials/006/client_handler.cpp2
-rw-r--r--docs/tutorials/006/combine.shar492
-rw-r--r--docs/tutorials/006/page01.html43
-rw-r--r--docs/tutorials/006/page02.html303
-rw-r--r--docs/tutorials/006/page03.html223
-rw-r--r--docs/tutorials/006/page04.html91
-rw-r--r--docs/tutorials/006/page05.html177
-rw-r--r--docs/tutorials/006/page06.html13
9 files changed, 889 insertions, 467 deletions
diff --git a/docs/tutorials/006/Makefile b/docs/tutorials/006/Makefile
index 53fe1f26bff..82143ac4792 100644
--- a/docs/tutorials/006/Makefile
+++ b/docs/tutorials/006/Makefile
@@ -88,6 +88,18 @@ 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/006/client_handler.cpp b/docs/tutorials/006/client_handler.cpp
index ad254f3f130..a4292fec2bd 100644
--- a/docs/tutorials/006/client_handler.cpp
+++ b/docs/tutorials/006/client_handler.cpp
@@ -84,7 +84,7 @@ int Client_Handler::open (void *_acceptor)
get_remote_addr() method to get 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
+ can query it to find out the client's host name, TCP/IP address, TCP/IP
port value and so forth. One word of warning: the get_host_name()
method of ACE_INET_Addr may return you an empty string if your name server
can't resolve it. On the other hand, get_host_addr() will always give you
diff --git a/docs/tutorials/006/combine.shar b/docs/tutorials/006/combine.shar
new file mode 100644
index 00000000000..41392122821
--- /dev/null
+++ b/docs/tutorials/006/combine.shar
@@ -0,0 +1,492 @@
+#!/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-18 20:31 EST by <jcej@chiroptera.tragus.org>.
+# Source directory was `/var/home/jcej/projects/ACE_wrappers/docs/tutorials/006'.
+#
+# Existing files will *not* be overwritten unless `-c' is specified.
+#
+# This shar contains:
+# length mode name
+# ------ ---------- ------------------------------------------
+# 605 -rw-rw-r-- hdr
+# 72 -rw-rw-r-- bodies
+# 1973 -rw-rw-r-- page01.pre
+# 252 -rw-rw-r-- page02.pre
+# 507 -rw-rw-r-- page03.pre
+# 227 -rw-rw-r-- page04.pre
+# 231 -rw-rw-r-- page05.pre
+# 697 -rw-rw-r-- page06.pre
+# 89 -rw-rw-r-- page02.pst
+# 168 -rw-rw-r-- page03.pst
+# 175 -rw-rw-r-- page04.pst
+# 528 -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 _sh23703; 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="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]">
+X <META NAME="Author" CONTENT="James CE Johnson">
+X <META NAME="Description" CONTENT="A first step towards using ACE productively">
+X <TITLE>ACE Tutorial 006</TITLE>
+</HEAD>
+<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F">
+X
+<CENTER><B><FONT SIZE=+2>ACE Tutorial 006</FONT></B></CENTER>
+X
+<CENTER><B><FONT SIZE=+2>Creating a thread-per-connection server</FONT></B></CENTER>
+X
+X
+<P>
+<HR WIDTH="100%">
+SHAR_EOF
+ $shar_touch -am 0118202399 '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'
+3289bf210fdf2f4b9d0a23b69c79a82f hdr
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`"
+ test 605 -eq "$shar_count" ||
+ $echo 'hdr:' 'original size' '605,' '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
+server.cpp
+client_acceptor.h
+client_handler.h
+client_handler.cpp
+SHAR_EOF
+ $shar_touch -am 0118202399 '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'
+1f7383474ecfc75883354e67afaf1b3b bodies
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`"
+ test 72 -eq "$shar_count" ||
+ $echo 'bodies:' 'original size' '72,' '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' &&
+X
+<P>In this tutorial, we're going to extend Tutorial 5 to create a thread-per-connection
+server.&nbsp; This implementation will create a new thread for each client
+which connects to us.&nbsp; The ACE_Reactor is still used but only for
+accepting new connections.&nbsp; The Client_Handler objects won't be registered
+with the reactor.&nbsp; Instead, they'll be responsible for monitoring
+their peer() directly.
+<P>
+Abstract:<sup>*</sup>
+<ul>
+Here, we build a thread-per-connection simple server. This is the next
+step from a simple single-threaded server towards a multithreaded
+server.
+<p>
+We make use of the Strategy Pattern in this example.
+The ACE_Acceptor inherits form the ACE_Acceptor_Base class which
+facilitates us to implement various different concurrency strategies
+depending on whether the server is single-threaded or the server creates
+a new thread per connection. This also allows us to extend the
+capabilities of the server in the future by implementing a different
+strategy.
+<p>
+This information is passed on to the Client_Handler
+(remember ACE_Acceptor < Client_Handler, ACE_SOCK_ACCEPTOR > ?).
+The Client_Handler is an ACE_Svc_Handler as the Svc_Handler is a
+derivative of the Event_Handler and is associated with
+ACE_Sock_Stream. It is also derived form the ACE_Task class which allows
+us to have a thread per connection.
+<p>
+We incorporate the data processing in the svc() method, which will be
+called per thread for the thread-per-connection server.
+<p>
+Note that here all the Client_Handler objects aren't registered with the
+reactor. The Reactor is only used to accept client connections. Once a
+thread has been deicated per connection, the Client Handler object
+reponsible for that client connection now takes up the job of the
+reactor and handles future events.
+<p>
+Thus a simple, thread-per-connection server has been built which doesnt
+delve too deeply into mutli-threading issues.
+</ul>
+<font size=-1>* Abstract by Kirthika as always</font>
+SHAR_EOF
+ $shar_touch -am 0118203099 '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'
+c4255ba9e01891294697e95d6edbc326 page01.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`"
+ test 1973 -eq "$shar_count" ||
+ $echo 'page01.pre:' 'original size' '1973,' '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' &&
+<P>Again, we begin with <A HREF="server.cpp">server.cpp.</A>&nbsp; If you
+look closely you will see that the only difference between this and the
+Tutorial 5 implementation is a single comment.
+X
+<P>
+<HR WIDTH="100%"><FONT FACE="Arial,Helvetica"></FONT>
+SHAR_EOF
+ $shar_touch -am 0118202399 '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'
+e9e18b8add5d997189fb16e67d1467b2 page02.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`"
+ test 252 -eq "$shar_count" ||
+ $echo 'page02.pre:' 'original size' '252,' '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 <A HREF="client_acceptor.h">client_acceptor.h</A>, we've extended
+our object just a bit.&nbsp; The primary reason is to allow us to select
+the previous single-threaded implementation or our new thread-per-connection
+implementation.&nbsp; Client_Acceptor itself doesn't use this information
+but makes it available to the Client_Handler objects it creates.&nbsp;
+If we wanted a single-strategy implementation, we would have made no changes
+to the Tutorial 5 version of this file.
+X
+<P>
+<HR WIDTH="100%">
+SHAR_EOF
+ $shar_touch -am 0118202399 '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'
+40dd465ac9815a2c35375ccdbad0c98b page03.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`"
+ test 507 -eq "$shar_count" ||
+ $echo 'page03.pre:' 'original size' '507,' '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><A HREF="client_handler.h">client_handler.h</A>
+shows a few more changes than the previous sources.&nbsp; The important
+change is the addition of a svc() method where our connection thread will
+exist.
+X
+<P>
+<HR WIDTH="100%">
+SHAR_EOF
+ $shar_touch -am 0118202399 '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'
+8256aff03563fbc281403fc5bb970e69 page04.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`"
+ test 227 -eq "$shar_count" ||
+ $echo 'page04.pre:' 'original size' '227,' '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><A HREF="client_handler.cpp">client_handler.cpp</A> exposes all the
+things I've been hinting at.&nbsp; Pay special attention to the decision
+made in open() as well as the bit of cleverness in svc().
+X
+<P>
+<HR WIDTH="100%">
+SHAR_EOF
+ $shar_touch -am 0118202399 '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'
+08278c0477a109e107b680424bf70a9d page05.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`"
+ test 231 -eq "$shar_count" ||
+ $echo 'page05.pre:' 'original size' '231,' '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>That's it for Tutorial 6.&nbsp; With very little effort we've managed
+to extend the previous single-threaded server to an implementation which
+allows runtime selection of single or multi-threaded operation.&nbsp; In
+Tutorial 7 we'll extend that again to allow a thread-pool choice in addition
+to the current two.
+X
+<P>For reference, here's the file list again:
+<UL>
+<LI>
+<A HREF="Makefile">Makefile</A></LI>
+X
+<LI>
+<A HREF="client_acceptor.h">client_acceptor.h</A></LI>
+X
+<LI>
+<A HREF="client_handler.cpp">client_handler.cpp</A></LI>
+X
+<LI>
+<A HREF="client_handler.h">client_handler.h</A></LI>
+X
+<LI>
+<A HREF="server.cpp">server.cpp</A></LI>
+X
+<LI>
+<A HREF="fix.Makefile">fix.Makefile</A></LI>
+</UL>
+SHAR_EOF
+ $shar_touch -am 0118202399 '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'
+0adca372a5154acf673cc373d2acaf5a page06.pre
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page06.pre'`"
+ test 697 -eq "$shar_count" ||
+ $echo 'page06.pre:' 'original size' '697,' '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%">
+X
+<P>Let's move along and see what happend to the Client_Acceptor.
+X
+<P>
+SHAR_EOF
+ $shar_touch -am 0118202399 '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'
+0188a5ff7cacc123676e420ac5432207 page02.pst
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pst'`"
+ test 89 -eq "$shar_count" ||
+ $echo 'page02.pst:' 'original size' '89,' '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%">
+X
+<P>Ok, so far we haven't done much to change our concurrency strategy.&nbsp;
+Let's move on to the Client_Handler and see if it has changed any.
+X
+<P>
+SHAR_EOF
+ $shar_touch -am 0118202399 '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'
+7743577254d06f5848b5e50f3b6c3014 page03.pst
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pst'`"
+ test 168 -eq "$shar_count" ||
+ $echo 'page03.pst:' 'original size' '168,' '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%">
+X
+<P>So... we've added a svc() method and alluded to changes in open().&nbsp;
+Let's move on to the object definition and see what all the fuss is about.
+X
+<P>
+SHAR_EOF
+ $shar_touch -am 0118202399 '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'
+dfe0897cc3f000b69c16c87dd1596281 page04.pst
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pst'`"
+ test 175 -eq "$shar_count" ||
+ $echo 'page04.pst:' 'original size' '175,' '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%">
+X
+<P>Well, that's it!&nbsp; After all the talk &amp; the hype, you would
+have expected it to be more difficult to create a multi-threaded server.&nbsp;
+Surprise!&nbsp; It really is that easy.&nbsp; You still have to handle
+contention issues which we haven't addressed here and that is a rather
+nasty topic.&nbsp; Still, for the simple case, this is all you have to
+do.
+X
+<P>The next page is the last for this tutorial.&nbsp; Head on over there
+&amp; we'll round up the file list one last time.
+X
+<P>
+SHAR_EOF
+ $shar_touch -am 0118202399 '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'
+c09a518d674612c988d52bba9333a943 page05.pst
+SHAR_EOF
+ else
+ shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pst'`"
+ test 528 -eq "$shar_count" ||
+ $echo 'page05.pst:' 'original size' '528,' 'current size' "$shar_count!"
+ fi
+fi
+rm -fr _sh23703
+exit 0
diff --git a/docs/tutorials/006/page01.html b/docs/tutorials/006/page01.html
index cd20f343e91..28a3d392d33 100644
--- a/docs/tutorials/006/page01.html
+++ b/docs/tutorials/006/page01.html
@@ -22,12 +22,39 @@ which connects to us.&nbsp; The ACE_Reactor is still used but only for
accepting new connections.&nbsp; The Client_Handler objects won't be registered
with the reactor.&nbsp; Instead, they'll be responsible for monitoring
their peer() directly.
-
<P>
-<HR WIDTH="100%">
-<CENTER>[<A HREF="..">Tutorial
-Index</A>] [<A HREF="page02.html">Continue
-This Tutorial</A>]</CENTER>
-
-</BODY>
-</HTML>
+Abstract:<sup>*</sup>
+<ul>
+Here, we build a thread-per-connection simple server. This is the next
+step from a simple single-threaded server towards a multithreaded
+server.
+<p>
+We make use of the Strategy Pattern in this example.
+The ACE_Acceptor inherits form the ACE_Acceptor_Base class which
+facilitates us to implement various different concurrency strategies
+depending on whether the server is single-threaded or the server creates
+a new thread per connection. This also allows us to extend the
+capabilities of the server in the future by implementing a different
+strategy.
+<p>
+This information is passed on to the Client_Handler
+(remember ACE_Acceptor < Client_Handler, ACE_SOCK_ACCEPTOR > ?).
+The Client_Handler is an ACE_Svc_Handler as the Svc_Handler is a
+derivative of the Event_Handler and is associated with
+ACE_Sock_Stream. It is also derived form the ACE_Task class which allows
+us to have a thread per connection.
+<p>
+We incorporate the data processing in the svc() method, which will be
+called per thread for the thread-per-connection server.
+<p>
+Note that here all the Client_Handler objects aren't registered with the
+reactor. The Reactor is only used to accept client connections. Once a
+thread has been deicated per connection, the Client Handler object
+reponsible for that client connection now takes up the job of the
+reactor and handles future events.
+<p>
+Thus a simple, thread-per-connection server has been built which doesnt
+delve too deeply into mutli-threading issues.
+</ul>
+<font size=-1>* Abstract by Kirthika as always</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/006/page02.html b/docs/tutorials/006/page02.html
index 29d4c457ff1..53413a1e094 100644
--- a/docs/tutorials/006/page02.html
+++ b/docs/tutorials/006/page02.html
@@ -15,191 +15,140 @@
<P>
<HR WIDTH="100%">
-
<P>Again, we begin with <A HREF="server.cpp">server.cpp.</A>&nbsp; If you
look closely you will see that the only difference between this and the
Tutorial 5 implementation is a single comment.
<P>
<HR WIDTH="100%"><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">// $Id: server.cpp,v 1.1 1998/08/30 13:38:28
-jcej Exp $</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; We try to keep main() very
-simple.&nbsp; One of the ways we do that is to push</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; much of the complicated stuff
-into worker objects.&nbsp; In this case, we only</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; need to include the acceptor
-header in our main source file.&nbsp; We let it</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; worry about the "real work".</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">#include "client_acceptor.h"</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; As before, we create a simple
-signal handler that will set our finished</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; flag.&nbsp; There are, of
-course, more elegant ways to handle program shutdown</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; requests but that isn't really
-our focus right now, so we'll just do the</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; easiest thing.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">static sig_atomic_t finished = 0;</FONT>
-<BR><FONT FACE="Arial,Helvetica">extern "C" void handler (int)</FONT>
-<BR><FONT FACE="Arial,Helvetica">{</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; finished = 1;</FONT>
-<BR><FONT FACE="Arial,Helvetica">}</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; A server has to listen for
-clients at a known TCP/IP port.&nbsp; The default ACE</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; port is 10002 (at least on
-my system) and that's good enough for what&nbsp; we</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; want to do here.&nbsp; Obviously,
-a more robust application would take a command</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; line parameter or read from
-a configuration file or do some other&nbsp; clever</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; thing.&nbsp; Just like the
-signal handler above, though, that's what we want to</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; focus on, so we're taking
-the easy way out.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">static const u_short PORT = ACE_DEFAULT_SERVER_PORT;</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; Finally, we get to main.&nbsp;
-Some C++ compilers will complain loudly if your</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; function signature doesn't
-match the prototype.&nbsp; Even though we're not</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; going to use the parameters,
-we still&nbsp; have to specify them.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">int main (int argc, char *argv[])</FONT>
-<BR><FONT FACE="Arial,Helvetica">{</FONT>
-<BR><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; In our earlier servers, we
-used a global pointer to get to the reactor. I've</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; never really liked that idea,
-so I've moved it into main() this time. When</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; we&nbsp; get to the Client_Handler
-object you'll see how we manage to get a</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; pointer back to this reactor.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; ACE_Reactor reactor;</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; The acceptor
-will take care of letting clients connect to us.&nbsp; It will</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; also arrange
-for a&nbsp; Client_Handler to be created for each new client.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Since we're only
-going to listen at one&nbsp; TCP/IP port, we only need one</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; acceptor.&nbsp;
-If we wanted, though, we could create several of these&nbsp; and</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; listen at several
-ports.&nbsp; (That's what we would do if we wanted to rewrite</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; inetd for&nbsp;
-instance.)</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; Client_Acceptor peer_acceptor;</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Create an ACE_INET_Addr
-that represents our endpoint of a connection. We</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; then open our
-acceptor object with that Addr.&nbsp; Doing so tells the acceptor</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; where to listen
-for connections.&nbsp; Servers generally listen at "well known"</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; addresses.&nbsp;
-If not, there must be some mechanism by which the client is</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; informed of the
-server's address.</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Note how ACE_ERROR_RETURN
-is used if we fail to open the acceptor.&nbsp; This</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; technique is
-used over and over again in our tutorials.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; if (peer_acceptor.open (ACE_INET_Addr
-(PORT), &amp;reactor) == -1)</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp; ACE_ERROR_RETURN ((LM_ERROR,
-"%p\n", "open"), -1);</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; As with Tutorial
-5, we know that we're now registered with our reactor</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; so we don't have
-to mess with that step.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Install our signal
-handler.&nbsp; You can actually register signal handlers</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; with the reactor.&nbsp;
-You might do that when the signal handler is</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; responsible for
-performing "real" work.&nbsp; Our simple flag-setter doesn't</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; justify deriving
-from ACE_Event_Handler and providing a callback function</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; though.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; ACE_Sig_Action sa ((ACE_SignalHandler)
-handler, SIGINT);</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; Like ACE_ERROR_RETURN,
-the ACE_DEBUG macro gets used quite a bit.&nbsp; It's a</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; handy way to
-generate uniform debug output from your program.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; ACE_DEBUG ((LM_DEBUG, "(%P|%t)
-starting up server daemon\n"));</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; /*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; This will loop
-"forever" invoking the handle_events() method of our</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; reactor. handle_events()
-watches for activity on any registered handlers</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; and invokes their
-appropriate callbacks when necessary.&nbsp; Callback-driven</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; programming is
-a big thing in ACE, you should get used to it. If the</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; signal handler
-catches something, the finished flag will be set and we'll</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; exit.&nbsp; Conveniently
-enough, handle_events() is also interrupted by signals</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; and will exit
-back to the while() loop.&nbsp; (If you want your event loop to</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; not be interrupted
-by signals, checkout the &lt;i>restart&lt;/i> flag on the</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp; open() method
-of ACE_Reactor if you're interested.)</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; */</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp; while (!finished)</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp; reactor.handle_events
-();</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; ACE_DEBUG ((LM_DEBUG, "(%P|%t) shutting
-down server daemon\n"));</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp; return 0;</FONT>
-<BR><FONT FACE="Arial,Helvetica">}</FONT>
-
-<P>
+<PRE>
+<font color=red>// $Id$</font>
+
+<font color=red>/*
+ We try to keep main() very simple. One of the ways we do that is to push
+ much of the complicated stuff into worker objects. In this case, we only
+ need to include the acceptor header in our main source file. We let it
+ worry about the "<font color=green>real work</font>".
+ */</font>
+
+<font color=blue>#include</font> "<font color=green>client_acceptor.h</font>"
+
+<font color=red>/*
+ As before, we create a simple signal handler that will set our finished
+ flag. There are, of course, more elegant ways to handle program shutdown
+ requests but that isn't really our focus right now, so we'll just do the
+ easiest thing.
+ */</font>
+
+static sig_atomic_t finished = 0;
+extern "<font color=green>C</font>" void handler (int)
+{
+ finished = 1;
+}
+
+<font color=red>/*
+ A server has to listen for clients at a known TCP/IP port. The default ACE
+ port is 10002 (at least on my system) and that's good enough for what we
+ want to do here. Obviously, a more robust application would take a command
+ line parameter or read from a configuration file or do some other clever
+ thing. Just like the signal handler above, though, that's what we want to
+ focus on, so we're taking the easy way out.
+ */</font>
+
+static const u_short PORT = ACE_DEFAULT_SERVER_PORT;
+
+<font color=red>/*
+ Finally, we get to main. Some C++ compilers will complain loudly if your
+ function signature doesn't match the prototype. Even though we're not
+ going to use the parameters, we still have to specify them.
+ */</font>
+
+int main (int argc, char *argv[])
+{
+<font color=red>/*
+ In our earlier servers, we used a global pointer to get to the reactor. I've
+ never really liked that idea, so I've moved it into main() this time. When
+ we get to the Client_Handler object you'll see how we manage to get a
+ pointer back to this reactor.
+ */</font>
+ ACE_Reactor reactor;
+
+ <font color=red>/*
+ The acceptor will take care of letting clients connect to us. It will
+ also arrange for a Client_Handler to be created for each new client.
+ Since we're only going to listen at one TCP/IP port, we only need one
+ acceptor. If we wanted, though, we could create several of these and
+ listen at several ports. (That's what we would do if we wanted to rewrite
+ inetd for instance.)
+ */</font>
+ Client_Acceptor peer_acceptor;
+
+ <font color=red>/*
+ Create an ACE_INET_Addr that represents our endpoint of a connection. We
+ then open our acceptor object with that Addr. Doing so tells the acceptor
+ where to listen for connections. Servers generally listen at "<font color=green>well known</font>"
+ addresses. If not, there must be some mechanism by which the client is
+ informed of the server's address.
+
+ Note how ACE_ERROR_RETURN is used if we fail to open the acceptor. This
+ technique is used over and over again in our tutorials.
+ */</font>
+ if (peer_acceptor.open (ACE_INET_Addr (PORT), &reactor) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>open</font>"), -1);
+
+ <font color=red>/*
+ As with Tutorial 5, we know that we're now registered with our reactor
+ so we don't have to mess with that step.
+ */</font>
+
+ <font color=red>/*
+ Install our signal handler. You can actually register signal handlers
+ with the reactor. You might do that when the signal handler is
+ responsible for performing "<font color=green>real</font>" work. Our simple flag-setter doesn't
+ justify deriving from ACE_Event_Handler and providing a callback function
+ though.
+ */</font>
+ ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT);
+
+ <font color=red>/*
+ Like ACE_ERROR_RETURN, the ACE_DEBUG macro gets used quite a bit. It's a
+ handy way to generate uniform debug output from your program.
+ */</font>
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) starting up server daemon\n</font>"));
+
+ <font color=red>/*
+ This will loop "<font color=green>forever</font>" invoking the handle_events() method of our
+ reactor. handle_events() watches for activity on any registered handlers
+ and invokes their appropriate callbacks when necessary. Callback-driven
+ programming is a big thing in ACE, you should get used to it. If the
+ 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
+ open() method of ACE_Reactor if you're interested.)
+ */</font>
+ while (!finished)
+ reactor.handle_events ();
+
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) shutting down server daemon\n</font>"));
+
+ return 0;
+}
+
+<font color=blue>#if !defined</font>(<font color=purple>ACE_HAS_GNU_REPO</font>)
+<font color=blue>#if defined</font> (<font color=purple>ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION</font>)
+template class ACE_Acceptor &lt;Client_Handler, ACE_SOCK_ACCEPTOR>;
+template class ACE_Svc_Handler&lt;ACE_SOCK_STREAM, ACE_NULL_SYNCH>;
+<font color=blue>#elif defined</font> (<font color=purple>ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA</font>)
+<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Acceptor &lt;Client_Handler, ACE_SOCK_ACCEPTOR>
+<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Svc_Handler&lt;ACE_SOCK_STREAM, ACE_NULL_SYNCH>
+<font color=blue>#endif</font> <font color=red>/* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */</font>
+<font color=blue>#endif</font> <font color=red>/* ACE_HAS_GNU_REPO */</font>
+</PRE>
<HR WIDTH="100%">
<P>Let's move along and see what happend to the Client_Acceptor.
<P>
-<HR WIDTH="100%">
-<CENTER>[<A HREF="..">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/006/page03.html b/docs/tutorials/006/page03.html
index b9dad643a4e..6fa27df0964 100644
--- a/docs/tutorials/006/page03.html
+++ b/docs/tutorials/006/page03.html
@@ -15,7 +15,6 @@
<P>
<HR WIDTH="100%">
-
<P>In <A HREF="client_acceptor.h">client_acceptor.h</A>, we've extended
our object just a bit.&nbsp; The primary reason is to allow us to select
the previous single-threaded implementation or our new thread-per-connection
@@ -26,142 +25,98 @@ to the Tutorial 5 version of this file.
<P>
<HR WIDTH="100%">
-
-<P><FONT FACE="Arial,Helvetica">// $Id: client_acceptor.h,v 1.1 1998/08/30
-13:38:27 jcej Exp $</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">#ifndef CLIENT_ACCEPTOR_H</FONT>
-<BR><FONT FACE="Arial,Helvetica">#define CLIENT_ACCEPTOR_H</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; The ACE_Acceptor&lt;> template
-lives in the ace/Acceptor.h header file. You'll</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; find a very consitent naming
-convention between the ACE objects and the</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; headers where they can be
-found.&nbsp; In general, the ACE object ACE_Foobar will</FONT>
-<BR><FONT FACE="Arial,Helvetica"></FONT>&nbsp;<FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; be found in ace/Foobar.h.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">#include "ace/Acceptor.h"</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; Since we want to work with
-sockets, we'll need a SOCK_Acceptor to allow the</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; clients to connect to us.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">#include "ace/SOCK_Acceptor.h"</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; The Client_Handler object
-we develop will be used to handle clients once</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; they're connected.&nbsp;
-The ACE_Acceptor&lt;> template's first parameter requires</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; such an object.&nbsp; In
-some cases, you can get by with just a forward</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; declaration on the class,
-in others you have to have the whole thing.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">#include "client_handler.h"</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; Parameterize the ACE_Acceptor&lt;>
-such that it will listen for socket</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; connection attempts and create
-Client_Handler objects when they happen. In</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; Tutorial 001, we wrote the
-basic acceptor logic on our own before we</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; realized that ACE_Acceptor&lt;>
-was available.&nbsp; You'll get spoiled using the</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; ACE templates because they
-take away a lot of the tedious details!</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">typedef ACE_Acceptor &lt; Client_Handler,
-ACE_SOCK_ACCEPTOR > Client_Acceptor_Base;</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; Here, we use the parameterized
-ACE_Acceptor&lt;> as a baseclass for our customized</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; Client_Acceptor object.&nbsp;
-I've done this so that we can provide it with our choice</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; of concurrency strategies
-when the object is created.&nbsp; Each Client_Handler it</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; creates will use this information
-to determine how to act.&nbsp; If we were going</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; to create a system that was
-always thread-per-connection, we would not have</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp; bothered to extend&nbsp;
-Client_Acceptor.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">class Client_Acceptor : public Client_Acceptor_Base</FONT>
-<BR><FONT FACE="Arial,Helvetica">{</FONT>
-<BR><FONT FACE="Arial,Helvetica">public:</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-This is always a good idea.&nbsp; If nothing else, it makes your code more</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-orthogonal no matter what baseclasses your objects have.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-typedef Client_Acceptor_Base inherited;</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Construct the object with the concurrency strategy.&nbsp; Since this tutorial</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-is focused on thread-per-connection, we make that the default.&nbsp; We
-could</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-have chosen to omitt the default and populate it in main() instead.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Client_Acceptor( int _thread_per_connection = 1 )</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-: thread_per_connection_(_thread_per_connection)</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-{</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-}</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-/*</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Return the value of our strategy flag.&nbsp; This is used by the Client_Handler</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-to decide how to act.&nbsp; If 'true' then the handler will behave in a</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-thread-per-connection manner.</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-*/</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-int thread_per_connection(void)</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-{ return this->thread_per_connection_; }</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">protected:</FONT>
-<BR><FONT FACE="Arial,Helvetica">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-int thread_per_connection_;</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">};</FONT><FONT FACE="Arial,Helvetica"></FONT>
-
-<P><FONT FACE="Arial,Helvetica">#endif // CLIENT_ACCEPTOR_H</FONT>
-
-<P>
+<PRE>
+
+<font color=red>// $Id$</font>
+
+<font color=blue>#ifndef</font> <font color=purple>CLIENT_ACCEPTOR_H</font>
+<font color=blue>#define</font> <font color=purple>CLIENT_ACCEPTOR_H</font>
+
+<font color=red>/*
+ 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>
+
+<font color=blue>#include</font> "<font color=green>ace/Acceptor.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>/*
+ Since we want to work with sockets, we'll need a SOCK_Acceptor to allow the
+ clients to connect to us.
+ */</font>
+<font color=blue>#include</font> "<font color=green>ace/SOCK_Acceptor.h</font>"
+
+<font color=red>/*
+ The Client_Handler object we develop will be used to handle clients once
+ they're connected. The ACE_Acceptor&lt;> template's first parameter requires
+ such an object. In some cases, you can get by with just a forward
+ declaration on the class, in others you have to have the whole thing.
+ */</font>
+<font color=blue>#include</font> "<font color=green>client_handler.h</font>"
+
+<font color=red>/*
+ Parameterize the ACE_Acceptor&lt;> such that it will listen for socket
+ connection attempts and create Client_Handler objects when they happen. In
+ Tutorial 001, we wrote the basic acceptor logic on our own before we
+ realized that ACE_Acceptor&lt;> was available. You'll get spoiled using the
+ ACE templates because they take away a lot of the tedious details!
+ */</font>
+typedef ACE_Acceptor &lt; Client_Handler, ACE_SOCK_ACCEPTOR > Client_Acceptor_Base;
+
+<font color=red>/*
+ Here, we use the parameterized ACE_Acceptor&lt;> as a baseclass for our customized
+ Client_Acceptor object. I've done this so that we can provide it with our choice
+ of concurrency strategies when the object is created. Each Client_Handler it
+ creates will use this information to determine how to act. If we were going
+ to create a system that was always thread-per-connection, we would not have
+ bothered to extend Client_Acceptor.
+ */</font>
+class Client_Acceptor : public Client_Acceptor_Base
+{
+public:
+ <font color=red>/*
+ This is always a good idea. If nothing else, it makes your code more
+ orthogonal no matter what baseclasses your objects have.
+ */</font>
+ typedef Client_Acceptor_Base inherited;
+
+ <font color=red>/*
+ Construct the object with the concurrency strategy. Since this tutorial
+ is focused on thread-per-connection, we make that the default. We could
+ have chosen to omitt the default and populate it in main() instead.
+ */</font>
+ Client_Acceptor( int _thread_per_connection = 1 )
+ : thread_per_connection_(_thread_per_connection)
+ {
+ }
+
+ <font color=red>/*
+ Return the value of our strategy flag. This is used by the Client_Handler
+ to decide how to act. If 'true' then the handler will behave in a
+ thread-per-connection manner.
+ */</font>
+ int thread_per_connection(void)
+ { return this->thread_per_connection_; }
+
+protected:
+ int thread_per_connection_;
+
+};
+
+<font color=blue>#endif</font> <font color=red>// CLIENT_ACCEPTOR_H</font>
+</PRE>
<HR WIDTH="100%">
<P>Ok, so far we haven't done much to change our concurrency strategy.&nbsp;
Let's move on to the Client_Handler and see if it has changed any.
<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/006/page04.html b/docs/tutorials/006/page04.html
index a203c7608a8..3e2002b1d52 100644
--- a/docs/tutorials/006/page04.html
+++ b/docs/tutorials/006/page04.html
@@ -15,7 +15,6 @@
<P>
<HR WIDTH="100%">
-
<P><A HREF="client_handler.h">client_handler.h</A>
shows a few more changes than the previous sources.&nbsp; The important
change is the addition of a svc() method where our connection thread will
@@ -23,12 +22,14 @@ exist.
<P>
<HR WIDTH="100%">
+<PRE>
+
+<font color=red>// $Id$</font>
-<pre><FONT FACE="Arial,Helvetica">
-#ifndef CLIENT_HANDLER_H
-#define CLIENT_HANDLER_H
+<font color=blue>#ifndef</font> <font color=purple>CLIENT_HANDLER_H</font>
+<font color=blue>#define</font> <font color=purple>CLIENT_HANDLER_H</font>
-/*
+<font color=red>/*
Our client handler must exist somewhere in the ACE_Event_Handler object
hierarchy. This is a requirement of the ACE_Reactor because it maintains
ACE_Event_Handler pointers for each registered event handler. You could
@@ -38,64 +39,64 @@ exist.
ACE_SOCK_Stream instance yourself. With ACE_Svc_Handler (which is a
derivative of ACE_Event_Handler) some of those details are handled for you.
- */
+ */</font>
-#include "ace/Svc_Handler.h"
+<font color=blue>#include</font> "<font color=green>ace/Svc_Handler.h</font>"
-#if !defined (ACE_LACKS_PRAGMA_ONCE)
+<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>)
# pragma once
-#endif /* ACE_LACKS_PRAGMA_ONCE */
+<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font>
-#include "ace/SOCK_Stream.h"
+<font color=blue>#include</font> "<font color=green>ace/SOCK_Stream.h</font>"
-/*
- Another feature of ACE_Svc_Handler is it's ability to present the ACE_Task<>
+<font color=red>/*
+ Another feature of ACE_Svc_Handler is it's ability to present the ACE_Task&lt;>
interface as well. That's what the ACE_NULL_SYNCH parameter below is all
about. If our Client_Acceptor has chosen thread-per-connection then our
open() method will activate us into a thread. At that point, our svc()
method will execute. We still don't take advantage of the thiings
ACE_NULL_SYNCH exists for but stick around for Tutorial 7 and pay special
attention to the Thread_Pool object there for an explanation.
- */
-class Client_Handler : public ACE_Svc_Handler < ACE_SOCK_STREAM, ACE_NULL_SYNCH >
+ */</font>
+class Client_Handler : public ACE_Svc_Handler &lt; ACE_SOCK_STREAM, ACE_NULL_SYNCH >
{
public:
- typedef ACE_Svc_Handler < ACE_SOCK_STREAM, ACE_NULL_SYNCH > inherited;
+ typedef ACE_Svc_Handler &lt; ACE_SOCK_STREAM, ACE_NULL_SYNCH > inherited;
- // Constructor...
+ <font color=red>// Constructor...</font>
Client_Handler (void);
- /*
+ <font color=red>/*
The destroy() method is our preferred method of destruction. We could
have overloaded the delete operator but that is neither easy nor
intuitive (at least to me). Instead, we provide a new method of
destruction and we make our destructor protected so that only ourselves,
our derivatives and our friends can delete us. It's a nice
compromise.
- */
+ */</font>
void destroy (void);
- /*
+ <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<> will invoke this method after
+ to create this overrride. 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
- to be an ACE_Acceptor<>* but since ACE_Event_Handler is generic, that
- would tie it too closely to the ACE_Acceptor<> set of objects. In our
+ to be an ACE_Acceptor&lt;>* but since ACE_Event_Handler is generic, that
+ would tie it too closely to the ACE_Acceptor&lt;> set of objects. In our
definition of open() you'll see how we get around that.
- */
+ */</font>
int open (void *_acceptor);
- /*
- When an ACE_Task<> object falls out of the svc() method, the framework
+ <font color=red>/*
+ When an ACE_Task&lt;> object falls out of the svc() method, the framework
will call the close() method. That's where we want to cleanup ourselves
if we're running in either thread-per-connection or thread-pool mode.
- */
+ */</font>
int close(u_long flags = 0);
- /*
+ <font color=red>/*
When there is activity on a registered handler, the handle_input() method
of the handler will be invoked. If that method returns an error code (eg
-- -1) then the reactor will invoke handle_close() to allow the object to
@@ -107,61 +108,57 @@ public:
As a side-effect, the reactor will also invoke remove_handler()
for the object on the mask that caused the -1 return. This means
that we don't have to do that ourselves!
- */
- int handle_close (ACE_HANDLE _handle, ACE_Reactor_Mask _mask);
+ */</font>
+ virtual int handle_close (ACE_HANDLE _handle = ACE_INVALID_HANDLE,
+ ACE_Reactor_Mask _mask = <font color=#008888>ACE_Event_Handler::ALL_EVENTS_MASK</font> );
protected:
- /*
+ <font color=red>/*
If the Client_Acceptor which created us has chosen a thread-per-connection
strategy then our open() method will activate us into a dedicate thread.
The svc() method will then execute in that thread performing some of the
functions we used to leave up to the reactor.
- */
+ */</font>
int svc(void);
- /*
+ <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
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
+ 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
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
would be important to us for reading the client's data.
- */
+ */</font>
int handle_input (ACE_HANDLE _handle);
- /*
+ <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(). As promised in Tutorial 5
I will use this now to make it easier to switch between our two possible
concurrency strategies.
- */
+ */</font>
int process (char *_rdbuf, int _rdbuf_len);
- /*
+ <font color=red>/*
We don't really do anything in our destructor but we've declared it to be
protected to prevent casual deletion of this object. As I said above, I
really would prefer that everyone goes through the destroy() method to get
rid of us.
- */
+ */</font>
~Client_Handler (void);
};
-#endif // CLIENT_HANDLER_H
-</pre>
+<font color=blue>#endif</font> <font color=red>// CLIENT_HANDLER_H</font>
+</PRE>
<HR WIDTH="100%">
<P>So... we've added a svc() method and alluded to changes in open().&nbsp;
Let's move on to the object definition and see what all the fuss is about.
<P>
-<HR WIDTH="100%">
-<CENTER>[<A HREF="..">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/006/page05.html b/docs/tutorials/006/page05.html
index 0b3209e8ba2..80b4e969b19 100644
--- a/docs/tutorials/006/page05.html
+++ b/docs/tutorials/006/page05.html
@@ -1,7 +1,7 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
- <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (WinNT; I) [Netscape]">
+ <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]">
<META NAME="Author" CONTENT="James CE Johnson">
<META NAME="Description" CONTENT="A first step towards using ACE productively">
<TITLE>ACE Tutorial 006</TITLE>
@@ -15,16 +15,17 @@
<P>
<HR WIDTH="100%">
-
<P><A HREF="client_handler.cpp">client_handler.cpp</A> exposes all the
things I've been hinting at.&nbsp; Pay special attention to the decision
made in open() as well as the bit of cleverness in svc().
<P>
<HR WIDTH="100%">
+<PRE>
+
+<font color=red>// $Id$</font>
-<pre><FONT FACE="Arial,Helvetica">
-/*
+<font color=red>/*
In client_handler.h I alluded to the fact that we'll mess around with a
Client_Acceptor pointer. To do so, we need the Client_Acceptor object
declaration.
@@ -35,99 +36,99 @@ made in open() as well as the bit of cleverness in svc().
we're using.
On the other hand, we don't directly include any ACE header files here.
- */
-#include "client_acceptor.h"
-#include "client_handler.h"
+ */</font>
+<font color=blue>#include</font> "<font color=green>client_acceptor.h</font>"
+<font color=blue>#include</font> "<font color=green>client_handler.h</font>"
-/*
+<font color=red>/*
Our constructor doesn't do anything. That's generally a good idea. Unless
you want to start throwing exceptions, there isn't a really good way to
indicate that a constructor has failed. If I had my way, I'd have a boolean
return code from it that would cause new to return 0 if I failed. Oh
well...
- */
-Client_Handler::Client_Handler (void)
+ */</font>
+<font color=#008888>Client_Handler::Client_Handler</font> (void)
{
}
-/*
+<font color=red>/*
Our destructor doesn't do anything either. That is also by design.
Remember, we really want folks to use destroy() to get rid of us. If that's
so, then there's nothing left to do when the destructor gets invoked.
- */
-Client_Handler::~Client_Handler (void)
+ */</font>
+<font color=#008888>Client_Handler::~Client_Handler</font> (void)
{
}
-/*
+<font color=red>/*
The much talked about destroy() method! The reason I keep going on about
this is because it's just a Bad Idea (TM) to do real work inside of a
destructor. Although this method is void, it really should return
int so that it can tell the caller there was a problem. Even as
void you could at least throw an exception which you would never want
to do in a destructor.
- */
-void Client_Handler::destroy (void)
+ */</font>
+void <font color=#008888>Client_Handler::destroy</font> (void)
{
- /*
+ <font color=red>/*
Tell the reactor to forget all about us. Notice that we use the same args
here that we use in the open() method to register ourselves. In addition,
we use the DONT_CALL flag to prevent handle_close() being called. Since we
likely got here due to handle_close(), that could cause a bit of nasty
recursion!
- */
+ */</font>
this->reactor ()->remove_handler (this,
- ACE_Event_Handler:: READ_MASK | ACE_Event_Handler::DONT_CALL);
+ ACE_Event_Handler:: READ_MASK | <font color=#008888>ACE_Event_Handler::DONT_CALL</font>);
- /*
+ <font color=red>/*
This is how we're able to tell folks not to use delete. By
deleting our own instance, we take care of memory leaks after ensuring
that the object is shut down correctly.
- */
+ */</font>
delete this;
}
-/*
+<font color=red>/*
As mentioned before, the open() method is called by the Client_Acceptor when
a new client connection has been accepted. The Client_Acceptor instance
pointer is cast to a void* and given to us here. We'll use that to avoid
some global data...
- */
-int Client_Handler::open (void *_acceptor)
+ */</font>
+int <font color=#008888>Client_Handler::open</font> (void *_acceptor)
{
- /*
+ <font color=red>/*
We need this to store the address of the client that we are now connected
to. We'll use it later to display a debug message.
- */
+ */</font>
ACE_INET_Addr addr;
- /*
+ <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
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
+ can query it to find out the client's host name, TCP/IP address, TCP/IP
port value and so forth. One word of warning: the get_host_name()
method of ACE_INET_Addr may return you an empty string if your name server
can't resolve it. On the other hand, get_host_addr() will always give you
the dotted-decimal string representing the TCP/IP address.
- */
+ */</font>
if (this->peer ().get_remote_addr (addr) == -1)
{
return -1;
}
- /*
+ <font color=red>/*
Convert the void* to a Client_Acceptor*. You should probably use those
fancy new C++ cast operators but I can never remember how/when to do so.
Since you can cast just about anything around a void* without compiler
warnings be very sure of what you're doing when you do this kind of thing.
That's where the new-style cast operators can save you.
- */
+ */</font>
Client_Acceptor *acceptor = (Client_Acceptor *) _acceptor;
- /*
+ <font color=red>/*
Our Client_Acceptor is constructed with a concurrency strategy. Here, we
go back to it to find out what that strategy was. If thread-per-connection
was selected then we simply activate a thread for ourselves and exit. Our
@@ -135,19 +136,19 @@ int Client_Handler::open (void *_acceptor)
If we are told to use the single-threaded strategy, there is no difference
between this and the Tutorial 5 implementation.
- */
+ */</font>
if( acceptor->thread_per_connection() )
{
return this->activate();
}
- /*
+ <font color=red>/*
Our reactor reference will be set when we register ourselves but I decided
to go ahead and set it here. No good reason really...
- */
+ */</font>
this->reactor (acceptor->reactor ());
- /*
+ <font color=red>/*
If we managed to get the client's address then we're connected to a real
and valid client. I suppose that in some cases, the client may connect
and disconnect so quickly that it is invalid by the time we get here. In
@@ -159,91 +160,91 @@ int Client_Handler::open (void *_acceptor)
reactor value from the acceptor which created us in the first place.
Since we're exploring a single-threaded implementation, this is the
correct thing to do.
- */
- if (this->reactor ()->register_handler (this, ACE_Event_Handler::READ_MASK) == -1)
+ */</font>
+ if (this->reactor ()->register_handler (this, <font color=#008888>ACE_Event_Handler::READ_MASK</font>) == -1)
{
- ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) can't register with reactor\n"), -1);
+ ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) can't register with reactor\n</font>"), -1);
}
- /*
+ <font color=red>/*
Here, we use the ACE_INET_Addr object to print a message with the name of
the client we're connected to. Again, it is possible that you'll get an
empty string for the host name if your DNS isn't configured correctly or
if there is some other reason that a TCP/IP addreess cannot be converted
into a host name.
- */
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) connected with %s\n", addr.get_host_name ()));
+ */</font>
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) connected with %s\n</font>", addr.get_host_name ()));
- /*
+ <font color=red>/*
Always return zero on success.
- */
+ */</font>
return 0;
}
-/*
+<font color=red>/*
As mentioned in the header, the typical way to close an object in a threaded
context is to invoke it's close() method. Since we already have a handle_close()
method built to cleanup after us, we'll just forward the request on to that
object.
- */
-int Client_Handler::close(u_long flags)
+ */</font>
+int <font color=#008888>Client_Handler::close</font>(u_long flags)
{
- /*
+ <font color=red>/*
We use the destroy() method to clean up after ourselves.
That will take care of removing us from the reactor and then
freeing our memory.
- */
+ */</font>
this->destroy();
- /*
+ <font color=red>/*
Don't forward the close() to the baseclass! handle_close() above has
already taken care of delete'ing. Forwarding close() would cause that
to happen again and things would get really ugly at that point!
- */
+ */</font>
return 0;
}
-/*
+<font color=red>/*
In the open() method, we registered with the reactor and requested to be
notified when there is data to be read. When the reactor sees that activity
it will invoke this handle_input() method on us. As I mentioned, the _handle
parameter isn't useful to us but it narrows the list of methods the reactor
has to worry about and the list of possible virtual functions we would have
to override.
- */
-int Client_Handler::handle_input (ACE_HANDLE _handle)
+ */</font>
+int <font color=#008888>Client_Handler::handle_input</font> (ACE_HANDLE _handle)
{
- /*
+ <font color=red>/*
Some compilers don't like it when you fail to use a parameter. This macro
will keep 'em quiet for you.
- */
+ */</font>
ACE_UNUSED_ARG (_handle);
- /*
+ <font color=red>/*
Now, we create and initialize a buffer for receiving the data. Since this
is just a simple test app, we'll use a small buffer size.
- */
+ */</font>
char buf[128];
- ACE_OS::memset (buf, 0, sizeof (buf));
+ <font color=#008888>ACE_OS::memset</font> (buf, 0, sizeof (buf));
- /*
+ <font color=red>/*
Invoke the process() method with a pointer to our data area. We'll let
that method worry about interfacing with the data. You might choose to go
ahead and read the data and then pass the result to process(). However,
application logic may require that you read a few bytes to determine what
else to read... It's best if we push that all into the application-logic
level.
- */
+ */</font>
return this->process (buf, sizeof (buf));
}
-/*
+<font color=red>/*
If we return -1 out of handle_input() or if the reactor sees other problems
with us then handle_close() will be called. The reactor framework
will take care of removing us (due to the -1), so we don't need to
use the destroy() method. Instead, we just delete ourselves directly.
- */
-int Client_Handler::handle_close (ACE_HANDLE _handle, ACE_Reactor_Mask _mask)
+ */</font>
+int <font color=#008888>Client_Handler::handle_close</font> (ACE_HANDLE _handle, ACE_Reactor_Mask _mask)
{
ACE_UNUSED_ARG (_handle);
ACE_UNUSED_ARG (_mask);
@@ -252,29 +253,29 @@ int Client_Handler::handle_close (ACE_HANDLE _handle, ACE_Reactor_Mask _mask)
return 0;
}
-/*
- The ACE_Svc_Handler<> is ultimately derived from ACE_Task<>. If you want to
+<font color=red>/*
+ The ACE_Svc_Handler&lt;> is ultimately derived from ACE_Task&lt;>. If you want to
create a multi-threaded application, these are your tools! Simply override
the svc() method in your derivative and arrange for your activate() method
to be called. The svc() method then executes in the new thread.
- */
-int Client_Handler::svc(void)
+ */</font>
+int <font color=#008888>Client_Handler::svc</font>(void)
{
- /*
+ <font color=red>/*
Like handle_input(), we create a buffer for loading the data. Doing so
in handle_input() doesn't help any but there is a small performance increase
by doing this here: the buffer is created once when the thread is created
instead of for each invocation of process().
- */
+ */</font>
char buf[128];
- // Forever...
+ <font color=red>// Forever...</font>
while( 1 )
{
- // Clean the buffer...
- ACE_OS::memset (buf, 0, sizeof (buf));
+ <font color=red>// Clean the buffer...</font>
+ <font color=#008888>ACE_OS::memset</font> (buf, 0, sizeof (buf));
- /*
+ <font color=red>/*
Invoke the proces() method to read and process the data. This is
exactly the way it is used by handle_input(). That's the reason I
created process() in the first place: so that it can be used in either
@@ -285,7 +286,7 @@ int Client_Handler::svc(void)
Notice that since the recv() method call in process() blocks until
there is data ready, this thread doesn't consume any CPU time until
there is actually data sent from the client.
- */
+ */</font>
if( this->process(buf,sizeof(buf)) == -1 )
{
return(-1);
@@ -295,17 +296,17 @@ int Client_Handler::svc(void)
return(0);
}
-/*
+<font color=red>/*
And, at last, we get to the application-logic level. Out of everything
we've done so far, this is the only thing that really has anything to do
with what your application will do. In this method we will read and process
the client's data. In a real appliation, you will probably have a bit more
in main() to deal with command line options but after that point, all of the
action takes place here.
- */
-int Client_Handler::process (char *_rdbuf, int _rdbuf_len)
+ */</font>
+int <font color=#008888>Client_Handler::process</font> (char *_rdbuf, int _rdbuf_len)
{
- /*
+ <font color=red>/*
Using the buffer provided for us, we read the data from the client. If
there is a read error (eg -- recv() returns -1) then it's a pretty good
bet that the connection is gone. Likewise, if we read zero bytes then
@@ -315,20 +316,20 @@ int Client_Handler::process (char *_rdbuf, int _rdbuf_len)
On the other hand, if we got some data then we can display it in a debug
message for everyone to see.
- */
+ */</font>
switch (this->peer ().recv (_rdbuf, _rdbuf_len))
{
case -1:
- ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p bad read\n", "client"), -1);
+ ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) %p bad read\n</font>", "<font color=green>client</font>"), -1);
case 0:
- ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) closing daemon (fd = %d)\n", this->get_handle ()), -1);
+ ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) closing daemon (fd = %d)\n</font>", this->get_handle ()), -1);
default:
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) from client: %s", _rdbuf));
+ ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) from client: %s</font>", _rdbuf));
}
return 0;
}
-</pre>
+</PRE>
<HR WIDTH="100%">
<P>Well, that's it!&nbsp; After all the talk &amp; the hype, you would
@@ -342,9 +343,5 @@ do.
&amp; we'll round up the file list one last time.
<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/006/page06.html b/docs/tutorials/006/page06.html
index b4ad640b25e..041042b8aec 100644
--- a/docs/tutorials/006/page06.html
+++ b/docs/tutorials/006/page06.html
@@ -10,12 +10,11 @@
<CENTER><B><FONT SIZE=+2>ACE Tutorial 006</FONT></B></CENTER>
-<CENTER><B><FONT SIZE=+2>On the road to a multithreaded server</FONT></B></CENTER>
+<CENTER><B><FONT SIZE=+2>Creating a thread-per-connection server</FONT></B></CENTER>
<P>
<HR WIDTH="100%">
-
<P>That's it for Tutorial 6.&nbsp; With very little effort we've managed
to extend the previous single-threaded server to an implementation which
allows runtime selection of single or multi-threaded operation.&nbsp; In
@@ -42,11 +41,5 @@ to the current two.
<LI>
<A HREF="fix.Makefile">fix.Makefile</A></LI>
</UL>
-&nbsp;
-
-<P>
-<HR WIDTH="100%">
-<CENTER>[<A HREF="../../tutorials">Tutorial Index</A>]</CENTER>
-
-</BODY>
-</HTML>
+<P><HR WIDTH="100%">
+<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER>