diff options
Diffstat (limited to 'docs/tutorials')
394 files changed, 0 insertions, 47950 deletions
diff --git a/docs/tutorials/001/001.dsp b/docs/tutorials/001/001.dsp deleted file mode 100644 index 196a498962a..00000000000 --- a/docs/tutorials/001/001.dsp +++ /dev/null @@ -1,108 +0,0 @@ -# Microsoft Developer Studio Project File - Name="001" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=001 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "001.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "001.mak" CFG="001 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "001 - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "001 - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "001 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "001 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"server.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "001 - Win32 Release"
-# Name "001 - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\server.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\acceptor.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\logger.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/001/00SetEnv b/docs/tutorials/001/00SetEnv deleted file mode 100644 index eca78e10c85..00000000000 --- a/docs/tutorials/001/00SetEnv +++ /dev/null @@ -1,2 +0,0 @@ -export ACE_ROOT=/local/src/ACE/ACE_wrappers -export LD_LIBRARY_PATH=$ACE_ROOT/ace:$LD_LIBRARY_PATH diff --git a/docs/tutorials/001/Makefile b/docs/tutorials/001/Makefile deleted file mode 100644 index 8c465a2faf4..00000000000 --- a/docs/tutorials/001/Makefile +++ /dev/null @@ -1,76 +0,0 @@ -#---------------------------------------------------------------------------- -# $Id$ -# -# Makefile for the Reactor Server Logging Daemon -#---------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = server - -FILES = - -LSRC = $(addsuffix .cpp,$(FILES)) -LOBJ = $(addsuffix .o,$(FILES)) -SHOBJ = $(addsuffix .so,$(FILES)) - -LDLIBS = $(addprefix .shobj/,$(SHOBJ)) - -VLDLIBS = $(LDLIBS:%=%$(VAR)) - -BUILD = $(VBIN) - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -# In order to make the generation of HTML pages from sourcecode -# easier, I've started putting the comments into *.pre and *.pst files. -# Those are then combined (via the perl script "combine") with the -# source code to create the HTMLs. In an effort to declutter the -# directory, I archive the component files in a shell-archive (eg -- -# shar) file that is commited to the repository. - -# Invoke the combine script to pull together the pre-code comments, -# code and post-code comments that makeup a tutorial page. 'combine' -# keys itself off of the *.pre files to know what it should build. An -# accessory file "bodies" specifies which source files comprise the -# body of each tutorial page. -HTML : # - [ -f hdr ] || $(MAKE) UNSHAR - perl ../combine *.pre ; chmod +r *.html - -# The SHAR target simply invokes "shar" to create the shell archive. -# It is important to include all "component" files in the shar command -# line so that they will be included in the archive. It is not -# necessary to include the source code files since they're commited as-is. -SHAR : # - [ ! -f combine.shar ] || exit 1 - shar -T hdr bodies *.pre *.pst > combine.shar && $(RM) hdr bodies *.pre *.pst - -# For orthogonality, we have an UNSHAR to match SHAR. -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - -.obj/server.o .shobj/server.so: server.cpp acceptor.h logger.h - diff --git a/docs/tutorials/001/acceptor.h b/docs/tutorials/001/acceptor.h deleted file mode 100644 index d44433bb233..00000000000 --- a/docs/tutorials/001/acceptor.h +++ /dev/null @@ -1,128 +0,0 @@ -// $Id$ - -#ifndef _CLIENT_ACCEPTOR_H -#define _CLIENT_ACCEPTOR_H - -/* A SOCK_Acceptor knows how to accept socket connections. We'll use - one of those at the heart of our Logging_Acceptor. */ -#include "ace/SOCK_Acceptor.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -/* An Event_Handler is what you register with ACE_Reactor. When - events occur, the reactor will callback on the Event_Handler. More - on that in a few lines. */ -#include "ace/Event_Handler.h" - -/* When a client connects, we'll create a Logging_Handler to deal with - the connection. Here, we bring in that declaration. */ -#include "logger.h" - -/* Our Logging_Acceptor is derived from ACE_Event_Handler. That lets - the reactor treat our acceptor just like every other handler. */ -class Logging_Acceptor : public ACE_Event_Handler -{ -public: - - /* For this simple case we won't bother with either constructor or - destructor. In a real application you would certainly have them. */ - - /* Here's the open() method we called from main(). We have two - things to accomplish here: (1) Open the acceptor so that we can - hear client requests and (2) register ourselves with the reactor - so that we can respond to those requests. */ - int open (const ACE_INET_Addr &addr, - ACE_Reactor *reactor) - { - /* Perform the open() on the acceptor. We pass through the - address at which main() wants us to listen. The second - parameter tells the acceptor it is OK to reuse the address. - This is necessary sometimes to get around closed connections - that haven't timed out. */ - if (this->peer_acceptor_.open (addr, 1) == -1) - return -1; - - /* Remember the reactor we're using. We'll need it later when we - create a client connection handler. */ - reactor_ = reactor; - - /* Now we can register with the reactor we were given. Since the - reactor pointer is global, we could have just used that but it's - gross enough already. Notice that we can pass 'this' right into - the registration since we're derived from ACE_Event_Handler. We - also provide ACCEPT_MASK to tell the reactor that we want to - know about accept requests from clients. */ - return reactor->register_handler (this, - ACE_Event_Handler::ACCEPT_MASK); - } - -private: - - /* To provide multi-OS abstraction, ACE uses the concept of - "handles" for connection endpoints. In Unix, this is a - traditional file descriptor (or integer). On other OS's, it may - be something else. The reactor will need to get the handle (file - descriptor) to satisfy it's own internal needs. Our relevant - handle is the handle of the acceptor object, so that's what we - provide. */ - ACE_HANDLE get_handle (void) const - { - return this->peer_acceptor_.get_handle (); - } - - /* When an accept request arrives, the reactor will invoke the - handle_input() callback. This is where we deal with the - connection request. */ - virtual int handle_input (ACE_HANDLE handle) - { - /* The handle provided to us by the reactor is the one that - triggered our up-call. In some advanced situations, you might - actually register a single handler for multiple connections. - The _handle parameter is a way to sort 'em out. Since we don't - use that here, we simply ignore the parameter with the - ACE_UNUSED_ARG() macro. */ - ACE_UNUSED_ARG (handle); - - Logging_Handler *svc_handler; - - /* In response to the connection request, we create a new - Logging_Handler. This new object will be used to interact with - the client until it disconnects. Note how we use the - ACE_NEW_RETURN macro, which returns -1 if operator new fails. */ - ACE_NEW_RETURN (svc_handler, - Logging_Handler, - -1); - - /* To complete the connection, we invoke the accept() method call - on the acceptor object and provide it with the connection - handler instance. This transfers "ownership" of the connection - from the acceptor to the connection handler. */ - if (this->peer_acceptor_.accept (*svc_handler) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p", - "accept failed"), - -1); - - /* Again, most objects need to be open()ed before they are useful. - We'll give the handler our reactor pointer so that it can - register for events as well. If the open fails, we'll force a - close(). */ - if (svc_handler->open (reactor_) == -1) - svc_handler->close (); - - return 0; - } - -protected: - - /* Our acceptor object instance */ - ACE_SOCK_Acceptor peer_acceptor_; - - /* A place to remember our reactor pointer */ - ACE_Reactor *reactor_; -}; - -#endif /* _CLIENT_ACCEPTOR_H */ - diff --git a/docs/tutorials/001/combine.shar b/docs/tutorials/001/combine.shar deleted file mode 100644 index 2a7e1b7a47a..00000000000 --- a/docs/tutorials/001/combine.shar +++ /dev/null @@ -1,574 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/001'. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 524 -rw-rw-r-- hdr -# 38 -rw-rw-r-- bodies -# 4034 -rw-rw-r-- page01.pre -# 2186 -rw-rw-r-- page02.pre -# 553 -rw-rw-r-- page03.pre -# 79 -rw-rw-r-- page04.pre -# 1149 -rw-rw-r-- page05.pre -# 478 -rw-rw-r-- page02.pst -# 1434 -rw-rw-r-- page03.pst -# 279 -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 _sh32295; 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' && -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> -<HTML> -<HEAD> -X <TITLE>ACE Tutorial 001</TITLE> -X <META NAME="GENERATOR" CONTENT="Mozilla/3.01Gold (Win95; I) [Netscape]"> -X <META NAME="Author" CONTENT="James CE Johnson"> -X <META NAME="Description" CONTENT="A first step towards using ACE productively"> -</HEAD> -<BODY text = "#000000" link="#000fff" vlink="#ff0f0f" bgcolor="#ffffff"> -X -X -<CENTER><P><B><FONT SIZE=+2>ACE Tutorial 001<BR> -A Beginners Guide to Using the ACE Toolkit</FONT></B></P></CENTER> -X -<hr> -SHAR_EOF - $shar_touch -am 03191459100 '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' -1d643c1c0995e071a0a9e3662d7a440b hdr -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`" - test 524 -eq "$shar_count" || - $echo 'hdr:' 'original size' '524,' '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 -acceptor.h -logger.h -SHAR_EOF - $shar_touch -am 0117140699 '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' -20ddb6c1ff71a6481ce0956f1a70a612 bodies -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`" - test 38 -eq "$shar_count" || - $echo 'bodies:' 'original size' '38,' '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>The purpose of this tutorial is to show you how to create a very simple -server capable of handling multiple client connections. Unlike a "traditional" -server application, this one handles all requests in one process. Issues -of multi-processing and multi-threading will be handled in later tutorials.</P> -X -<P> -<HR WIDTH="100%"></P> -X -<P>What do you need to create a server?</P> -X -<OL> -<LI>Something which accepts connections from clients</LI> -X -<LI>Something which handles established connections</LI> -X -<LI>A main program loop that handles it all</LI> -</OL> -X -<P>The ACE Acceptor provides a solution for our first requirement. -This class is given a TCP/IP port number on which it will listen for -incoming connections. When a connection is attempted, the acceptor will -create a new object (the handler) to deal with the client connection while -the acceptor goes back to listening for other connections.</P> -X -<P>The ACE EventHandler solves our second requirement. This doesn't -seem obvious now but as we progress through this tutorial it will become -more clear.</P> -X -<P>Finally, a simple <I>main()</I> function will provide our program loop. -After any program initialization, it will enter an infinite loop which -waits for connection attempts to the Acceptor or data "events" -on the EventHandler.</P> -X -<P> -<HR WIDTH="100%"></P> -X -<P>Before we continue, I need to introduce one more ACE concept: the Reactor. -</P> -X -<P>I don't want to go into great detail at this time on what the Reactor -is, what it does and how it does it but it is necessary for you to understand -the basic function of a reactor because it is going to be in the first -piece of code you see. The figure below depicts the interrelationships -between the Reactor, the Acceptor and the application handler.</P> -<P> <center> <img src="simple.gif" align=center> </center> -X -<P>Briefly:<BR> -The reactor is an object which reacts when things happen to other objects. -These things are called <I>events</I>. The <I>other objects</I> are communications -objects which you have <I>registered</I> with the reactor. At the time -of registration, you also specify which events you are interested in. The -reactor is notified by the operating system when the events of interest -occur within the registered objects. The reactor then uses member functions -of the registered object to process the event. Notice that the reactor -doesn't care what happens because of the event. It is the object's responsibility -to process the event correctly. The reactor simply notifies the object -of the event.</P> -X -<P>Why use the reactor?</P> -X -<P>That will become clear as the tutorial progresses. For now, however, -a brief answer would be this: it allows multiple simultaneous client connections -to be processed efficiently by a single-threaded server. </P> -X -<P>Servers have traditionally created a separate thread or process for -each client served. For large-volume services (such as telnet and ftp) -this is appropriate. However, for small-volume services the overhead of -process creation far outweighs the actual work being done. So... folks -begin using threads instead of processes to handle the clients. This is -good also but still, in some cases, the overhead is too much to bear. Instead, -why not have a single thread handle several clients and use a more intelligent -load-balancing methodology than one-thread-or-process-per-client? -<i>Caveat: Handling all requests in one thread of one process is really -only good when the requests can be handled almost instantaneously.</i> -</P> -X -<P>This is where the reactor's power and flexibility come into play. The -developer can create a simple, single-threaded application that is later -modified to thread-per-client, process-per-client or thread-pool solution. -<P> -If all of this is gibberish and makes you think that ACE is way to hard to -learn, don't worry. We'll go into all the details and explain as we go. -I only went into all of this so that it can kick around in the back of your -mind until you need it later. -<P> -SHAR_EOF - $shar_touch -am 03191459100 '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' -58b12a93efda94c99be5d0b38c3096a5 page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 4034 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '4034,' '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>From here, we to move on to the main program loop. In a way, we're -starting at the final product when we do this, but it is a very simple -piece of code and a good place to start. -X -<P>The <A HREF="server.cpp">main</A> -program is really quite simple. The real work is done in the ACE derived -classes. -X -<P> -Kirthika Parameswaran offers this abstract of Tutorial 1: -<UL> -<P> -This is a simple logging server example. -The Reactor is used to handle more than one client request using a -single thread of execution instead of one thread per client. The Reactor -reactes to events and demultiplexes the events to the appropriate -Event_Handler registered with it, using the "callback" technique. The -reactor runs in an infinte event loop handling all the incoming events. -<P> -The Logging_Acceptor listens at a SERVER PORT address and passively -waits for requests to arrive. The Acceptor is also an Event_Handler and -is registered with the Reactor. This way it is simply yet another -Event_Handler for the Reactor and hence no special processing is needed -for it. -<P> -Once a connection request occurs, the Acceptor accepts it and -a connection is established. The reactor instance is passed to the -handler so that it can register with the Reactor. It does so with an -ACE_Event_Handler::ACCEPT_MASK. -<P> -The Logging_Client is another Event_Handler which actually handles the -client requests in its handle_input() method. It is also registered -with the Reactor with the ACE_Event_Handler::READ_MASK. -<P> -The Event_Handlers can be unregistered from the Reactor using -handle_close() methods -or explicitly calling the remove_handler() methods. -<P> -This server application builds and executes succesfully waiting for -client requests to arrive. -<P> -</UL> -FYI (from Doug): -<UL> -The ACCEPT_MASK is defined in the ACE_Event_Handler class. It's used -to inform the Reactor that you want to register an event handler to -"accept" a connection passively. Not surprisingly, the ACE_Acceptor -component uses this. -<P> -The READ_MASK is also defined in the ACE_Event_Handler class. It's -used to inform the Reactor that you want to register an event handler -to "read" data from an established connection. -</UL> -<hr> -SHAR_EOF - $shar_touch -am 03191459100 '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' -38b2ebf93344832204a8327d37bab41c page02.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`" - test 2186 -eq "$shar_count" || - $echo 'page02.pre:' 'original size' '2186,' '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>Now we begin to look at the <A HREF="acceptor.h">acceptor</A> object. -X -<P> -Kirthika has this analogy: -<P> -<UL> -Consider an office: -<P> -Reactor: Receptionist -<P> -Event_Handlers: various Departments catering to specific needs. -<P> -SERVER_PORT: door -<P> -Acceptor: Doorkeeper -<P> -Thus when a needy person (client) enters the open door (port) -maintained by the doorkeeper (acceptor waiting for connection -request), the receptionist(reactor) directs the person towards the -appropriate section (event_handler) which would cater to his needs. -</UL> -<P> -<HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -b1eca88136f15c2c1156a2602daaff7e page03.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`" - test 553 -eq "$shar_count" || - $echo 'page03.pre:' 'original size' '553,' '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>Now we begin to look at the <A HREF="logger.h">logger</A> -object. -X -<P> -<HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -ea4861a868e3dce3607602f1ce35b7fa page04.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`" - test 79 -eq "$shar_count" || - $echo 'page04.pre:' 'original size' '79,' '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>This concludes the first tutorial on using ACE. We've learned how to -create a simple server without knowing very much about network programming. -X -<P>The code used in this tutorial is for illustration purposes. That means -it may or may not work. Actually, it <I>does</I> work but the -astute reader will notice a number of places for potential memory leaks. -We'll work on cleaning those up in future tutorials but if you find one -feel free to send me a fix and I'll integrate it into the tutorial. -X -<UL> -<LI> -<A HREF="00SetEnv">Environment -Settings</A></LI> -X -<LI> -<A HREF="Makefile">Makefile</A></LI> -X -<LI> -<A HREF="server.cpp">main -program</A></LI> -X -<LI> -<A HREF="acceptor.h">acceptor -object</A></LI> -X -<LI> -<A HREF="logger.h">connection -handler</A></LI> -</UL> -X -<P> -To read more about the patterns used in this example (as well as -quite a few which aren't!), you should check out -<A HREF="http://www.cs.wustl.edu/~schmidt/patterns-ace.html">http://www.cs.wustl.edu/~schmidt/patterns-ace.html.</A> -In fact, it's probably safe to say that the concepts found there will keep -coming back to haunt you as these tutorials continue. -<P> -SHAR_EOF - $shar_touch -am 03191459100 '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' -7d00b8c59c4f7210634bc5fdb75dfbcc page05.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`" - test 1149 -eq "$shar_count" || - $echo 'page05.pre:' 'original size' '1149,' '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>As I said, the main program is really quite simple: -<UL> -<LI> -Create an address for the <I>port</I> we want to listen to</LI> -X -<LI> -Create an acceptor which listens on that address</LI> -X -<LI> -Register the acceptor with a reactor to respond to the connection requests</LI> -X -<LI> -Enter an infinite loop to let the reactor handle the events</LI> -</UL> -On the next page, we will take a look at the acceptor and how it responds -to new connection requests. -X -<P> -SHAR_EOF - $shar_touch -am 03191459100 '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' -51b1f08eabda5789182b566fdb7756fe page02.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pst'`" - test 478 -eq "$shar_count" || - $echo 'page02.pst:' 'original size' '478,' '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%"></PRE> -It is important to notice here that we have done very little application-specifc -code in developing this object. In fact, if we take out the progress information, -the only app-specific code is when we create the new <I>Logging_Handler</I> -object to give to the <I>accept</I> function. You may begin to wonder why -there isn't a C++ template that does all of this coding for you. Actually, -the ACE toolkit happens to have one handy: -<UL>typedef ACE_Acceptor <<I>YourHandlerClass</I>, ACE_SOCK_ACCEPTOR> -<I>YourAcceptorClass</I>;</UL> -We would have used it like this: -<UL>typedef ACE_Acceptor <Logging_Handler, ACE_SOCK_ACCEPTOR> Client_Acceptor;</UL> -This will create a piece of code similar to what I've shown above. The -primary difference is that the <I>handle_input </I>function created by -the template does NOT register the handler with the reactor. In the long-run, -that is good for us because we can then move that logic into the <I>open</I> -function of the <I>Logging_Handler</I> and use a completely-generic acceptor. -X -<P>Now that we know how to accept a connection request, let's move on to -the next page where we learn how to handle the actual connection. Even -though we just learned about this cool template thing, we will continue -to use the "hand-written" acceptor developed above. As I mentioned, the -only difference will be in the <I>open</I> function of the connection handler -anyway. -X -<P> -SHAR_EOF - $shar_touch -am 03191459100 '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' -7a18def18c6a83a1015e08f63b5868be page03.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pst'`" - test 1434 -eq "$shar_count" || - $echo 'page03.pst:' 'original size' '1434,' '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> -The comments really should tell the story. The really -interesting stuff is in <i>handle_input()</i>. Everything -else is just housekeeping. -In the future, we'll learn about ACE_Svc_Handler<> -which will take care of most of the housekeeping for us. -<P> -SHAR_EOF - $shar_touch -am 03191459100 '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' -5baa295de79c6c978bae3e496e32854e page04.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pst'`" - test 279 -eq "$shar_count" || - $echo 'page04.pst:' 'original size' '279,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh32295 -exit 0 diff --git a/docs/tutorials/001/logger.h b/docs/tutorials/001/logger.h deleted file mode 100644 index e292250e17a..00000000000 --- a/docs/tutorials/001/logger.h +++ /dev/null @@ -1,178 +0,0 @@ -// $Id$ - -#ifndef _CLIENT_HANDLER_H -#define _CLIENT_HANDLER_H - -/* A connection handler will also be derived from ACE_Event_Handler so - that we can register with a reactor. */ - -#include "ace/Event_Handler.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "ace/INET_Addr.h" - -/* Since we're doing TCP/IP, we'll need a SOCK_Stream for the - connection. */ -#include "ace/SOCK_Stream.h" - -class Logging_Handler : public ACE_Event_Handler -{ -public: - /* - Like the acceptor, we're simple enough to avoid constructor and destructor. - */ - - /* To open the client handler, we have to register ourselves with - the reactor. Notice that we don't have to "open" our - ACE_SOCK_Stream member variable. Why? Because the call to the - acceptor's accept() method took care of those details for us. */ - - int open (ACE_Reactor *reactor) - { - /* - Remember our reactor... - */ - reactor_ = reactor; - - /* In this case we're using the READ_MASK. Like the acceptor, - handle_input() will be called due to this mask but it's a nice - piece of bookkeeping to have separate masks for the separate - types of activity. */ - - if (reactor->register_handler (this, - ACE_Event_Handler::READ_MASK) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) can't register with reactor\n"), - -1); - return 0; - } - - /* If we're explicitly closed we'll close our "file handle". The - net result is to close the connection to the client and remove - ourselves from the reactor if we're registered */ - - int close (void) - { - return this->handle_close (ACE_INVALID_HANDLE, - ACE_Event_Handler::RWE_MASK); - } - - /* This is a bit of magic... When we call the accept() method of - the acceptor object, it wants to do work on an ACE_SOCK_Stream. - We have one of those as our connection to the client but it would - be gross to provide a method to access that object. It's much - cooler if the acceptor can just treat the Logging_Handler as an - ACE_SOCK_Stream. Providing this cast operator lets that happen - cleanly. */ - - operator ACE_SOCK_Stream &() - { - return this->cli_stream_; - } - -protected: - - /* Again, like the acceptor, we need to provide the connection - handle to the reactor. */ - - ACE_HANDLE get_handle (void) const - { - return this->cli_stream_.get_handle (); - } - - /* And here's the handle_input(). This is really the workhorse of - the application. */ - - virtual int handle_input (ACE_HANDLE) - { - /* - Create and initialize a small receive buffer. The extra byte is - there to allow us to have a null-terminated string when it's over. - */ - char buf[BUFSIZ + 1]; - - /* Invoke the recv() method of the ACE_SOCK_Stream to get some - data. It will return -1 if there is an error. Otherwise, it - will return the number of bytes read. Of course, if it read - zero bytes then the connection must be gone. How do I know - that? Because handle_input() would not be called by the reactor - if there wasn't *some* kind of activity and a closed connection - looks like a read request to the reactor. But when you read - from a closed connection you'll read zero bytes. - - Notice that in the error case or closed case we return -1. That - tells the reactor to call our handle_close() where we'll take - care of shutting down cleanly. - - Although we don't make use of them, there are additional - parameters you can use with the recv() call. One of these is an - ACE_Time_Value that allows you to limit the amount of time - blocking on the recv(). You would use that if you weren't sure - if data was available. Since we only get to handle_input() when - data is ready, that would be redundant. On the other hand, if - you use recv_n() to read *exactly* a number of bytes then - limiting the time you wait for those bytes might be good. The - other paramter that may come in handy is an integer - <i>flags</i>. This is passed directly to the underlying OS - recv() call. See the man page recv(2) and the header - sys/socket.h for the gory details. */ - - ssize_t retval; - switch (retval = this->cli_stream_.recv (buf, BUFSIZ)) - { - case -1: - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) %p bad read\n", - "client logger"), - -1); - case 0: - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) closing log daemon (fd = %d)\n", - this->get_handle ()), - -1); - default: - buf[retval] = '\0'; - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) from client: %s", - buf)); - } - - return 0; - } - - /* When handle_input() returns -1, we'll end up here. There are a - few housekeeping chores to handle. */ - - int handle_close (ACE_HANDLE, - ACE_Reactor_Mask _mask) - { - /* Remove ourselves from the reactor. We have to include the - DONT_CALL in the mask so that it won't call handle_close() on us - again! */ - reactor_->remove_handler (this, - _mask | ACE_Event_Handler::DONT_CALL); - - /* Close the socket that we're connected to the client with. */ - cli_stream_.close (); - - /* Since we know we were dynamically allocated by the acceptor, - now is a good time to get rid of ourselves. */ - delete this; - - return 0; - } - -protected: - - /* Our peer connection. */ - ACE_SOCK_Stream cli_stream_; - - /* Our reactor (and our acceptor's reactor). */ - ACE_Reactor *reactor_; -}; - -#endif /* _CLIENT_HANDLER_H */ - diff --git a/docs/tutorials/001/page01.html b/docs/tutorials/001/page01.html deleted file mode 100644 index f79c256bbeb..00000000000 --- a/docs/tutorials/001/page01.html +++ /dev/null @@ -1,104 +0,0 @@ -<!-- $Id$ --> -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> -<HTML> -<HEAD> - <TITLE>ACE Tutorial 001</TITLE> - <META NAME="GENERATOR" CONTENT="Mozilla/3.01Gold (Win95; I) [Netscape]"> - <META NAME="Author" CONTENT="James CE Johnson"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> -</HEAD> -<BODY text = "#000000" link="#000fff" vlink="#ff0f0f" bgcolor="#ffffff"> - - -<CENTER><P><B><FONT SIZE=+2>ACE Tutorial 001<BR> -A Beginners Guide to Using the ACE Toolkit</FONT></B></P></CENTER> - -<hr> -<P>The purpose of this tutorial is to show you how to create a very simple -server capable of handling multiple client connections. Unlike a "traditional" -server application, this one handles all requests in one process. Issues -of multi-processing and multi-threading will be handled in later tutorials.</P> - -<P> -<HR WIDTH="100%"></P> - -<P>What do you need to create a server?</P> - -<OL> -<LI>Something which accepts connections from clients</LI> - -<LI>Something which handles established connections</LI> - -<LI>A main program loop that handles it all</LI> -</OL> - -<P>The ACE Acceptor provides a solution for our first requirement. -This class is given a TCP/IP port number on which it will listen for -incoming connections. When a connection is attempted, the acceptor will -create a new object (the handler) to deal with the client connection while -the acceptor goes back to listening for other connections.</P> - -<P>The ACE EventHandler solves our second requirement. This doesn't -seem obvious now but as we progress through this tutorial it will become -more clear.</P> - -<P>Finally, a simple <I>main()</I> function will provide our program loop. -After any program initialization, it will enter an infinite loop which -waits for connection attempts to the Acceptor or data "events" -on the EventHandler.</P> - -<P> -<HR WIDTH="100%"></P> - -<P>Before we continue, I need to introduce one more ACE concept: the Reactor. -</P> - -<P>I don't want to go into great detail at this time on what the Reactor -is, what it does and how it does it but it is necessary for you to understand -the basic function of a reactor because it is going to be in the first -piece of code you see. The figure below depicts the interrelationships -between the Reactor, the Acceptor and the application handler.</P> -<P> <center> <img src="simple.gif" align=center> </center> - -<P>Briefly:<BR> -The reactor is an object which reacts when things happen to other objects. -These things are called <I>events</I>. The <I>other objects</I> are communications -objects which you have <I>registered</I> with the reactor. At the time -of registration, you also specify which events you are interested in. The -reactor is notified by the operating system when the events of interest -occur within the registered objects. The reactor then uses member functions -of the registered object to process the event. Notice that the reactor -doesn't care what happens because of the event. It is the object's responsibility -to process the event correctly. The reactor simply notifies the object -of the event.</P> - -<P>Why use the reactor?</P> - -<P>That will become clear as the tutorial progresses. For now, however, -a brief answer would be this: it allows multiple simultaneous client connections -to be processed efficiently by a single-threaded server. </P> - -<P>Servers have traditionally created a separate thread or process for -each client served. For large-volume services (such as telnet and ftp) -this is appropriate. However, for small-volume services the overhead of -process creation far outweighs the actual work being done. So... folks -begin using threads instead of processes to handle the clients. This is -good also but still, in some cases, the overhead is too much to bear. Instead, -why not have a single thread handle several clients and use a more intelligent -load-balancing methodology than one-thread-or-process-per-client? -<i>Caveat: Handling all requests in one thread of one process is really -only good when the requests can be handled almost instantaneously.</i> -</P> - -<P>This is where the reactor's power and flexibility come into play. The -developer can create a simple, single-threaded application that is later -modified to thread-per-client, process-per-client or thread-pool solution. -<P> -If all of this is gibberish and makes you think that ACE is way to hard to -learn, don't worry. We'll go into all the details and explain as we go. -I only went into all of this so that it can kick around in the back of your -mind until you need it later. -<P> -<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/001/page02.html b/docs/tutorials/001/page02.html deleted file mode 100644 index e8a2ea6e156..00000000000 --- a/docs/tutorials/001/page02.html +++ /dev/null @@ -1,174 +0,0 @@ -<!-- $Id$ --> -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> -<HTML> -<HEAD> - <TITLE>ACE Tutorial 001</TITLE> - <META NAME="GENERATOR" CONTENT="Mozilla/3.01Gold (Win95; I) [Netscape]"> - <META NAME="Author" CONTENT="James CE Johnson"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> -</HEAD> -<BODY text = "#000000" link="#000fff" vlink="#ff0f0f" bgcolor="#ffffff"> - - -<CENTER><P><B><FONT SIZE=+2>ACE Tutorial 001<BR> -A Beginners Guide to Using the ACE Toolkit</FONT></B></P></CENTER> - -<hr> -<P>From here, we to move on to the main program loop. In a way, we're -starting at the final product when we do this, but it is a very simple -piece of code and a good place to start. - -<P>The <A HREF="server.cpp">main</A> -program is really quite simple. The real work is done in the ACE derived -classes. - -<P> -Kirthika Parameswaran offers this abstract of Tutorial 1: -<UL> -<P> -This is a simple logging server example. -The Reactor is used to handle more than one client request using a -single thread of execution instead of one thread per client. The Reactor -reactes to events and demultiplexes the events to the appropriate -Event_Handler registered with it, using the "callback" technique. The -reactor runs in an infinte event loop handling all the incoming events. -<P> -The Logging_Acceptor listens at a SERVER PORT address and passively -waits for requests to arrive. The Acceptor is also an Event_Handler and -is registered with the Reactor. This way it is simply yet another -Event_Handler for the Reactor and hence no special processing is needed -for it. -<P> -Once a connection request occurs, the Acceptor accepts it and -a connection is established. The reactor instance is passed to the -handler so that it can register with the Reactor. It does so with an -ACE_Event_Handler::ACCEPT_MASK. -<P> -The Logging_Client is another Event_Handler which actually handles the -client requests in its handle_input() method. It is also registered -with the Reactor with the ACE_Event_Handler::READ_MASK. -<P> -The Event_Handlers can be unregistered from the Reactor using -handle_close() methods -or explicitly calling the remove_handler() methods. -<P> -This server application builds and executes succesfully waiting for -client requests to arrive. -<P> -</UL> -FYI (from Doug): -<UL> -The ACCEPT_MASK is defined in the ACE_Event_Handler class. It's used -to inform the Reactor that you want to register an event handler to -"accept" a connection passively. Not surprisingly, the ACE_Acceptor -component uses this. -<P> -The READ_MASK is also defined in the ACE_Event_Handler class. It's -used to inform the Reactor that you want to register an event handler -to "read" data from an established connection. -</UL> -<hr> -<PRE> -<font color=red>// $Id$</font> - -<font color=red>/* Include the header file where our client acceptor is defined. */</font> -<font color=blue>#include</font> "<A HREF="../../../ace/Reactor.h">ace/Reactor.h</A>" - -<font color=red>/* For simplicity, we create our reactor in the global address space. - In later tutorials we will do something more clever and - appropriate. However, the purpose of this tutorial is to introduce a - connection acceptance and handling, not the full capabilities of a - reactor. */</font> -ACE_Reactor *g_reactor; - -<font color=red>/* Include the header where we define our acceptor object. An - acceptor is an abstraction that allows a server to "<font color=green>accept</font>" - connections from clients. */</font> -<font color=blue>#include</font> "<font color=green>acceptor.h</font>" - -<font color=red>/* A TCP/IP server can listen to only one port for connection - requests. Well-known services can always be found at the same - address. Lesser-known services are generally told where to listen by - a configuration file or command-line parameter. For this example, - we're satisfied with simply hard-coding a random but known value. */</font> -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -int -main (int, char *[]) -{ - <font color=red>/* Create a Reactor instance. Again, a global pointer isn't exactly - the best way to handle this but for the simple example here, it - will be OK. We'll get cute with it later. Note how we use the - ACE_NEW_RETURN macro, which returns 1 if operator new fails. */</font> - ACE_NEW_RETURN (g_reactor, - ACE_Reactor, - 1); - - <font color=red>/* Like the Reactor, I'm skimming over the details of the ADDR - object. What it provides is an abstraction for addressing services - in the network. All we need to know at this point is that we are - creating an address object which specifies the TCP/IP port on - which the server will listen for new connection requests. */</font> - ACE_INET_Addr addr (PORT); - - Logging_Acceptor *peer_acceptor; - - <font color=red>/* We now create an acceptor object. No connections will yet be - established because the object isn't "<font color=green>open for business</font>" at this - time. Which brings us to the next line... */</font> - ACE_NEW_RETURN (peer_acceptor, - Logging_Acceptor, - 1); - - <font color=red>/* where the acceptor object is opened. You'll find that most ACE - objects have to be open()ed before they're of any use to you. On - this open() call, we're telling the acceptor where to listen for - connections via the 'addr' object. We're also telling it that we - want it to be registered with our 'g_reactor' instance. */</font> - if (peer_acceptor->open (addr, g_reactor) == -1 ) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>Opening Acceptor\n</font>"), - -1); - - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) starting up server logging daemon\n</font>")); - - <font color=red>/* The reactor's handle_events member function is responsible for - looking at all registered objects and invoking an appropriate - member function when anything of interest occurs. When an event is - processed, the handle_events function returns. In order to get all - events, we embed this in an infinite loop. - - Since we put ourselves into an infinite loop, you'll need to - CTRL-C to exit the program. */</font> - - for (;;) - g_reactor->handle_events (); - - return 0; -} - -</PRE> -<HR WIDTH="100%"> - -<P>As I said, the main program is really quite simple: -<UL> -<LI> -Create an address for the <I>port</I> we want to listen to</LI> - -<LI> -Create an acceptor which listens on that address</LI> - -<LI> -Register the acceptor with a reactor to respond to the connection requests</LI> - -<LI> -Enter an infinite loop to let the reactor handle the events</LI> -</UL> -On the next page, we will take a look at the acceptor and how it responds -to new connection requests. - -<P> -<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/001/page03.html b/docs/tutorials/001/page03.html deleted file mode 100644 index a20aacfa007..00000000000 --- a/docs/tutorials/001/page03.html +++ /dev/null @@ -1,197 +0,0 @@ -<!-- $Id$ --> -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> -<HTML> -<HEAD> - <TITLE>ACE Tutorial 001</TITLE> - <META NAME="GENERATOR" CONTENT="Mozilla/3.01Gold (Win95; I) [Netscape]"> - <META NAME="Author" CONTENT="James CE Johnson"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> -</HEAD> -<BODY text = "#000000" link="#000fff" vlink="#ff0f0f" bgcolor="#ffffff"> - - -<CENTER><P><B><FONT SIZE=+2>ACE Tutorial 001<BR> -A Beginners Guide to Using the ACE Toolkit</FONT></B></P></CENTER> - -<hr> -<P>Now we begin to look at the <A HREF="acceptor.h">acceptor</A> object. - -<P> -Kirthika has this analogy: -<P> -<UL> -Consider an office: -<P> -Reactor: Receptionist -<P> -Event_Handlers: various Departments catering to specific needs. -<P> -SERVER_PORT: door -<P> -Acceptor: Doorkeeper -<P> -Thus when a needy person (client) enters the open door (port) -maintained by the doorkeeper (acceptor waiting for connection -request), the receptionist(reactor) directs the person towards the -appropriate section (event_handler) which would cater to his needs. -</UL> -<P> -<HR> -<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>/* A SOCK_Acceptor knows how to accept socket connections. We'll use - one of those at the heart of our Logging_Acceptor. */</font> -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Acceptor.h">ace/SOCK_Acceptor.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=red>/* An Event_Handler is what you register with ACE_Reactor. When - events occur, the reactor will callback on the Event_Handler. More - on that in a few lines. */</font> -<font color=blue>#include</font> "<A HREF="../../../ace/Event_Handler.h">ace/Event_Handler.h</A>" - -<font color=red>/* When a client connects, we'll create a Logging_Handler to deal with - the connection. Here, we bring in that declaration. */</font> -<font color=blue>#include</font> "<font color=green>logger.h</font>" - -<font color=red>/* Our Logging_Acceptor is derived from ACE_Event_Handler. That lets - the reactor treat our acceptor just like every other handler. */</font> -class Logging_Acceptor : public ACE_Event_Handler -{ -public: - - <font color=red>/* For this simple case we won't bother with either constructor or - destructor. In a real application you would certainly have them. */</font> - - <font color=red>/* Here's the open() method we called from main(). We have two - things to accomplish here: (1) Open the acceptor so that we can - hear client requests and (2) register ourselves with the reactor - so that we can respond to those requests. */</font> - int open (const ACE_INET_Addr &addr, - ACE_Reactor *reactor) - { - <font color=red>/* Perform the open() on the acceptor. We pass through the - address at which main() wants us to listen. The second - parameter tells the acceptor it is OK to reuse the address. - This is necessary sometimes to get around closed connections - that haven't timed out. */</font> - if (this->peer_acceptor_.open (addr, 1) == -1) - return -1; - - <font color=red>/* Remember the reactor we're using. We'll need it later when we - create a client connection handler. */</font> - reactor_ = reactor; - - <font color=red>/* Now we can register with the reactor we were given. Since the - reactor pointer is global, we could have just used that but it's - gross enough already. Notice that we can pass 'this' right into - the registration since we're derived from ACE_Event_Handler. We - also provide ACCEPT_MASK to tell the reactor that we want to - know about accept requests from clients. */</font> - return reactor->register_handler (this, - <font color=#008888>ACE_Event_Handler::ACCEPT_MASK</font>); - } - -private: - - <font color=red>/* To provide multi-OS abstraction, ACE uses the concept of - "<font color=green>handles</font>" for connection endpoints. In Unix, this is a - traditional file descriptor (or integer). On other OS's, it may - be something else. The reactor will need to get the handle (file - descriptor) to satisfy it's own internal needs. Our relevant - handle is the handle of the acceptor object, so that's what we - provide. */</font> - ACE_HANDLE get_handle (void) const - { - return this->peer_acceptor_.get_handle (); - } - - <font color=red>/* When an accept request arrives, the reactor will invoke the - handle_input() callback. This is where we deal with the - connection request. */</font> - virtual int handle_input (ACE_HANDLE handle) - { - <font color=red>/* The handle provided to us by the reactor is the one that - triggered our up-call. In some advanced situations, you might - actually register a single handler for multiple connections. - The _handle parameter is a way to sort 'em out. Since we don't - use that here, we simply ignore the parameter with the - ACE_UNUSED_ARG() macro. */</font> - ACE_UNUSED_ARG (handle); - - Logging_Handler *svc_handler; - - <font color=red>/* In response to the connection request, we create a new - Logging_Handler. This new object will be used to interact with - the client until it disconnects. Note how we use the - ACE_NEW_RETURN macro, which returns -1 if operator new fails. */</font> - ACE_NEW_RETURN (svc_handler, - Logging_Handler, - -1); - - <font color=red>/* To complete the connection, we invoke the accept() method call - on the acceptor object and provide it with the connection - handler instance. This transfers "<font color=green>ownership</font>" of the connection - from the acceptor to the connection handler. */</font> - if (this->peer_acceptor_.accept (*svc_handler) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p</font>", - "<font color=green>accept failed</font>"), - -1); - - <font color=red>/* Again, most objects need to be open()ed before they are useful. - We'll give the handler our reactor pointer so that it can - register for events as well. If the open fails, we'll force a - close(). */</font> - if (svc_handler->open (reactor_) == -1) - svc_handler->close (); - - return 0; - } - -protected: - - <font color=red>/* Our acceptor object instance */</font> - ACE_SOCK_Acceptor peer_acceptor_; - - <font color=red>/* A place to remember our reactor pointer */</font> - ACE_Reactor *reactor_; -}; - -<font color=blue>#endif</font> <font color=red>/* _CLIENT_ACCEPTOR_H */</font> - -</PRE> -<HR WIDTH="100%"></PRE> -It is important to notice here that we have done very little application-specifc -code in developing this object. In fact, if we take out the progress information, -the only app-specific code is when we create the new <I>Logging_Handler</I> -object to give to the <I>accept</I> function. You may begin to wonder why -there isn't a C++ template that does all of this coding for you. Actually, -the ACE toolkit happens to have one handy: -<UL>typedef ACE_Acceptor <<I>YourHandlerClass</I>, ACE_SOCK_ACCEPTOR> -<I>YourAcceptorClass</I>;</UL> -We would have used it like this: -<UL>typedef ACE_Acceptor <Logging_Handler, ACE_SOCK_ACCEPTOR> Client_Acceptor;</UL> -This will create a piece of code similar to what I've shown above. The -primary difference is that the <I>handle_input </I>function created by -the template does NOT register the handler with the reactor. In the long-run, -that is good for us because we can then move that logic into the <I>open</I> -function of the <I>Logging_Handler</I> and use a completely-generic acceptor. - -<P>Now that we know how to accept a connection request, let's move on to -the next page where we learn how to handle the actual connection. Even -though we just learned about this cool template thing, we will continue -to use the "hand-written" acceptor developed above. As I mentioned, the -only difference will be in the <I>open</I> function of the connection handler -anyway. - -<P> -<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/001/page04.html b/docs/tutorials/001/page04.html deleted file mode 100644 index aa420c45f50..00000000000 --- a/docs/tutorials/001/page04.html +++ /dev/null @@ -1,213 +0,0 @@ -<!-- $Id$ --> -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> -<HTML> -<HEAD> - <TITLE>ACE Tutorial 001</TITLE> - <META NAME="GENERATOR" CONTENT="Mozilla/3.01Gold (Win95; I) [Netscape]"> - <META NAME="Author" CONTENT="James CE Johnson"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> -</HEAD> -<BODY text = "#000000" link="#000fff" vlink="#ff0f0f" bgcolor="#ffffff"> - - -<CENTER><P><B><FONT SIZE=+2>ACE Tutorial 001<BR> -A Beginners Guide to Using the ACE Toolkit</FONT></B></P></CENTER> - -<hr> -<P>Now we begin to look at the <A HREF="logger.h">logger</A> -object. - -<P> -<HR> -<PRE> -<font color=red>// $Id$</font> - -<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>/* A connection handler will also be derived from ACE_Event_Handler so - that we can register with a reactor. */</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Event_Handler.h">ace/Event_Handler.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/INET_Addr.h">ace/INET_Addr.h</A>" - -<font color=red>/* Since we're doing TCP/IP, we'll need a SOCK_Stream for the - connection. */</font> -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" - -class Logging_Handler : public ACE_Event_Handler -{ -public: - <font color=red>/* - Like the acceptor, we're simple enough to avoid constructor and destructor. - */</font> - - <font color=red>/* To open the client handler, we have to register ourselves with - the reactor. Notice that we don't have to "<font color=green>open</font>" our - ACE_SOCK_Stream member variable. Why? Because the call to the - acceptor's accept() method took care of those details for us. */</font> - - int open (ACE_Reactor *reactor) - { - <font color=red>/* - Remember our reactor... - */</font> - reactor_ = reactor; - - <font color=red>/* In this case we're using the READ_MASK. Like the acceptor, - handle_input() will be called due to this mask but it's a nice - piece of bookkeeping to have separate masks for the separate - types of activity. */</font> - - if (reactor->register_handler (this, - <font color=#008888>ACE_Event_Handler::READ_MASK</font>) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>(%P|%t) can't register with reactor\n</font>"), - -1); - return 0; - } - - <font color=red>/* If we're explicitly closed we'll close our "<font color=green>file handle</font>". The - net result is to close the connection to the client and remove - ourselves from the reactor if we're registered */</font> - - int close (void) - { - return this->handle_close (ACE_INVALID_HANDLE, - <font color=#008888>ACE_Event_Handler::RWE_MASK</font>); - } - - <font color=red>/* This is a bit of magic... When we call the accept() method of - the acceptor object, it wants to do work on an ACE_SOCK_Stream. - We have one of those as our connection to the client but it would - be gross to provide a method to access that object. It's much - cooler if the acceptor can just treat the Logging_Handler as an - ACE_SOCK_Stream. Providing this cast operator lets that happen - cleanly. */</font> - - operator ACE_SOCK_Stream &() - { - return this->cli_stream_; - } - -protected: - - <font color=red>/* Again, like the acceptor, we need to provide the connection - handle to the reactor. */</font> - - ACE_HANDLE get_handle (void) const - { - return this->cli_stream_.get_handle (); - } - - <font color=red>/* And here's the handle_input(). This is really the workhorse of - the application. */</font> - - virtual int handle_input (ACE_HANDLE) - { - <font color=red>/* - Create and initialize a small receive buffer. The extra byte is - there to allow us to have a null-terminated string when it's over. - */</font> - char buf[BUFSIZ + 1]; - - <font color=red>/* Invoke the recv() method of the ACE_SOCK_Stream to get some - data. It will return -1 if there is an error. Otherwise, it - will return the number of bytes read. Of course, if it read - zero bytes then the connection must be gone. How do I know - that? Because handle_input() would not be called by the reactor - if there wasn't *some* kind of activity and a closed connection - looks like a read request to the reactor. But when you read - from a closed connection you'll read zero bytes. - - Notice that in the error case or closed case we return -1. That - tells the reactor to call our handle_close() where we'll take - care of shutting down cleanly. - - Although we don't make use of them, there are additional - parameters you can use with the recv() call. One of these is an - ACE_Time_Value that allows you to limit the amount of time - blocking on the recv(). You would use that if you weren't sure - if data was available. Since we only get to handle_input() when - data is ready, that would be redundant. On the other hand, if - you use recv_n() to read *exactly* a number of bytes then - limiting the time you wait for those bytes might be good. The - other paramter that may come in handy is an integer - <i>flags</i>. This is passed directly to the underlying OS - recv() call. See the man page recv(2) and the header - sys/socket.h for the gory details. */</font> - - ssize_t retval; - switch (retval = this->cli_stream_.recv (buf, BUFSIZ)) - { - case -1: - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>(%P|%t) %p bad read\n</font>", - "<font color=green>client logger</font>"), - -1); - case 0: - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>(%P|%t) closing log daemon (fd = %d)\n</font>", - this->get_handle ()), - -1); - default: - buf[retval] = '\0'; - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) from client: %s</font>", - buf)); - } - - return 0; - } - - <font color=red>/* When handle_input() returns -1, we'll end up here. There are a - few housekeeping chores to handle. */</font> - - int handle_close (ACE_HANDLE, - ACE_Reactor_Mask _mask) - { - <font color=red>/* Remove ourselves from the reactor. We have to include the - DONT_CALL in the mask so that it won't call handle_close() on us - again! */</font> - reactor_->remove_handler (this, - _mask | <font color=#008888>ACE_Event_Handler::DONT_CALL</font>); - - <font color=red>/* Close the socket that we're connected to the client with. */</font> - cli_stream_.close (); - - <font color=red>/* Since we know we were dynamically allocated by the acceptor, - now is a good time to get rid of ourselves. */</font> - delete this; - - return 0; - } - -protected: - - <font color=red>/* Our peer connection. */</font> - ACE_SOCK_Stream cli_stream_; - - <font color=red>/* Our reactor (and our acceptor's reactor). */</font> - ACE_Reactor *reactor_; -}; - -<font color=blue>#endif</font> <font color=red>/* _CLIENT_HANDLER_H */</font> - -</PRE> -<HR WIDTH="100%"> - -<P> -The comments really should tell the story. The really -interesting stuff is in <i>handle_input()</i>. Everything -else is just housekeeping. -In the future, we'll learn about ACE_Svc_Handler<> -which will take care of most of the housekeeping for us. -<P> -<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/001/page05.html b/docs/tutorials/001/page05.html deleted file mode 100644 index 582fd0de953..00000000000 --- a/docs/tutorials/001/page05.html +++ /dev/null @@ -1,56 +0,0 @@ -<!-- $Id$ --> -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> -<HTML> -<HEAD> - <TITLE>ACE Tutorial 001</TITLE> - <META NAME="GENERATOR" CONTENT="Mozilla/3.01Gold (Win95; I) [Netscape]"> - <META NAME="Author" CONTENT="James CE Johnson"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> -</HEAD> -<BODY text = "#000000" link="#000fff" vlink="#ff0f0f" bgcolor="#ffffff"> - - -<CENTER><P><B><FONT SIZE=+2>ACE Tutorial 001<BR> -A Beginners Guide to Using the ACE Toolkit</FONT></B></P></CENTER> - -<hr> -<P>This concludes the first tutorial on using ACE. We've learned how to -create a simple server without knowing very much about network programming. - -<P>The code used in this tutorial is for illustration purposes. That means -it may or may not work. Actually, it <I>does</I> work but the -astute reader will notice a number of places for potential memory leaks. -We'll work on cleaning those up in future tutorials but if you find one -feel free to send me a fix and I'll integrate it into the tutorial. - -<UL> -<LI> -<A HREF="00SetEnv">Environment -Settings</A></LI> - -<LI> -<A HREF="Makefile">Makefile</A></LI> - -<LI> -<A HREF="server.cpp">main -program</A></LI> - -<LI> -<A HREF="acceptor.h">acceptor -object</A></LI> - -<LI> -<A HREF="logger.h">connection -handler</A></LI> -</UL> - -<P> -To read more about the patterns used in this example (as well as -quite a few which aren't!), you should check out -<A HREF="http://www.cs.wustl.edu/~schmidt/patterns-ace.html">http://www.cs.wustl.edu/~schmidt/patterns-ace.html.</A> -In fact, it's probably safe to say that the concepts found there will keep -coming back to haunt you as these tutorials continue. -<P> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/001/server.cpp b/docs/tutorials/001/server.cpp deleted file mode 100644 index e5922a56422..00000000000 --- a/docs/tutorials/001/server.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// $Id$ - -/* Include the header file where our client acceptor is defined. */ -#include "ace/Reactor.h" - -/* For simplicity, we create our reactor in the global address space. - In later tutorials we will do something more clever and - appropriate. However, the purpose of this tutorial is to introduce a - connection acceptance and handling, not the full capabilities of a - reactor. */ -ACE_Reactor *g_reactor; - -/* Include the header where we define our acceptor object. An - acceptor is an abstraction that allows a server to "accept" - connections from clients. */ -#include "acceptor.h" - -/* A TCP/IP server can listen to only one port for connection - requests. Well-known services can always be found at the same - address. Lesser-known services are generally told where to listen by - a configuration file or command-line parameter. For this example, - we're satisfied with simply hard-coding a random but known value. */ -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -int -main (int, char *[]) -{ - /* Create a Reactor instance. Again, a global pointer isn't exactly - the best way to handle this but for the simple example here, it - will be OK. We'll get cute with it later. Note how we use the - ACE_NEW_RETURN macro, which returns 1 if operator new fails. */ - ACE_NEW_RETURN (g_reactor, - ACE_Reactor, - 1); - - /* Like the Reactor, I'm skimming over the details of the ADDR - object. What it provides is an abstraction for addressing services - in the network. All we need to know at this point is that we are - creating an address object which specifies the TCP/IP port on - which the server will listen for new connection requests. */ - ACE_INET_Addr addr (PORT); - - Logging_Acceptor *peer_acceptor; - - /* We now create an acceptor object. No connections will yet be - established because the object isn't "open for business" at this - time. Which brings us to the next line... */ - ACE_NEW_RETURN (peer_acceptor, - Logging_Acceptor, - 1); - - /* where the acceptor object is opened. You'll find that most ACE - objects have to be open()ed before they're of any use to you. On - this open() call, we're telling the acceptor where to listen for - connections via the 'addr' object. We're also telling it that we - want it to be registered with our 'g_reactor' instance. */ - if (peer_acceptor->open (addr, g_reactor) == -1 ) - ACE_ERROR_RETURN ((LM_ERROR, - "Opening Acceptor\n"), - -1); - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) starting up server logging daemon\n")); - - /* The reactor's handle_events member function is responsible for - looking at all registered objects and invoking an appropriate - member function when anything of interest occurs. When an event is - processed, the handle_events function returns. In order to get all - events, we embed this in an infinite loop. - - Since we put ourselves into an infinite loop, you'll need to - CTRL-C to exit the program. */ - - for (;;) - g_reactor->handle_events (); - - return 0; -} - diff --git a/docs/tutorials/001/simple.fig b/docs/tutorials/001/simple.fig deleted file mode 100644 index afea1bddabe..00000000000 --- a/docs/tutorials/001/simple.fig +++ /dev/null @@ -1,57 +0,0 @@ -#FIG 3.2 -Landscape -Center -Inches -Letter -100.00 -Single --2 -1200 2 -6 7800 5925 11850 6900 -2 4 0 1 0 7 0 0 -1 0.000 0 0 7 0 0 5 - 11850 6900 11850 5925 7800 5925 7800 6900 11850 6900 -4 0 0 0 0 0 12 0.0000 4 180 3360 7800 6150 Application_Handler (ACE_Event_Handler)\001 -4 0 0 0 0 0 12 0.0000 4 180 3825 7950 6450 handle_input() {read connection, process data ... }\001 -4 0 0 0 0 0 12 0.0000 4 180 1335 7950 6675 get_handle() {...}\001 --6 -2 4 0 1 0 7 0 0 -1 0.000 0 0 7 0 0 5 - 5100 7200 5100 5925 1725 5925 1725 7200 5100 7200 -2 1 1 1 1 7 0 0 -1 4.000 0 0 -1 1 0 2 - 2 1 1.00 60.00 120.00 - 4950 6600 7725 6600 -2 1 0 1 4 7 0 0 -1 0.000 0 0 -1 0 1 2 - 2 1 1.00 60.00 120.00 - 3900 5925 5400 2250 -2 1 0 1 4 7 0 0 -1 0.000 0 0 -1 0 1 2 - 2 1 1.00 60.00 120.00 - 8400 5925 6600 2250 -2 1 0 1 12 7 0 0 -1 0.000 0 0 -1 1 0 2 - 2 1 1.00 60.00 120.00 - 4500 5925 6000 2250 -2 1 0 1 12 7 0 0 -1 0.000 0 0 -1 1 0 2 - 2 1 1.00 60.00 120.00 - 9000 5925 7200 2250 -2 1 2 2 24 7 0 0 -1 3.000 0 0 -1 0 1 2 - 0 0 1.00 60.00 120.00 - 3300 7200 3300 8325 -2 1 0 2 15 7 0 0 -1 0.000 0 0 -1 1 1 2 - 0 0 1.00 60.00 120.00 - 0 0 1.00 60.00 120.00 - 9600 6900 9600 8025 -2 4 0 1 0 7 0 0 -1 0.000 0 0 7 0 0 5 - 7500 2250 7500 1425 5100 1425 5100 2250 7500 2250 -4 0 0 0 0 0 12 0.0000 4 180 3045 1800 6150 Client_Acceptor (ACE_Event_Handler)\001 -4 0 0 0 0 0 12 0.0000 4 180 2565 1950 6450 handle_input() {open data conn ...\001 -4 0 0 0 0 0 12 0.0000 4 180 1755 3150 6675 create Handler Obj ... }\001 -4 0 0 0 0 0 12 0.0000 4 180 1335 1950 6900 get_handle() {...}\001 -4 0 1 0 0 0 12 0.0000 4 180 1800 5550 6450 create new Handler Obj\001 -4 0 24 0 0 0 12 0.0000 4 180 1530 2550 7800 Connection Request\001 -4 0 15 0 0 0 12 0.0000 4 135 1275 9000 7500 Data Connection\001 -4 0 0 0 0 0 12 0.0000 4 135 600 5925 1725 Reactor\001 -4 0 0 0 0 0 12 0.0000 4 180 1935 5325 2025 event handler dispatching\001 -4 0 0 0 0 0 12 0.0000 4 180 585 8175 4875 register\001 -4 0 0 0 0 0 12 0.0000 4 180 585 4650 5025 register\001 -4 0 0 0 0 0 12 0.0000 4 180 1110 4200 3675 handle_input()\001 -4 0 0 0 0 0 12 0.0000 4 180 975 4200 3900 get_handle()\001 -4 0 0 0 0 0 12 0.0000 4 180 1110 6675 3675 handle_input()\001 -4 0 0 0 0 0 12 0.0000 4 180 975 6675 3900 get_handle()\001 diff --git a/docs/tutorials/001/simple.gif b/docs/tutorials/001/simple.gif Binary files differdeleted file mode 100644 index ef29d88a120..00000000000 --- a/docs/tutorials/001/simple.gif +++ /dev/null diff --git a/docs/tutorials/002/002.dsp b/docs/tutorials/002/002.dsp deleted file mode 100644 index 2632dc42e5f..00000000000 --- a/docs/tutorials/002/002.dsp +++ /dev/null @@ -1,104 +0,0 @@ -# Microsoft Developer Studio Project File - Name="002" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=002 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "002.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "002.mak" CFG="002 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "002 - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "002 - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "002 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "002 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"server.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "002 - Win32 Release"
-# Name "002 - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\server.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\handler.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/002/00SetEnv b/docs/tutorials/002/00SetEnv deleted file mode 100644 index eca78e10c85..00000000000 --- a/docs/tutorials/002/00SetEnv +++ /dev/null @@ -1,2 +0,0 @@ -export ACE_ROOT=/local/src/ACE/ACE_wrappers -export LD_LIBRARY_PATH=$ACE_ROOT/ace:$LD_LIBRARY_PATH diff --git a/docs/tutorials/002/Makefile b/docs/tutorials/002/Makefile deleted file mode 100644 index f2eca0928bc..00000000000 --- a/docs/tutorials/002/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -#---------------------------------------------------------------------------- -# $Id$ -# -# Makefile for the Reactor version of the Server Logging Daemon -#---------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = server - -VLDLIBS = $(LDLIBS:%=%$(VAR)) - -BUILD = $(VBIN) - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -HTML : # - [ -f hdr ] || $(MAKE) UNSHAR - perl ../combine *.pre ; chmod +r *.html - -SHAR : # - [ ! -f combine.shar ] || exit 1 - shar -T hdr bodies *.pre > combine.shar && $(RM) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - -# DO NOT DELETE THIS LINE -- g++dep uses it. -# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. - - - -# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/docs/tutorials/002/combine.shar b/docs/tutorials/002/combine.shar deleted file mode 100644 index f873c160bf6..00000000000 --- a/docs/tutorials/002/combine.shar +++ /dev/null @@ -1,328 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/002'. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 590 -rw-rw-r-- hdr -# 28 -rw-rw-r-- bodies -# 994 -rw-rw-r-- page01.pre -# 1816 -rw-rw-r-- page02.pre -# 100 -rw-rw-r-- page03.pre -# 429 -rw-rw-r-- page04.pre -# -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 _sh32325; 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 002</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> -X -<CENTER><B><FONT SIZE=+2>ACE Tutorial 002</FONT></B></CENTER> -X -<CENTER><B><FONT SIZE=+2>Creating a Better Server</FONT></B></CENTER> -X -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -1c8564e0ea8b3acd6438853dd2bc34d4 hdr -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`" - test 590 -eq "$shar_count" || - $echo 'hdr:' 'original size' '590,' '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 -handler.h -SHAR_EOF - $shar_touch -am 0117141899 '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' -9ec2171f52b5b973c247ef550fb7b035 bodies -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`" - test 28 -eq "$shar_count" || - $echo 'bodies:' 'original size' '28,' '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 will build a little on what we learned in the first -tutorial and add a few extras. In the end, we will have a better server -object that is actually simpler and more maintainable than the one we created -before.</P> -X -<P> -<HR WIDTH="100%"></P> -X -<P>To begin, let's ask ourselves the same thing we did at the beginning -of tutorial 001:</P> -X -<UL> -<P>What do you need to create a server?</P> -</UL> -X -<OL> -<OL> -<LI>Something which accepts connections from clients</LI> -X -<LI>Something which handles established connections</LI> -X -<LI>A main program loop that handles it all</LI> -</OL> -</OL> -X -<P>Previously, we created a solution which addressed each one of these -questions specifically. At the end of it all, we realized that our only -application-specific coding was confined to the <I>handler</I> portion -of the program. We hinted that there may be a way to eliminate hand-coding -an <I>acceptor</I> each time we want to create a server. Here, we will -explore that approach.</P> -X -SHAR_EOF - $shar_touch -am 03191459100 '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' -ca5fd1b413d68211ee2e6d5132fd04d3 page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 994 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '994,' '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 -<P>Like Tutorial 1, this is also a rather small program. I'm going -to add a couple of new ideas along the way but to make up for it I'm also -going to simplify the acceptor a great deal. -X -<P> -Kirthika's Abstract: -<UL> -This is a server example made simpler due to the use of off-the-shelf -components and classes from ACE. -<P> -Here, the Logging_Acceptor is an ACE_Acceptor class which is associated -with the Logging_Handler and the ACE_SOCK_ACCEPTOR. This will now -accept connection requests from the clients on being opened with the -reactor instance passed to it. -<P> -We also implement a signal to capture CTRL-C [ which generates SIGINT ] using ACE_SigAction and -ACE_SignalHandler. This signal can now be used to stop the reactor -from handling events. -<P> -Then, the reactor is allowed to loop infintely until it is shut down -using a ^C, after which both the reactor as well as the acceptor are -destroyed. -<P> -The Logging_Handler derives from the ACE_Svc_Handler instead of the -Event_Handler since the Svc_Handler has inbuilt SOCK_Stream and -provides all the calls needed by the reactor. The Svc_Handler has the -ability to react to events and communicate to remote tasks using the -underlying data stream passed to it. -<P> -A timer is scheduled in the reactor which does nothing but simply -display how it could be used to provide periodic processing when -needed. The ACE_TimeValue is used to set the time period. -<P> -Also, optimisations have been made in the form of a separate function -for -destroying the objects used. -<P> -Thus a simpler server has now been built which successfully -demonstrates how simple a task, writing a server can become on using -the various ACE components judiciously. -</UL> -<P>We begin by looking at the <A HREF="server.cpp">main (server.cpp)</A> portion program: -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -596b8e60a2219f83cbe15600f0f2b29f page02.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`" - test 1816 -eq "$shar_count" || - $echo 'page02.pre:' 'original size' '1816,' '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 -<P>Now lets take a look at the new <A HREF="handler.h">Logging_Handler</A>: -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -f62bcf39007ec332f581a0849e33fe50 page03.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`" - test 100 -eq "$shar_count" || - $echo 'page03.pre:' 'original size' '100,' '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 -<P>Well, that's it for the second tutorial. We've found a much easier way -to create a server, especially the acceptor part. At the same time, we -introduced more functionality and robustness. Not bad for a day's work. -<BR> -<UL> -<LI> -<A HREF="00SetEnv">Environment -Settings</A></LI> -X -<LI> -<A HREF="Makefile">Makefile</A></LI> -X -<LI> -<A HREF="server.cpp">server.cpp</A></LI> -<LI> -<A HREF="handler.h">handler.h</A></LI> -</UL> -X -SHAR_EOF - $shar_touch -am 03191459100 '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' -a215a80c256c303e810c97f0d92f311c page04.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`" - test 429 -eq "$shar_count" || - $echo 'page04.pre:' 'original size' '429,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh32325 -exit 0 diff --git a/docs/tutorials/002/handler.h b/docs/tutorials/002/handler.h deleted file mode 100644 index cce05f3aab3..00000000000 --- a/docs/tutorials/002/handler.h +++ /dev/null @@ -1,167 +0,0 @@ -// $Id$ - -#ifndef LOGGING_HANDLER_H -#define LOGGING_HANDLER_H - -#include "ace/INET_Addr.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "ace/SOCK_Stream.h" -#include "ace/Reactor.h" - -/* Since we used the template to create the acceptor, we don't know if - there is a way to get to the reactor it uses. We'll take the easy - way out and grab the global pointer. (There is a way to get back to - the acceptor's reactor that we'll see later on.) */ -extern ACE_Reactor *g_reactor; - -/* This time we're deriving from ACE_Svc_Handler instead of - ACE_Event_Handler. The big reason for this is because it already - knows how to contain a SOCK_Stream and provides all of the method - calls needed by the reactor. The second template parameter is for - some advanced stuff we'll do with later servers. For now, just use - it as is... */ -class Logging_Handler : public ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> -{ -public: - - /* The Acceptor<> template will open() us when there is a new client - connection. */ - virtual int open (void *) - { - ACE_INET_Addr addr; - - /* Ask the peer() (held in our baseclass) to tell us the address - of the cient which has connected. There may be valid reasons - for this to fail where we wouldn't want to drop the connection - but I can't think of one. */ - if (this->peer ().get_remote_addr (addr) == -1) - return -1; - - /* The Acceptor<> won't register us with it's reactor, so we have - to do so ourselves. This is where we have to grab that global - pointer. Notice that we again use the READ_MASK so that - handle_input() will be called when the client does something. */ - if (g_reactor->register_handler (this, - ACE_Event_Handler::READ_MASK) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) can't register with reactor\n"), - -1); - - /* Here's another new treat. We schedule a timer event. This - particular one will fire in two seconds and then every three - seconds after that. It doesn't serve any useful purpose in our - application other than to show you how it is done. */ - else if (g_reactor->schedule_timer (this, - 0, - ACE_Time_Value (2), - ACE_Time_Value (3)) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "can'(%P|%t) t register with reactor\n"), - -1); - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) connected with %s\n", - addr.get_host_name ())); - - return 0; - } - - /* This is a matter of style & maybe taste. Instead of putting all - of this stuff into a destructor, we put it here and request that - everyone call destroy() instead of 'delete'. */ - virtual void destroy (void) - { - /* Remove ourselves from the reactor */ - g_reactor->remove_handler - (this, - ACE_Event_Handler::READ_MASK | ACE_Event_Handler::DONT_CALL); - - /* Cancel that timer we scheduled in open() */ - g_reactor->cancel_timer (this); - - /* Shut down the connection to the client. */ - this->peer ().close (); - - /* Free our memory. */ - delete this; - } - - /* If somebody doesn't like us, they will close() us. Actually, if - our open() method returns -1, the Acceptor<> will invoke close() - on us for cleanup. */ - virtual int close (u_long flags = 0) - { - /* The ACE_Svc_Handler baseclass requires the <flags> parameter. - We don't use it here though, so we mark it as UNUSED. You can - accomplish the same thing with a signature like handle_input's - below. */ - ACE_UNUSED_ARG (flags); - - /* - Clean up and go away. - */ - this->destroy (); - return 0; - } - -protected: - - /* Respond to input just like Tutorial 1. */ - virtual int handle_input (ACE_HANDLE) - { - char buf[128]; - ACE_OS::memset (buf, 0, sizeof (buf)); - - switch (this->peer ().recv (buf, - sizeof buf)) - { - case -1: - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) %p bad read\n", - "client logger"), - -1); - case 0: - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) closing log daemon (fd = %d)\n", - this->get_handle ()), - -1); - default: - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) from client: %s", - buf)); - } - - return 0; - } - - /* When the timer expires, handle_timeout() will be called. The - 'arg' is the value passed after 'this' in the schedule_timer() - call. You can pass in anything there that you can cast to a - void*. */ - virtual int handle_timeout (const ACE_Time_Value &tv, - const void *arg) - { - ACE_UNUSED_ARG(tv); - ACE_UNUSED_ARG(arg); - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) handling timeout from this = %u\n", - this)); - return 0; - } - - /* - Clean ourselves up when handle_input() (or handle_timer()) returns -1 - */ - virtual int handle_close (ACE_HANDLE, - ACE_Reactor_Mask) - { - this->destroy (); - return 0; - } -}; - -#endif /* LOGGING_HANDLER_H */ diff --git a/docs/tutorials/002/page01.html b/docs/tutorials/002/page01.html deleted file mode 100644 index 0b8a99ff965..00000000000 --- a/docs/tutorials/002/page01.html +++ /dev/null @@ -1,54 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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 002</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 002</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a Better Server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>In this tutorial, we will build a little on what we learned in the first -tutorial and add a few extras. In the end, we will have a better server -object that is actually simpler and more maintainable than the one we created -before.</P> - -<P> -<HR WIDTH="100%"></P> - -<P>To begin, let's ask ourselves the same thing we did at the beginning -of tutorial 001:</P> - -<UL> -<P>What do you need to create a server?</P> -</UL> - -<OL> -<OL> -<LI>Something which accepts connections from clients</LI> - -<LI>Something which handles established connections</LI> - -<LI>A main program loop that handles it all</LI> -</OL> -</OL> - -<P>Previously, we created a solution which addressed each one of these -questions specifically. At the end of it all, we realized that our only -application-specific coding was confined to the <I>handler</I> portion -of the program. We hinted that there may be a way to eliminate hand-coding -an <I>acceptor</I> each time we want to create a server. Here, we will -explore that approach.</P> - -<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/002/page02.html b/docs/tutorials/002/page02.html deleted file mode 100644 index 42d7a8eefcc..00000000000 --- a/docs/tutorials/002/page02.html +++ /dev/null @@ -1,159 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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 002</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 002</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a Better Server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>Like Tutorial 1, this is also a rather small program. I'm going -to add a couple of new ideas along the way but to make up for it I'm also -going to simplify the acceptor a great deal. - -<P> -Kirthika's Abstract: -<UL> -This is a server example made simpler due to the use of off-the-shelf -components and classes from ACE. -<P> -Here, the Logging_Acceptor is an ACE_Acceptor class which is associated -with the Logging_Handler and the ACE_SOCK_ACCEPTOR. This will now -accept connection requests from the clients on being opened with the -reactor instance passed to it. -<P> -We also implement a signal to capture CTRL-C [ which generates SIGINT ] using ACE_SigAction and -ACE_SignalHandler. This signal can now be used to stop the reactor -from handling events. -<P> -Then, the reactor is allowed to loop infintely until it is shut down -using a ^C, after which both the reactor as well as the acceptor are -destroyed. -<P> -The Logging_Handler derives from the ACE_Svc_Handler instead of the -Event_Handler since the Svc_Handler has inbuilt SOCK_Stream and -provides all the calls needed by the reactor. The Svc_Handler has the -ability to react to events and communicate to remote tasks using the -underlying data stream passed to it. -<P> -A timer is scheduled in the reactor which does nothing but simply -display how it could be used to provide periodic processing when -needed. The ACE_TimeValue is used to set the time period. -<P> -Also, optimisations have been made in the form of a separate function -for -destroying the objects used. -<P> -Thus a simpler server has now been built which successfully -demonstrates how simple a task, writing a server can become on using -the various ACE components judiciously. -</UL> -<P>We begin by looking at the <A HREF="server.cpp">main (server.cpp)</A> portion program: - -<P> -<HR WIDTH="100%"> -<PRE> -<font color=red>// $Id$</font> - -<font color=red>/* As before, we need a few ACE objects as well as our Logging_Handler - declaration. */</font> -<font color=blue>#include</font> "<A HREF="../../../ace/Acceptor.h">ace/Acceptor.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Acceptor.h">ace/SOCK_Acceptor.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/Reactor.h">ace/Reactor.h</A>" -<font color=blue>#include</font> "<font color=green>handler.h</font>" - -<font color=red>/* We'll still use the global reactor pointer. There's a snappy way - around this that shows up in later server tutorials. */</font> -ACE_Reactor *g_reactor; - -<font color=red>/* This was hinted at in Tutorial 1. Remember the hand-coded acceptor - that we created there? This template does all of that and more and - better. If you find yourself creating code that doesn't feel like a - part of your application, there's a good chance that ACE has a - template or framework component to do it for you. */</font> -typedef ACE_Acceptor <Logging_Handler, ACE_SOCK_ACCEPTOR> Logging_Acceptor; - -<font color=red>/* One of the new things will be a signal handler so that we can exit - the application somewhat cleanly. The 'finished' flag is used - instead of the previous infninite loop and the 'handler' will set - that flag in respose to SIGINT (CTRL-C). - The invocation of <font color=#008888>ACE_Reactor::notify</font>() will cause the - handle_events() to return so that we can see the new value of 'finished'. -*/</font> -static sig_atomic_t finished = 0; -extern "<font color=green>C</font>" void handler (int) -{ - finished = 1; - g_reactor->notify(); -} - -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -int -main (int, char **) -{ - <font color=red>// Create the reactor we'll register our event handler derivatives with.</font> - ACE_NEW_RETURN (g_reactor, - ACE_Reactor, - 1); - - <font color=red>// Create the acceptor that will listen for client connetions</font> - Logging_Acceptor peer_acceptor; - - <font color=red>/* Notice how similar this is to the open() call in Tutorial 1. I - read ahead when I created that one so that it would come out this - way... */</font> - if (peer_acceptor.open (ACE_INET_Addr (PORT), - g_reactor) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>open</font>"), - -1); - - <font color=red>/* Here's the easiest way to respond to signals in your application. - Simply construct an ACE_Sig_Action object with a "<font color=green>C</font>" function and - the signal you want to capture. As you might expect, there is - also a way to register signal handlers with a reactor but we take - the easy-out here. */</font> - ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT); - - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) starting up server logging daemon\n</font>")); - - <font color=red>// Perform logging service until the signal handler receives SIGINT.</font> - while (!finished) - g_reactor->handle_events (); - - <font color=red>// Close the acceptor so that no more clients will be taken in.</font> - peer_acceptor.close(); - - <font color=red>// Free up the memory allocated for the reactor.</font> - delete g_reactor; - - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) shutting down server logging daemon\n</font>")); - return 0; -} - -<font color=blue>#if defined</font> (<font color=purple>ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION</font>) -template class ACE_Acceptor <Logging_Handler, ACE_SOCK_ACCEPTOR>; -template class ACE_Svc_Handler<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 <Logging_Handler, ACE_SOCK_ACCEPTOR> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> -<font color=blue>#endif</font> <font color=red>/* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */</font> - -</PRE> -<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/002/page03.html b/docs/tutorials/002/page03.html deleted file mode 100644 index 3e36bcfe81f..00000000000 --- a/docs/tutorials/002/page03.html +++ /dev/null @@ -1,195 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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 002</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 002</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a Better Server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>Now lets take a look at the new <A HREF="handler.h">Logging_Handler</A>: - -<P> -<HR WIDTH="100%"> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>LOGGING_HANDLER_H</font> -<font color=blue>#define</font> <font color=purple>LOGGING_HANDLER_H</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/INET_Addr.h">ace/INET_Addr.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/Reactor.h">ace/Reactor.h</A>" - -<font color=red>/* Since we used the template to create the acceptor, we don't know if - there is a way to get to the reactor it uses. We'll take the easy - way out and grab the global pointer. (There is a way to get back to - the acceptor's reactor that we'll see later on.) */</font> -extern ACE_Reactor *g_reactor; - -<font color=red>/* This time we're deriving from ACE_Svc_Handler instead of - ACE_Event_Handler. The big reason for this is because it already - knows how to contain a SOCK_Stream and provides all of the method - calls needed by the reactor. The second template parameter is for - some advanced stuff we'll do with later servers. For now, just use - it as is... */</font> -class Logging_Handler : public ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> -{ -public: - - <font color=red>/* The Acceptor<> template will open() us when there is a new client - connection. */</font> - virtual int open (void *) - { - ACE_INET_Addr addr; - - <font color=red>/* Ask the peer() (held in our baseclass) to tell us the address - of the cient which has connected. There may be valid reasons - for this to fail where we wouldn't want to drop the connection - but I can't think of one. */</font> - if (this->peer ().get_remote_addr (addr) == -1) - return -1; - - <font color=red>/* The Acceptor<> won't register us with it's reactor, so we have - to do so ourselves. This is where we have to grab that global - pointer. Notice that we again use the READ_MASK so that - handle_input() will be called when the client does something. */</font> - if (g_reactor->register_handler (this, - <font color=#008888>ACE_Event_Handler::READ_MASK</font>) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>(%P|%t) can't register with reactor\n</font>"), - -1); - - <font color=red>/* Here's another new treat. We schedule a timer event. This - particular one will fire in two seconds and then every three - seconds after that. It doesn't serve any useful purpose in our - application other than to show you how it is done. */</font> - else if (g_reactor->schedule_timer (this, - 0, - ACE_Time_Value (2), - ACE_Time_Value (3)) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>can'(%P|%t) t register with reactor\n</font>"), - -1); - - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) connected with %s\n</font>", - addr.get_host_name ())); - - return 0; - } - - <font color=red>/* This is a matter of style & maybe taste. Instead of putting all - of this stuff into a destructor, we put it here and request that - everyone call destroy() instead of 'delete'. */</font> - virtual void destroy (void) - { - <font color=red>/* Remove ourselves from the reactor */</font> - g_reactor->remove_handler - (this, - <font color=#008888>ACE_Event_Handler::READ_MASK</font> | ACE_Event_Handler::DONT_CALL); - - <font color=red>/* Cancel that timer we scheduled in open() */</font> - g_reactor->cancel_timer (this); - - <font color=red>/* Shut down the connection to the client. */</font> - this->peer ().close (); - - <font color=red>/* Free our memory. */</font> - delete this; - } - - <font color=red>/* If somebody doesn't like us, they will close() us. Actually, if - our open() method returns -1, the Acceptor<> will invoke close() - on us for cleanup. */</font> - virtual int close (u_long flags = 0) - { - <font color=red>/* The ACE_Svc_Handler baseclass requires the <flags> parameter. - We don't use it here though, so we mark it as UNUSED. You can - accomplish the same thing with a signature like handle_input's - below. */</font> - ACE_UNUSED_ARG (flags); - - <font color=red>/* - Clean up and go away. - */</font> - this->destroy (); - return 0; - } - -protected: - - <font color=red>/* Respond to input just like Tutorial 1. */</font> - virtual int handle_input (ACE_HANDLE) - { - char buf[128]; - <font color=#008888>ACE_OS::memset</font> (buf, 0, sizeof (buf)); - - switch (this->peer ().recv (buf, - sizeof buf)) - { - case -1: - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>(%P|%t) %p bad read\n</font>", - "<font color=green>client logger</font>"), - -1); - case 0: - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>(%P|%t) closing log daemon (fd = %d)\n</font>", - this->get_handle ()), - -1); - default: - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) from client: %s</font>", - buf)); - } - - return 0; - } - - <font color=red>/* When the timer expires, handle_timeout() will be called. The - 'arg' is the value passed after 'this' in the schedule_timer() - call. You can pass in anything there that you can cast to a - void*. */</font> - virtual int handle_timeout (const ACE_Time_Value &tv, - const void *arg) - { - ACE_UNUSED_ARG(tv); - ACE_UNUSED_ARG(arg); - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) handling timeout from this = %u\n</font>", - this)); - return 0; - } - - <font color=red>/* - Clean ourselves up when handle_input() (or handle_timer()) returns -1 - */</font> - virtual int handle_close (ACE_HANDLE, - ACE_Reactor_Mask) - { - this->destroy (); - return 0; - } -}; - -<font color=blue>#endif</font> <font color=red>/* LOGGING_HANDLER_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page04.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/002/page04.html b/docs/tutorials/002/page04.html deleted file mode 100644 index 0b04d2eedbf..00000000000 --- a/docs/tutorials/002/page04.html +++ /dev/null @@ -1,40 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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 002</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 002</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a Better Server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>Well, that's it for the second tutorial. We've found a much easier way -to create a server, especially the acceptor part. At the same time, we -introduced more functionality and robustness. Not bad for a day's work. -<BR> -<UL> -<LI> -<A HREF="00SetEnv">Environment -Settings</A></LI> - -<LI> -<A HREF="Makefile">Makefile</A></LI> - -<LI> -<A HREF="server.cpp">server.cpp</A></LI> -<LI> -<A HREF="handler.h">handler.h</A></LI> -</UL> - -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/002/server.cpp b/docs/tutorials/002/server.cpp deleted file mode 100644 index cfef3aa1a59..00000000000 --- a/docs/tutorials/002/server.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// $Id$ - -/* As before, we need a few ACE objects as well as our Logging_Handler - declaration. */ -#include "ace/Acceptor.h" -#include "ace/SOCK_Acceptor.h" -#include "ace/Reactor.h" -#include "handler.h" - -/* We'll still use the global reactor pointer. There's a snappy way - around this that shows up in later server tutorials. */ -ACE_Reactor *g_reactor; - -/* This was hinted at in Tutorial 1. Remember the hand-coded acceptor - that we created there? This template does all of that and more and - better. If you find yourself creating code that doesn't feel like a - part of your application, there's a good chance that ACE has a - template or framework component to do it for you. */ -typedef ACE_Acceptor <Logging_Handler, ACE_SOCK_ACCEPTOR> Logging_Acceptor; - -/* One of the new things will be a signal handler so that we can exit - the application somewhat cleanly. The 'finished' flag is used - instead of the previous infninite loop and the 'handler' will set - that flag in respose to SIGINT (CTRL-C). - The invocation of ACE_Reactor::notify() will cause the - handle_events() to return so that we can see the new value of 'finished'. -*/ -static sig_atomic_t finished = 0; -extern "C" void handler (int) -{ - finished = 1; - g_reactor->notify(); -} - -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -int -main (int, char **) -{ - // Create the reactor we'll register our event handler derivatives with. - ACE_NEW_RETURN (g_reactor, - ACE_Reactor, - 1); - - // Create the acceptor that will listen for client connetions - Logging_Acceptor peer_acceptor; - - /* Notice how similar this is to the open() call in Tutorial 1. I - read ahead when I created that one so that it would come out this - way... */ - if (peer_acceptor.open (ACE_INET_Addr (PORT), - g_reactor) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "open"), - -1); - - /* Here's the easiest way to respond to signals in your application. - Simply construct an ACE_Sig_Action object with a "C" function and - the signal you want to capture. As you might expect, there is - also a way to register signal handlers with a reactor but we take - the easy-out here. */ - ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT); - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) starting up server logging daemon\n")); - - // Perform logging service until the signal handler receives SIGINT. - while (!finished) - g_reactor->handle_events (); - - // Close the acceptor so that no more clients will be taken in. - peer_acceptor.close(); - - // Free up the memory allocated for the reactor. - delete g_reactor; - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) shutting down server logging daemon\n")); - return 0; -} - -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Acceptor <Logging_Handler, ACE_SOCK_ACCEPTOR>; -template class ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>; -#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate ACE_Acceptor <Logging_Handler, ACE_SOCK_ACCEPTOR> -#pragma instantiate ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> -#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ - diff --git a/docs/tutorials/003/003.dsp b/docs/tutorials/003/003.dsp deleted file mode 100644 index c4a5a21faa4..00000000000 --- a/docs/tutorials/003/003.dsp +++ /dev/null @@ -1,100 +0,0 @@ -# Microsoft Developer Studio Project File - Name="003" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=003 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "003.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "003.mak" CFG="003 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "003 - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "003 - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "003 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "003 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"client.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "003 - Win32 Release"
-# Name "003 - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\client.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/003/00SetEnv b/docs/tutorials/003/00SetEnv deleted file mode 100644 index eca78e10c85..00000000000 --- a/docs/tutorials/003/00SetEnv +++ /dev/null @@ -1,2 +0,0 @@ -export ACE_ROOT=/local/src/ACE/ACE_wrappers -export LD_LIBRARY_PATH=$ACE_ROOT/ace:$LD_LIBRARY_PATH diff --git a/docs/tutorials/003/Makefile b/docs/tutorials/003/Makefile deleted file mode 100644 index 874926a64f1..00000000000 --- a/docs/tutorials/003/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -#---------------------------------------------------------------------------- -# $Id$ -# -# Makefile for client logging applications -#---------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = client - -LSRC = $(addsuffix .cpp,$(BIN)) - -VLDLIBS = $(LDLIBS:%=%$(VAR)) - -BUILD = $(VBIN) - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -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) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - diff --git a/docs/tutorials/003/client.cpp b/docs/tutorials/003/client.cpp deleted file mode 100644 index fdfa51e1752..00000000000 --- a/docs/tutorials/003/client.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// $Id$ - -/* To establish a socket connection to a server, we'll need an - ACE_SOCK_Connector. */ -#include "ace/Log_Msg.h" -#include "ace/SOCK_Connector.h" - -/* Unlike the previous two tutorials, we're going to allow the user to - provide command line options this time. Still, we need defaults in - case that isn't done. */ -static u_short SERVER_PORT = ACE_DEFAULT_SERVER_PORT; -static const char *const SERVER_HOST = ACE_DEFAULT_SERVER_HOST; -static const int MAX_ITERATIONS = 4; - -int -main (int argc, char *argv[]) -{ - /* Accept the users's choice of hosts or use the default. Then do - the same for the TCP/IP port at which the server is listening as - well as the number of iterations to perform. */ - const char *server_host = argc > 1 ? argv[1] : SERVER_HOST; - u_short server_port = argc > 2 ? ACE_OS::atoi (argv[2]) : SERVER_PORT; - int max_iterations = argc > 3 ? ACE_OS::atoi (argv[3]) : MAX_ITERATIONS; - - /* Build ourselves a Stream socket. This is a connected socket that - provides reliable end-to-end communications. We will use the - server object to send data to the server we connect to. */ - ACE_SOCK_Stream server; - - /* And we need a connector object to establish that connection. The - ACE_SOCK_Connector object provides all of the tools we need to - establish a connection once we know the server's network - address... */ - ACE_SOCK_Connector connector; - - /* Which we create with an ACE_INET_Addr object. This object is - given the TCP/IP port and hostname of the server we want to - connect to. */ - ACE_INET_Addr addr (server_port, - server_host); - - /* So, we feed the Addr object and the Stream object to the - connector's connect() member function. Given this information, it - will establish the network connection to the server and attach - that connection to the server object. */ - if (connector.connect (server, addr) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "open"), - -1); - - /* Just for grins, we'll send the server several messages. */ - for (int i = 0; i < max_iterations; i++) - { - char buf[BUFSIZ]; - - /* Create our message with the message number */ - ACE_OS::sprintf (buf, - "message = %d\n", - i + 1); - /* Send the message to the server. We use the server object's - send_n() function to send all of the data at once. There is - also a send() function but it may not send all of the - data. That is due to network buffer availability and such. If - the send() doesn't send all of the data, it is up to you to - program things such that it will keep trying until all of the - data is sent or simply give up. The send_n() function already - does the "keep trying" option for us, so we use it. - - Like the send() method used in the servers we've seen, there - are two additional parameters you can use on the send() and - send_n() method calls. The timeout parameter limits the - amount of time the system will attempt to send the data to the - peer. The flags parameter is passed directly to the OS send() - system call. See send(2) for the valid flags values. */ - if (server.send_n (buf, - ACE_OS::strlen (buf)) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "send"), - -1); - else - /* Pause for a second. */ - ACE_OS::sleep (1); - } - - /* Close the connection to the server. The servers we've created so - far all are based on the ACE_Reactor. When we close(), the - server's reactor will see activity for the registered event - handler and invoke handle_input(). That, in turn, will try to - read from the socket but get back zero bytes. At that point, the - server will know that we've closed from our side. */ - if (server.close () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "close"), - -1); - return 0; -} diff --git a/docs/tutorials/003/combine.shar b/docs/tutorials/003/combine.shar deleted file mode 100644 index 21649b57f57..00000000000 --- a/docs/tutorials/003/combine.shar +++ /dev/null @@ -1,217 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/003'. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 590 -rw-rw-r-- hdr -# 18 -rw-rw-r-- bodies -# 1208 -rw-rw-r-- page01.pre -# 434 -rw-rw-r-- page01.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 _sh32347; 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 003</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> -X -<CENTER><B><FONT SIZE=+2>ACE Tutorial 003</FONT></B></CENTER> -X -<CENTER><B><FONT SIZE=+2>Creating a Simple Client</FONT></B></CENTER> -X -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -6999fd3c50ab0c7fea97b644e7281f09 hdr -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`" - test 590 -eq "$shar_count" || - $echo 'hdr:' 'original size' '590,' '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=1 -client.cpp -SHAR_EOF - $shar_touch -am 0117142499 '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' -d02fcd98e57e40350f82497be4ac0e0c bodies -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`" - test 18 -eq "$shar_count" || - $echo 'bodies:' 'original size' '18,' '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>Now that we've seen how to create servers, let's spend just a moment -making a client. Since this is so easy, I'm going to do all of it in this -one page. -X -<P> -Kirthika says, "Here's an one paragraph abstract for a one page client app:" -X -<UL> -X The server is an Stream object of ACE_SOCK_Stream type. The -X ACE_Sock_Connector does the job of actively making a connection with the -X listening server. It does so using the server_host_address and port -X number which are stored in the ACE_INET_Addr object.Once the -X connection has been established, the client begins its interaction -X with the server and bombards it with messages. -X Note: send_n() call is used since this call sees to the issues of -X network buffering and reliably gets the data across to the server. -X Also, a timeout value is set to provide fault tolerance if the server -X ever dies before the transaction is completed. The server calls a -X close() method -X once it reads in zero bytes during the Event_Handler::handle_input() -X call. This -X proves that the client has severed its connection. The server then -X shuts down. -</UL> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -a141752492580c57f849e42ff287e276 page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 1208 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '1208,' 'current size' "$shar_count!" - fi -fi -# ============= page01.pst ============== -if test -f 'page01.pst' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page01.pst' '(file already exists)' -else - $echo 'x -' extracting 'page01.pst' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page01.pst' && -<HR WIDTH="100%"> -X -<P>Ok, so that was pretty easy. What would be even easier would be to wrap -all of the connection mess up in an object and overload a couple of basic -operators to make things less network-centric. Perhaps we'll see that in -another tutorial. -X -<P>If you want to compile it yourself, here's the <A HREF="client.cpp">source</A>, -the <A HREF="Makefile">Makefile</A>, -and <A HREF="00SetEnv">Environment -settings</A>. -X -<P> -SHAR_EOF - $shar_touch -am 03191459100 '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' -4f24418c514b6359350769103a4ed617 page01.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pst'`" - test 434 -eq "$shar_count" || - $echo 'page01.pst:' 'original size' '434,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh32347 -exit 0 diff --git a/docs/tutorials/003/page01.html b/docs/tutorials/003/page01.html deleted file mode 100644 index 5dd805844f0..00000000000 --- a/docs/tutorials/003/page01.html +++ /dev/null @@ -1,161 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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 003</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 003</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a Simple Client</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>Now that we've seen how to create servers, let's spend just a moment -making a client. Since this is so easy, I'm going to do all of it in this -one page. - -<P> -Kirthika says, "Here's an one paragraph abstract for a one page client app:" - -<UL> - The server is an Stream object of ACE_SOCK_Stream type. The - ACE_Sock_Connector does the job of actively making a connection with the - listening server. It does so using the server_host_address and port - number which are stored in the ACE_INET_Addr object.Once the - connection has been established, the client begins its interaction - with the server and bombards it with messages. - Note: send_n() call is used since this call sees to the issues of - network buffering and reliably gets the data across to the server. - Also, a timeout value is set to provide fault tolerance if the server - ever dies before the transaction is completed. The server calls a - close() method - once it reads in zero bytes during the Event_Handler::handle_input() - call. This - proves that the client has severed its connection. The server then - shuts down. -</UL> -<HR WIDTH="100%"> -<PRE> -<font color=red>// $Id$</font> - -<font color=red>/* To establish a socket connection to a server, we'll need an - ACE_SOCK_Connector. */</font> -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Connector.h">ace/SOCK_Connector.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" - -<font color=red>/* Unlike the previous two tutorials, we're going to allow the user to - provide command line options this time. Still, we need defaults in - case that isn't done. */</font> -static u_short SERVER_PORT = ACE_DEFAULT_SERVER_PORT; -static const char *const SERVER_HOST = ACE_DEFAULT_SERVER_HOST; -static const int MAX_ITERATIONS = 4; - -int -main (int argc, char *argv[]) -{ - <font color=red>/* Accept the users's choice of hosts or use the default. Then do - the same for the TCP/IP port at which the server is listening as - well as the number of iterations to perform. */</font> - const char *server_host = argc > 1 ? argv[1] : SERVER_HOST; - u_short server_port = argc > 2 ? <font color=#008888>ACE_OS::atoi</font> (argv[2]) : SERVER_PORT; - int max_iterations = argc > 3 ? <font color=#008888>ACE_OS::atoi</font> (argv[3]) : MAX_ITERATIONS; - - <font color=red>/* Build ourselves a Stream socket. This is a connected socket that - provides reliable end-to-end communications. We will use the - server object to send data to the server we connect to. */</font> - ACE_SOCK_Stream server; - - <font color=red>/* And we need a connector object to establish that connection. The - ACE_SOCK_Connector object provides all of the tools we need to - establish a connection once we know the server's network - address... */</font> - ACE_SOCK_Connector connector; - - <font color=red>/* Which we create with an ACE_INET_Addr object. This object is - given the TCP/IP port and hostname of the server we want to - connect to. */</font> - ACE_INET_Addr addr (server_port, - server_host); - - <font color=red>/* So, we feed the Addr object and the Stream object to the - connector's connect() member function. Given this information, it - will establish the network connection to the server and attach - that connection to the server object. */</font> - if (connector.connect (server, addr) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>open</font>"), - -1); - - <font color=red>/* Just for grins, we'll send the server several messages. */</font> - for (int i = 0; i < max_iterations; i++) - { - char buf[BUFSIZ]; - - <font color=red>/* Create our message with the message number */</font> - <font color=#008888>ACE_OS::sprintf</font> (buf, - "<font color=green>message = %d\n</font>", - i + 1); - <font color=red>/* Send the message to the server. We use the server object's - send_n() function to send all of the data at once. There is - also a send() function but it may not send all of the - data. That is due to network buffer availability and such. If - the send() doesn't send all of the data, it is up to you to - program things such that it will keep trying until all of the - data is sent or simply give up. The send_n() function already - does the "<font color=green>keep trying</font>" option for us, so we use it. - - Like the send() method used in the servers we've seen, there - are two additional parameters you can use on the send() and - send_n() method calls. The timeout parameter limits the - amount of time the system will attempt to send the data to the - peer. The flags parameter is passed directly to the OS send() - system call. See send(2) for the valid flags values. */</font> - if (server.send_n (buf, - <font color=#008888>ACE_OS::strlen</font> (buf)) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>send</font>"), - -1); - else - <font color=red>/* Pause for a second. */</font> - <font color=#008888>ACE_OS::sleep</font> (1); - } - - <font color=red>/* Close the connection to the server. The servers we've created so - far all are based on the ACE_Reactor. When we close(), the - server's reactor will see activity for the registered event - handler and invoke handle_input(). That, in turn, will try to - read from the socket but get back zero bytes. At that point, the - server will know that we've closed from our side. */</font> - if (server.close () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>close</font>"), - -1); - return 0; -} -</PRE> -<HR WIDTH="100%"> - -<P>Ok, so that was pretty easy. What would be even easier would be to wrap -all of the connection mess up in an object and overload a couple of basic -operators to make things less network-centric. Perhaps we'll see that in -another tutorial. - -<P>If you want to compile it yourself, here's the <A HREF="client.cpp">source</A>, -the <A HREF="Makefile">Makefile</A>, -and <A HREF="00SetEnv">Environment -settings</A>. - -<P> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/004/004.dsp b/docs/tutorials/004/004.dsp deleted file mode 100644 index 67106a5bf88..00000000000 --- a/docs/tutorials/004/004.dsp +++ /dev/null @@ -1,100 +0,0 @@ -# Microsoft Developer Studio Project File - Name="004" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=004 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "004.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "004.mak" CFG="004 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "004 - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "004 - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "004 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "004 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"client.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "004 - Win32 Release"
-# Name "004 - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\client.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/004/00SetEnv b/docs/tutorials/004/00SetEnv deleted file mode 100644 index eca78e10c85..00000000000 --- a/docs/tutorials/004/00SetEnv +++ /dev/null @@ -1,2 +0,0 @@ -export ACE_ROOT=/local/src/ACE/ACE_wrappers -export LD_LIBRARY_PATH=$ACE_ROOT/ace:$LD_LIBRARY_PATH diff --git a/docs/tutorials/004/Makefile b/docs/tutorials/004/Makefile deleted file mode 100644 index 0bfc82e3bd5..00000000000 --- a/docs/tutorials/004/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -#---------------------------------------------------------------------------- -# $Id$ -# -# Makefile for client logging applications -#---------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = client - -LSRC = $(addsuffix .cpp,$(BIN)) - -VLDLIBS = $(LDLIBS:%=%$(VAR)) - -BUILD = $(VBIN) - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - - -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) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- diff --git a/docs/tutorials/004/client.cpp b/docs/tutorials/004/client.cpp deleted file mode 100644 index 54bcbc04fa0..00000000000 --- a/docs/tutorials/004/client.cpp +++ /dev/null @@ -1,216 +0,0 @@ -// $Id$ - -/* We need the connector object & we also bring in a simple string - class. */ -#include "ace/Log_Msg.h" -#include "ace/SOCK_Connector.h" -#include "ace/SString.h" - -/* In this tutorial, we extend SOCK_Stream by adding a few wrappers - around the send_n() method. */ -class Client : public ACE_SOCK_Stream -{ -public: - // Basic constructor - Client (void); - - /* Construct and open() in one call. This isn't generally a good - idea because you don't have a clean way to inform the caller when - open() fails. (Unless you use C++ exceptions.) */ - Client (const char *server, - u_short port); - - /* Open the connection to the server. Notice that this mirrors the - use of ACE_SOCK_Connector. By providing our own open(), we can - hide the connector from our caller & make it's interaction easier. */ - int open (const char *server, - u_short port); - - /* These are necessary if you're going to use the constructor that - invokes open(). */ - int initialized (void) { return initialized_; } - int error (void) { return error_; } - - /* This is where the coolness lies. Most C++ folks are familiar - 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. */ - Client &operator<< (ACE_SString &str); - Client &operator<< (char *str); - Client &operator<< (int n); - -protected: - u_char initialized_; - u_char error_; -}; - -/* The basic constructor just sets our flags to reasonable values. */ -Client::Client(void) -{ - initialized_ = 0; - error_ = 0; -} - -/* This constructor also sets the flags but then calls open(). If the - open() fails, the flags will be set appropriately. Use the two - inline method calls initialized() and error() to check the object - state after using this constructor. */ -Client::Client (const char *server, - u_short port) -{ - initialized_ = 0; - error_ = 0; - this->open (server, port); -} - -/* Open a connection to the server. This hides the use of - ACE_SOCK_Connector from our caller. Since our caller probably - doesn't care *how* we connect, this is a good thing. */ -int -Client::open (const char *server, - u_short port) -{ - /* This is right out of Tutorial 3. The only thing we've added is - to set the initialized_ member variable on success. */ - - ACE_SOCK_Connector connector; - ACE_INET_Addr addr (port, server); - - if (connector.connect (*this, addr) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "open"), - -1); - initialized_ = 1; - return 0; -} - -/* The first of our put operators sends a simple string object to the - peer. */ -Client & -Client::operator<< (ACE_SString &str) -{ - /* We have to be able to allow: server << foo << bar << stuff; - - To accomplish that, every << operator must check that the object - is in a valid state before doing work. */ - - if (initialized () && !error ()) - { - /* Get the actual data held in the string object */ - const char *cp = str.fast_rep (); - - /* Send that data to the peer using send_n() as before. If we - have a problem, we'll set error_ so that subsequent << - operations won't try to use a broken stream. */ - if (this->send_n (cp, - ACE_OS::strlen (cp)) == -1) - error_ = 1; - } - else - /* Be sure that error_ is set if somebody tries to use us when - we're not initialized. */ - error_ = 1; - - /* We have to return a reference to ourselves to allow chaining of - put operations (eg -- "server << foo << bar"). Without the - reference, you would have to do each put operation as a statement. - That's OK but doesn't have the same feel as standard C++ - iostreams. */ - return *this ; -} - -/* How do you put a char*? We'll take an easy way out and construct -an ACE_SString from the char* and then put that. It would have been -more efficient to implement this with the body of the -operator<<(ACE_SString&) method and then express that method in terms -of this one. There's always more than one way to do things! */ - -Client & -Client::operator<< (char *str) -{ - ACE_SString newStr (str); - - *this << newStr; - - return *this ; - - /* Notice that we could have been really clever and done: - - return *this << ACE_SString (str); - - That kind of thing just makes debugging a pain though! */ -} - -/* ACE_SString and char* are both about the same thing. What do you - do about different datatypes though? - - Do the same thing we did with char* and convert it to ACE_SString - where we already have a << operator defined. */ -Client & -Client::operator<< (int n) -{ - /* Create a character buffer large enough for the largest number. - That's a tough call but BUFSIZ should be quite enough. */ - char buf[BUFSIZ]; - - /* Put the number into our buffer... */ - ACE_OS::sprintf (buf, - "(%d)\n", - n); - - /* And create the ACE_SString that we know how to put. */ - ACE_SString newStr (buf); - - /* Send it and... */ - *this << newStr; - - /* return ourselves as usual. */ - return *this; -} - -/* Now we pull it all together. Like Tutorial 3, we'll allow command - line options. */ -int -main (int argc, char *argv[]) -{ - const char *server_host = argc > 1 ? argv[1] : ACE_DEFAULT_SERVER_HOST; - u_short server_port = argc > 2 ? ACE_OS::atoi (argv[2]) : ACE_DEFAULT_SERVER_PORT; - int max_iterations = argc > 3 ? ACE_OS::atoi (argv[3]) : 4; - - /* Use the basic constructor since the other isn't really very safe. */ - 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 (peer.open (server_host, - server_port) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "open"), - -1); - - for (int i = 0; i < max_iterations; i++) - { - /* Tell the server which iteration we're on. No more mucking - aroudn with sprintf at this level! It's all hidden from us. */ - peer << "message = " << i+1; - - /* Everything OK? */ - if (peer.error ()) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "send"), - -1); - else - ACE_OS::sleep (1); - } - - if (peer.close () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "close"), - -1); - return 0; -} diff --git a/docs/tutorials/004/combine.shar b/docs/tutorials/004/combine.shar deleted file mode 100644 index 89c0785719e..00000000000 --- a/docs/tutorials/004/combine.shar +++ /dev/null @@ -1,216 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/004'. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 591 -rw-rw-r-- hdr -# 18 -rw-rw-r-- bodies -# 701 -rw-rw-r-- page01.pre -# 959 -rw-rw-r-- page01.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 _sh32365; 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 004</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> -X -<CENTER><B><FONT SIZE=+2>ACE Tutorial 004</FONT></B></CENTER> -X -<CENTER><B><FONT SIZE=+2>A much more clever Client</FONT></B></CENTER> -X -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -f129543602285ef632d3ae560999a4db hdr -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`" - test 591 -eq "$shar_count" || - $echo 'hdr:' 'original size' '591,' '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=1 -client.cpp -SHAR_EOF - $shar_touch -am 0117142999 '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' -d02fcd98e57e40350f82497be4ac0e0c bodies -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`" - test 18 -eq "$shar_count" || - $echo 'bodies:' 'original size' '18,' '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>Ok, so the last time around, we learned how to create a simple client -that can send a chunk of data. A cooler thing to do is to overload -the C++ put operator (<<) to put some data for us. That's what -we're going to do this time. (This tutorial is actually where ACE_IOStream -was born.) -<P> -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<<() 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. -</UL> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -c0f522e5dbdca1211121476939bb2eaf page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 701 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '701,' 'current size' "$shar_count!" - fi -fi -# ============= page01.pst ============== -if test -f 'page01.pst' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page01.pst' '(file already exists)' -else - $echo 'x -' extracting 'page01.pst' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page01.pst' && -<HR WIDTH="100%"> -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 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. -In addition, there are a lot of optimizations that this client would benefit -from! -X -<P>As an exercise to the reader (don't you hate those!) I challenge you -to write the server side of this. You can take a look at IOStream_Test -in the ACE distribution if you get stuck... -X -<P>If you want to compile it yourself, here's the <A HREF="client.cpp">source</A>, -the <A HREF="Makefile">Makefile</A>, -and <A HREF="00SetEnv">Environment -settings</A>. -X -<P> -SHAR_EOF - $shar_touch -am 03191459100 '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' -82999856145d3dfa74ebbda7e98eb4b2 page01.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pst'`" - test 959 -eq "$shar_count" || - $echo 'page01.pst:' 'original size' '959,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh32365 -exit 0 diff --git a/docs/tutorials/004/page01.html b/docs/tutorials/004/page01.html deleted file mode 100644 index f0ca6eb2ef3..00000000000 --- a/docs/tutorials/004/page01.html +++ /dev/null @@ -1,277 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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 004</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 004</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>A much more clever Client</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>Ok, so the last time around, we learned how to create a simple client -that can send a chunk of data. A cooler thing to do is to overload -the C++ put operator (<<) to put some data for us. That's what -we're going to do this time. (This tutorial is actually where ACE_IOStream -was born.) -<P> -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<<() 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. -</UL> -<HR WIDTH="100%"> -<PRE> -<font color=red>// $Id$</font> - -<font color=red>/* We need the connector object & we also bring in a simple string - class. */</font> -<font color=blue>#include</font> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Connector.h">ace/SOCK_Connector.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/SString.h">ace/SString.h</A>" - -<font color=red>/* In this tutorial, we extend SOCK_Stream by adding a few wrappers - around the send_n() method. */</font> -class Client : public ACE_SOCK_Stream -{ -public: - <font color=red>// Basic constructor</font> - Client (void); - - <font color=red>/* Construct and open() in one call. This isn't generally a good - idea because you don't have a clean way to inform the caller when - open() fails. (Unless you use C++ exceptions.) */</font> - Client (const char *server, - u_short port); - - <font color=red>/* Open the connection to the server. Notice that this mirrors the - use of ACE_SOCK_Connector. By providing our own open(), we can - hide the connector from our caller & make it's interaction easier. */</font> - int open (const char *server, - u_short port); - - <font color=red>/* These are necessary if you're going to use the constructor that - invokes open(). */</font> - int initialized (void) { return initialized_; } - int error (void) { return error_; } - - <font color=red>/* This is where the coolness lies. Most C++ folks are familiar - with "<font color=green>cout << 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> - Client &operator<< (ACE_SString &str); - Client &operator<< (char *str); - Client &operator<< (int n); - -protected: - u_char initialized_; - u_char error_; -}; - -<font color=red>/* The basic constructor just sets our flags to reasonable values. */</font> -<font color=#008888>Client::Client</font>(void) -{ - initialized_ = 0; - error_ = 0; -} - -<font color=red>/* This constructor also sets the flags but then calls open(). If the - open() fails, the flags will be set appropriately. Use the two - inline method calls initialized() and error() to check the object - state after using this constructor. */</font> -<font color=#008888>Client::Client</font> (const char *server, - u_short port) -{ - initialized_ = 0; - error_ = 0; - this->open (server, port); -} - -<font color=red>/* Open a connection to the server. This hides the use of - ACE_SOCK_Connector from our caller. Since our caller probably - doesn't care *how* we connect, this is a good thing. */</font> -int -<font color=#008888>Client::open</font> (const char *server, - u_short port) -{ - <font color=red>/* This is right out of Tutorial 3. The only thing we've added is - to set the initialized_ member variable on success. */</font> - - ACE_SOCK_Connector connector; - ACE_INET_Addr addr (port, server); - - if (connector.connect (*this, addr) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>open</font>"), - -1); - initialized_ = 1; - return 0; -} - -<font color=red>/* The first of our put operators sends a simple string object to the - peer. */</font> -Client & -<font color=#008888>Client::operator</font><< (ACE_SString &str) -{ - <font color=red>/* We have to be able to allow: server << foo << bar << stuff; - - To accomplish that, every << operator must check that the object - is in a valid state before doing work. */</font> - - if (initialized () && !error ()) - { - <font color=red>/* Get the actual data held in the string object */</font> - const char *cp = str.fast_rep (); - - <font color=red>/* Send that data to the peer using send_n() as before. If we - have a problem, we'll set error_ so that subsequent << - operations won't try to use a broken stream. */</font> - if (this->send_n (cp, - <font color=#008888>ACE_OS::strlen</font> (cp)) == -1) - error_ = 1; - } - else - <font color=red>/* Be sure that error_ is set if somebody tries to use us when - we're not initialized. */</font> - error_ = 1; - - <font color=red>/* We have to return a reference to ourselves to allow chaining of - put operations (eg -- "<font color=green>server << foo << bar</font>"). Without the - reference, you would have to do each put operation as a statement. - That's OK but doesn't have the same feel as standard C++ - iostreams. */</font> - return *this ; -} - -<font color=red>/* How do you put a char*? We'll take an easy way out and construct -an ACE_SString from the char* and then put that. It would have been -more efficient to implement this with the body of the -operator<<(ACE_SString&) method and then express that method in terms -of this one. There's always more than one way to do things! */</font> - -Client & -<font color=#008888>Client::operator</font><< (char *str) -{ - ACE_SString newStr (str); - - *this << newStr; - - return *this ; - - <font color=red>/* Notice that we could have been really clever and done: - - return *this << ACE_SString (str); - - That kind of thing just makes debugging a pain though! */</font> -} - -<font color=red>/* ACE_SString and char* are both about the same thing. What do you - do about different datatypes though? - - Do the same thing we did with char* and convert it to ACE_SString - where we already have a << operator defined. */</font> -Client & -<font color=#008888>Client::operator</font><< (int n) -{ - <font color=red>/* Create a character buffer large enough for the largest number. - That's a tough call but BUFSIZ should be quite enough. */</font> - char buf[BUFSIZ]; - - <font color=red>/* Put the number into our buffer... */</font> - <font color=#008888>ACE_OS::sprintf</font> (buf, - "<font color=green>(%d)\n</font>", - n); - - <font color=red>/* And create the ACE_SString that we know how to put. */</font> - ACE_SString newStr (buf); - - <font color=red>/* Send it and... */</font> - *this << newStr; - - <font color=red>/* return ourselves as usual. */</font> - return *this; -} - -<font color=red>/* Now we pull it all together. Like Tutorial 3, we'll allow command - line options. */</font> -int -main (int argc, char *argv[]) -{ - const char *server_host = argc > 1 ? argv[1] : ACE_DEFAULT_SERVER_HOST; - u_short server_port = argc > 2 ? <font color=#008888>ACE_OS::atoi</font> (argv[2]) : ACE_DEFAULT_SERVER_PORT; - int max_iterations = argc > 3 ? <font color=#008888>ACE_OS::atoi</font> (argv[3]) : 4; - - <font color=red>/* Use the basic constructor since the other isn't really very safe. */</font> - 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 (peer.open (server_host, - server_port) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>open</font>"), - -1); - - for (int i = 0; i < max_iterations; i++) - { - <font color=red>/* Tell the server which iteration we're on. No more mucking - aroudn with sprintf at this level! It's all hidden from us. */</font> - peer << "<font color=green>message = </font>" << i+1; - - <font color=red>/* Everything OK? */</font> - if (peer.error ()) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>send</font>"), - -1); - else - <font color=#008888>ACE_OS::sleep</font> (1); - } - - if (peer.close () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>close</font>"), - -1); - return 0; -} -</PRE> -<HR WIDTH="100%"> - -<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 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. -In addition, there are a lot of optimizations that this client would benefit -from! - -<P>As an exercise to the reader (don't you hate those!) I challenge you -to write the server side of this. You can take a look at IOStream_Test -in the ACE distribution if you get stuck... - -<P>If you want to compile it yourself, here's the <A HREF="client.cpp">source</A>, -the <A HREF="Makefile">Makefile</A>, -and <A HREF="00SetEnv">Environment -settings</A>. - -<P> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/005/005.dsp b/docs/tutorials/005/005.dsp deleted file mode 100644 index 785534901f1..00000000000 --- a/docs/tutorials/005/005.dsp +++ /dev/null @@ -1,114 +0,0 @@ -# Microsoft Developer Studio Project File - Name="005" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=005 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "005.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "005.mak" CFG="005 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "005 - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "005 - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "005 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "005 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"server.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "005 - Win32 Release"
-# Name "005 - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\client_handler.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\server.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\client_acceptor.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\client_handler.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/005/00SetEnv b/docs/tutorials/005/00SetEnv deleted file mode 100644 index eca78e10c85..00000000000 --- a/docs/tutorials/005/00SetEnv +++ /dev/null @@ -1,2 +0,0 @@ -export ACE_ROOT=/local/src/ACE/ACE_wrappers -export LD_LIBRARY_PATH=$ACE_ROOT/ace:$LD_LIBRARY_PATH diff --git a/docs/tutorials/005/Makefile b/docs/tutorials/005/Makefile deleted file mode 100644 index d8f01d76929..00000000000 --- a/docs/tutorials/005/Makefile +++ /dev/null @@ -1,118 +0,0 @@ -#---------------------------------------------------------------------------- -# $Id$ -#---------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -# You can generally find a Makefile in the ACE examples, tests or the library -# itself that will satisfy our application needs. This one was taken from -# one of the examples. - - # Define the name of the binary we want to create. There has to be - # a CPP file $(BIN).cpp but it doesn't necessarily have to have your - # main() in it. Most of the time, though, it will. -BIN = server - - # Few applications will have a single source file. We use the FILES - # macro to build up a list of additional files to compile. Notice - # that we leave off the extension just as with BIN -FILES = -FILES += client_handler - - # The BUILD macro is used by the ACE makefiles. Basically, it tells - # the system what to build. I don't really know what VBIN is other - # than it is constructed from the value of BIN. Just go with it... -BUILD = $(VBIN) - - # Here we use some GNU make extensions to build the SRC macro. Basically, - # we're just adding .cpp to the value of BIN and for each entry of the - # FILES macro. -SRC = $(addsuffix .cpp,$(BIN)) $(addsuffix .cpp,$(FILES)) - - # This is used by my Indent target below. It's not a part of standard - # ACE and you don't need it yourself. -HDR = *.h - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - - # This is where the real power lies! These included makefile components - # are similar to the C++ templates in ACE. That is, they do a tremendous - # amount of work for you and all you have to do is include them. - # As a matter of fact, in our project, I created a single file named - # "app.mk" that includes all of these. Our project makefiles then just - # need to include app.mk to get everything they need. - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - - # Sometimes I like to reformat my code to make it more readable. This is - # more useful for the comments than anything else. Unfortunately, the - # "indent" program doesn't quite grok C++ so I have to post-process it's - # output just a bit. -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - - # One of the targets in the ACE makefiles is "depend". It will invoke - # your compiler in a way that will generate a list of dependencies for - # you. This is a great thing! Unfortunately, it puts all of that mess - # directly into the Makefile. I prefer my Makefile to stay clean and - # 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 - -.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 > combine.shar && $(RM) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - - # Don't put anything below here. Between the "depend" target and fix.Makefile - # it's guaranteed to be lost! - - # This is inserted by the fix.Makefile script -include .depend diff --git a/docs/tutorials/005/client_acceptor.h b/docs/tutorials/005/client_acceptor.h deleted file mode 100644 index 44db0e9984b..00000000000 --- a/docs/tutorials/005/client_acceptor.h +++ /dev/null @@ -1,36 +0,0 @@ -// $Id$ - -#ifndef CLIENT_ACCEPTOR_H -#define CLIENT_ACCEPTOR_H - -/* 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. */ - -#include "ace/Acceptor.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -/* Since we want to work with sockets, we'll need a SOCK_Acceptor to - allow the clients to connect to us. */ -#include "ace/SOCK_Acceptor.h" - -/* The Client_Handler object we develop will be used to handle clients - once they're connected. The ACE_Acceptor<> 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. */ -#include "client_handler.h" - -/* Parameterize the ACE_Acceptor<> 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<> was available. You'll - get spoiled using the ACE templates because they take away a lot of - the tedious details! */ -typedef ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> Client_Acceptor; - -#endif /* CLIENT_ACCEPTOR_H */ diff --git a/docs/tutorials/005/client_handler.cpp b/docs/tutorials/005/client_handler.cpp deleted file mode 100644 index d1e51f0833c..00000000000 --- a/docs/tutorials/005/client_handler.cpp +++ /dev/null @@ -1,225 +0,0 @@ -// $Id$ - -/* 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. - - We know that including client_handler.h is redundant because - client_acceptor.h includes it. Still, the sentry prevents - double-inclusion from causing problems and it's sometimes good to - be explicit about what 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" - -/* 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) -{ -} - -/* 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) -{ - // Make sure that our peer closes when we're deleted. This - // will probably happened when the peer is deleted but it - // doesn't hurt to be explicit. - this->peer ().close (); -} - -/* 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) -{ - /* 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! */ - this->reactor ()->remove_handler (this, - ACE_Event_Handler:: READ_MASK | ACE_Event_Handler::DONT_CALL); - - /* 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. */ - delete this; -} - -/* 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) -{ - /* Convert the void* to a Client_Acceptor*. You should probably use - those fancy ACE_*_cast macros 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. */ - Client_Acceptor *acceptor = (Client_Acceptor *) _acceptor; - - /* Our reactor reference will be set when we register ourselves but - I decided to go ahead and set it here. No good reason really... */ - this->reactor (acceptor->reactor ()); - - /* 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. */ - ACE_INET_Addr addr; - - /* 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 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 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. */ - if (this->peer ().get_remote_addr (addr) == -1) - return -1; - - /* 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 any case, the test above should - always be done to ensure that the connection is worth keeping. - - 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 correct thing to do. */ - if (this->reactor ()->register_handler (this, - ACE_Event_Handler::READ_MASK) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) can't register with reactor\n"), - -1); - - /* 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 ())); - - /* Always return zero on success. */ - return 0; -} - -/* 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) -{ - /* Some compilers don't like it when you fail to use a parameter. - This macro will keep 'em quiet for you. */ - ACE_UNUSED_ARG (handle); - - /* 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. */ - char buf[BUFSIZ]; - - /* 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. */ - return this->process (buf, sizeof (buf)); -} - -/* 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) -{ - ACE_UNUSED_ARG (handle); - ACE_UNUSED_ARG (mask); - - delete this; - return 0; -} - -/* 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) -{ - ssize_t bytes_read = -1; - - /* 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 something wrong has happened. The - reactor wouldn't have called us if there wasn't some kind of read - activity but there wouldn't be activity if there were no bytes to - read... - - On the other hand, if we got some data then we can display it in - a debug message for everyone to see. */ - switch ( (bytes_read = 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 - // NULL-terminate the string before printing it. - rdbuf[bytes_read] = 0; - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) from client: %s", - rdbuf)); - } - - /* It's also worth mentioning that recv() has a cousin: recv_n(). - recv_n() will receive exactly the number of bytes you provide it. - This is very good when you know exactly how much you expect to - receive. For the application here, unfortunately, we don't have - any idea how much the client will be sending. recv() will read - up-to-but-not-more-than the number of bytes we specify (e.g. -- - _rdbuf_len). That works well when we don't know how much the - client will provide. */ - - return 0; -} diff --git a/docs/tutorials/005/client_handler.h b/docs/tutorials/005/client_handler.h deleted file mode 100644 index 03d3b1a8e10..00000000000 --- a/docs/tutorials/005/client_handler.h +++ /dev/null @@ -1,100 +0,0 @@ -// $Id$ - -#ifndef CLIENT_HANDLER_H -#define CLIENT_HANDLER_H - -/* 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 derive our Client_Handler directly from - ACE_Event_Handler but you still have to have an ACE_SOCK_Stream for - the actual connection. With a direct derivative of - ACE_Event_Handler, you'll have to contain and maintain an - 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. */ - -#include "ace/Svc_Handler.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "ace/SOCK_Stream.h" - -/* Another feature of ACE_Svc_Handler is it's ability to present the - ACE_Task<> interface as well. That's what the ACE_NULL_SYNCH - parameter below is all about. That's beyond our scope here but - we'll come back to it in the next tutorial when we start looking at - concurrency options. */ -class Client_Handler : public ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> -{ -public: - // Constructor... - Client_Handler (void); - - /* 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. */ - void destroy (void); - - /* 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 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 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 definition of open() - you'll see how we get around that. */ - int open (void *acceptor); - - /* 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 clean itself - up. Since an event handler can be registered for more than one - type of callback, the callback mask is provided to inform - handle_close() exactly which method failed. That way, you don't - have to maintain state information between your handle_* method - calls. The <handle> parameter is explained below... 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); - -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 _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 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 <handle> would - be important to us for reading the client's data. */ - int handle_input (ACE_HANDLE handle); - - /* 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 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. */ - int process (char *rdbuf, int rdbuf_len); - - /* 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. */ - ~Client_Handler (void); -}; - -#endif /* CLIENT_HANDLER_H */ diff --git a/docs/tutorials/005/combine.shar b/docs/tutorials/005/combine.shar deleted file mode 100644 index 841589e3c0c..00000000000 --- a/docs/tutorials/005/combine.shar +++ /dev/null @@ -1,423 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/005'. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 598 -rw-rw-r-- hdr -# 97 -rw-rw-r-- bodies -# 628 -rw-rw-r-- page01.pre -# 515 -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 -# 172 -rw-rw-r-- page07.pre -# 715 -rw-rw-r-- page08.pre -# -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 _sh32383; 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="Billy Quinn"> -X <META NAME="Description" CONTENT="A first step towards using ACE productively"> -X <TITLE>ACE Tutorial 005</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> -X -<CENTER><B><FONT SIZE=+2>ACE Tutorial 005</FONT></B></CENTER> -X -<CENTER><B><FONT SIZE=+2>On the road to a multithreaded server</FONT></B></CENTER> -X -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -197a3d789965f9c046d4d84ee137ace9 hdr -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`" - test 598 -eq "$shar_count" || - $echo 'hdr:' 'original size' '598,' '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 -Makefile -X../fix.Makefile -SHAR_EOF - $shar_touch -am 0117143799 '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' -dcbb8d7d85345e022a122f4f7fa10fb9 bodies -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`" - test 97 -eq "$shar_count" || - $echo 'bodies:' 'original size' '97,' '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 flash-back to the simple server we -created a while back. We'll create a very simple server where everything -takes place in one thread. Once we have a solid understanding there, -we'll move on to the next tutorial where we begin to introduce concurrency -concepts. -X -<P>There are four C++ source files in this tutorial: server.cpp, -client_acceptor.h, client_handler.h and client_handler.cpp. I'll -talk about each of these in turn with the usual color commentary as we -go. In addition, I'll briefly discuss the Makefile and a short perl -script I've added. -X -<P> -SHAR_EOF - $shar_touch -am 03191459100 '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' -b819665dcbed1ef2efe12bdc8d8710c5 page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 628 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '628,' '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 -<P>We begin with <I><A HREF="server.cpp">server.cpp</A></I>. -<P> -Abstraction by Kirthika: -<UL> -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 ACE_Reactor to handle events. Everything -occurs in a single thread. -<P> -This tutorial is a stepping stone towards a mutithreaded server model. -</ul> -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -94844c847ed36aa6bc7c7b98aafb7bbc page02.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`" - test 515 -eq "$shar_count" || - $echo 'page02.pre:' 'original size' '515,' '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 -<P>Now, let's take a look at <I><A HREF="client_acceptor.h">client_acceptor.h</A></I>. -Since I went on about how it does all the work of letting clients connect -to us, it must be rather complex. Right? Wrong. -X -<P>The more you use ACE, the more you'll find that they've already taken -care of most details for you. With respect to the acceptance of client -connections: there just aren't that many ways to do it! The -ACE team has chosen an approach and created a C++ template that does -all of the work for you. All you're required to do is provide it -with an object type to instantiate when a new connection arrives. -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -edb44ba6e3033259e60b4a83d0675b03 page03.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`" - test 685 -eq "$shar_count" || - $echo 'page03.pre:' 'original size' '685,' '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 -<P>Ok, so we've got a main() loop that sets up the acceptor and we've seen -how easy it is to create the acceptor object. So far, we've hardly -written any code at all. Well, that's just about to change... -X -<P>First, we look at <I><A HREF="client_handler.h">client_handler.h</A></I> -for the declaration of the Client_Handler object. Then we look at -the definition where all of the real work of the application takes place. -X -<P> -<HR WIDTH="100%"> -X -SHAR_EOF - $shar_touch -am 03191459100 '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' -3a0e0d0c79318ca18dd5920dd97ca834 page04.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`" - test 464 -eq "$shar_count" || - $echo 'page04.pre:' 'original size' '464,' '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 -<P>Now we're finally at <I><A HREF="client_handler.cpp">client_handler.cpp</A></I> -where we have to write some code. This file has more code than the -rest of the application all together. -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -d5fa96547c3b94abc387c8b87f2f3c92 page05.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`" - test 218 -eq "$shar_count" || - $echo 'page05.pre:' 'original size' '218,' '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 -<P>Before we go, I wanted you to see the <A HREF="Makefile">Makefile</A>. -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -b8a35eb354a8e5c90155dd728a8bfa4e page06.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page06.pre'`" - test 98 -eq "$shar_count" || - $echo 'page06.pre:' 'original size' '98,' '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 -<P>And last (and probably least) is the <A HREF="../fix.Makefile">perl script</A> -that pulls the dependency stuff out of Makefile and into .depend. -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -7f896dc992a365d4d095d0a6d3b9eb47 page07.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page07.pre'`" - test 172 -eq "$shar_count" || - $echo 'page07.pre:' 'original size' '172,' 'current size' "$shar_count!" - fi -fi -# ============= page08.pre ============== -if test -f 'page08.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page08.pre' '(file already exists)' -else - $echo 'x -' extracting 'page08.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page08.pre' && -X -<P>That's it for Tutorial 5. In this tutorial we've built a single-threaded -reactor-based server. We've done a couple of things that aren't exactly -necessary for such an implementation but I plan to build on that as -we explore two other concurrency strategies: thread per connection -and thread pool. -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 03191459100 'page08.pre' && - chmod 0664 'page08.pre' || - $echo 'restore of' 'page08.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 'page08.pre:' 'MD5 check failed' -678ef0c3162d2a2739d0efdcfeac5cb9 page08.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page08.pre'`" - test 715 -eq "$shar_count" || - $echo 'page08.pre:' 'original size' '715,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh32383 -exit 0 diff --git a/docs/tutorials/005/page01.html b/docs/tutorials/005/page01.html deleted file mode 100644 index a3324f51fa0..00000000000 --- a/docs/tutorials/005/page01.html +++ /dev/null @@ -1,35 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="Billy Quinn"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> - <TITLE>ACE Tutorial 005</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 005</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>On the road to a multithreaded server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>In this tutorial, we're going to flash-back to the simple server we -created a while back. We'll create a very simple server where everything -takes place in one thread. Once we have a solid understanding there, -we'll move on to the next tutorial where we begin to introduce concurrency -concepts. - -<P>There are four C++ source files in this tutorial: server.cpp, -client_acceptor.h, client_handler.h and client_handler.cpp. I'll -talk about each of these in turn with the usual color commentary as we -go. In addition, I'll briefly discuss the Makefile and a short perl -script I've added. - -<P> -<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/005/page02.html b/docs/tutorials/005/page02.html deleted file mode 100644 index d9f111507c1..00000000000 --- a/docs/tutorials/005/page02.html +++ /dev/null @@ -1,153 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="Billy Quinn"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> - <TITLE>ACE Tutorial 005</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 005</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>On the road to a multithreaded server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>We begin with <I><A HREF="server.cpp">server.cpp</A></I>. -<P> -Abstraction by Kirthika: -<UL> -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 ACE_Reactor to handle events. Everything -occurs in a single thread. -<P> -This tutorial is a stepping stone towards a mutithreaded server model. -</ul> -<P> -<HR WIDTH="100%"> -<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 not 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[]) -{ - ACE_UNUSED_ARG(argc); - ACE_UNUSED_ARG(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>/* Here, we know that the open was successful. If it had failed, we - would have exited above. A nice side-effect of the open() is that - we're already registered with the reactor we provided it. */</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 'restart' 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_EXPLICIT_TEMPLATE_INSTANTIATION</font>) -template class ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR>; -template class ACE_Svc_Handler<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 <Client_Handler, ACE_SOCK_ACCEPTOR> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> -<font color=blue>#endif</font> <font color=red>/* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */</font> -</PRE> -<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/005/page03.html b/docs/tutorials/005/page03.html deleted file mode 100644 index eb8d99b9e0d..00000000000 --- a/docs/tutorials/005/page03.html +++ /dev/null @@ -1,73 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="Billy Quinn"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> - <TITLE>ACE Tutorial 005</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 005</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>On the road to a multithreaded server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>Now, let's take a look at <I><A HREF="client_acceptor.h">client_acceptor.h</A></I>. -Since I went on about how it does all the work of letting clients connect -to us, it must be rather complex. Right? Wrong. - -<P>The more you use ACE, the more you'll find that they've already taken -care of most details for you. With respect to the acceptance of client -connections: there just aren't that many ways to do it! The -ACE team has chosen an approach and created a C++ template that does -all of the work for you. All you're required to do is provide it -with an object type to instantiate when a new connection arrives. - -<P> -<HR WIDTH="100%"> -<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<> 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> "<A HREF="../../../ace/Acceptor.h">ace/Acceptor.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<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> "<A HREF="../../../ace/SOCK_Acceptor.h">ace/SOCK_Acceptor.h</A>" - -<font color=red>/* The Client_Handler object we develop will be used to handle clients - once they're connected. The ACE_Acceptor<> 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<> 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<> was available. You'll - get spoiled using the ACE templates because they take away a lot of - the tedious details! */</font> -typedef ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> Client_Acceptor; - -<font color=blue>#endif</font> <font color=red>/* CLIENT_ACCEPTOR_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page04.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/005/page04.html b/docs/tutorials/005/page04.html deleted file mode 100644 index 1cede9705cb..00000000000 --- a/docs/tutorials/005/page04.html +++ /dev/null @@ -1,135 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="Billy Quinn"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> - <TITLE>ACE Tutorial 005</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 005</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>On the road to a multithreaded server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>Ok, so we've got a main() loop that sets up the acceptor and we've seen -how easy it is to create the acceptor object. So far, we've hardly -written any code at all. Well, that's just about to change... - -<P>First, we look at <I><A HREF="client_handler.h">client_handler.h</A></I> -for the declaration of the Client_Handler object. Then we look at -the definition where all of the real work of the application takes place. - -<P> -<HR WIDTH="100%"> - -<PRE> -<font color=red>// $Id$</font> - -<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 derive our Client_Handler directly from - ACE_Event_Handler but you still have to have an ACE_SOCK_Stream for - the actual connection. With a direct derivative of - ACE_Event_Handler, you'll have to contain and maintain an - 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> - -<font color=blue>#include</font> "<A HREF="../../../ace/Svc_Handler.h">ace/Svc_Handler.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" - -<font color=red>/* Another feature of ACE_Svc_Handler is it's ability to present the - ACE_Task<> interface as well. That's what the ACE_NULL_SYNCH - parameter below is all about. That's beyond our scope here but - we'll come back to it in the next tutorial when we start looking at - concurrency options. */</font> -class Client_Handler : public ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> -{ -public: - <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 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 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 definition of open() - you'll see how we get around that. */</font> - int open (void *acceptor); - - <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 clean itself - up. Since an event handler can be registered for more than one - type of callback, the callback mask is provided to inform - handle_close() exactly which method failed. That way, you don't - have to maintain state information between your handle_* method - calls. The <handle> parameter is explained below... 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! */</font> - int handle_close (ACE_HANDLE handle, - ACE_Reactor_Mask mask); - -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 _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 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 <handle> 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(). That - allows me to 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> - 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); -}; - -<font color=blue>#endif</font> <font color=red>/* CLIENT_HANDLER_H */</font> -</PRE> -<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/005/page05.html b/docs/tutorials/005/page05.html deleted file mode 100644 index 541fce8d11a..00000000000 --- a/docs/tutorials/005/page05.html +++ /dev/null @@ -1,255 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="Billy Quinn"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> - <TITLE>ACE Tutorial 005</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 005</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>On the road to a multithreaded server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>Now we're finally at <I><A HREF="client_handler.cpp">client_handler.cpp</A></I> -where we have to write some code. This file has more code than the -rest of the application all together. - -<P> -<HR WIDTH="100%"> -<PRE> -<font color=red>// $Id$</font> - -<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. - - We know that including client_handler.h is redundant because - client_acceptor.h includes it. Still, the sentry prevents - double-inclusion from causing problems and it's sometimes good to - be explicit about what we're using. - - On the other hand, we don't directly include any ACE header files - here. */</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... */</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. */</font> -<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 happened when the peer is deleted but it</font> - <font color=red>// doesn't hurt to be explicit.</font> - this->peer ().close (); -} - -<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. */</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 | <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... */</font> -int -<font color=#008888>Client_Handler::open</font> (void *_acceptor) -{ - <font color=red>/* Convert the void* to a Client_Acceptor*. You should probably use - those fancy ACE_*_cast macros 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 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>/* 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 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 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>/* 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 any case, the test above should - always be done to ensure that the connection is worth keeping. - - 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 correct thing to do. */</font> - if (this->reactor ()->register_handler (this, - <font color=#008888>ACE_Event_Handler::READ_MASK</font>) == -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. */</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>/* 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. */</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[BUFSIZ]; - - <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. */</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); - - delete this; - 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. */</font> -int -<font color=#008888>Client_Handler::process</font> (char *rdbuf, - int rdbuf_len) -{ - ssize_t bytes_read = -1; - - <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 something wrong has happened. The - reactor wouldn't have called us if there wasn't some kind of read - activity but there wouldn't be activity if there were no bytes to - read... - - On the other hand, if we got some data then we can display it in - a debug message for everyone to see. */</font> - switch ( (bytes_read = 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> - <font color=red>// NULL-terminate the string before printing it.</font> - rdbuf[bytes_read] = 0; - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) from client: %s</font>", - rdbuf)); - } - - <font color=red>/* It's also worth mentioning that recv() has a cousin: recv_n(). - recv_n() will receive exactly the number of bytes you provide it. - This is very good when you know exactly how much you expect to - receive. For the application here, unfortunately, we don't have - any idea how much the client will be sending. recv() will read - up-to-but-not-more-than the number of bytes we specify (e.g. -- - _rdbuf_len). That works well when we don't know how much the - client will provide. */</font> - - return 0; -} -</PRE> -<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/005/page06.html b/docs/tutorials/005/page06.html deleted file mode 100644 index 5034104d33f..00000000000 --- a/docs/tutorials/005/page06.html +++ /dev/null @@ -1,146 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="Billy Quinn"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> - <TITLE>ACE Tutorial 005</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 005</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>On the road to a multithreaded server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>Before we go, I wanted you to see the <A HREF="Makefile">Makefile</A>. - -<P> -<HR WIDTH="100%"> -<PRE> -#---------------------------------------------------------------------------- -# $Id$ -#---------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -# You can generally find a Makefile in the ACE examples, tests or the library -# itself that will satisfy our application needs. This one was taken from -# one of the examples. - - # Define the name of the binary we want to create. There has to be - # a CPP file $(BIN).cpp but it doesn't necessarily have to have your - # main() in it. Most of the time, though, it will. -BIN = server - - # Few applications will have a single source file. We use the FILES - # macro to build up a list of additional files to compile. Notice - # that we leave off the extension just as with BIN -FILES = -FILES += client_handler - - # The BUILD macro is used by the ACE makefiles. Basically, it tells - # the system what to build. I don't really know what VBIN is other - # than it is constructed from the value of BIN. Just go with it... -BUILD = $(VBIN) - - # Here we use some GNU make extensions to build the SRC macro. Basically, - # we're just adding .cpp to the value of BIN and for each entry of the - # FILES macro. -SRC = $(addsuffix .cpp,$(BIN)) $(addsuffix .cpp,$(FILES)) - - # This is used by my Indent target below. It's not a part of standard - # ACE and you don't need it yourself. -HDR = *.h - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - - # This is where the real power lies! These included makefile components - # are similar to the C++ templates in ACE. That is, they do a tremendous - # amount of work for you and all you have to do is include them. - # As a matter of fact, in our project, I created a single file named - # "<font color=green>app.mk</font>" that includes all of these. Our project makefiles then just - # need to include app.mk to get everything they need. - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - - # Sometimes I like to reformat my code to make it more readable. This is - # more useful for the comments than anything else. Unfortunately, the - # "<font color=green>indent</font>" program doesn't quite grok C++ so I have to post-process it's - # output just a bit. -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - - # One of the targets in the ACE makefiles is "<font color=green>depend</font>". It will invoke - # your compiler in a way that will generate a list of dependencies for - # you. This is a great thing! Unfortunately, it puts all of that mess - # directly into the Makefile. I prefer my Makefile to stay clean and - # 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 - <font color=blue># include</font> 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 - -.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 > combine.shar && $(RM) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - - # Don't put anything below here. Between the "<font color=green>depend</font>" target and fix.Makefile - # it's guaranteed to be lost! - - # This is inserted by the fix.Makefile script -include .depend -</PRE> -<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/005/page07.html b/docs/tutorials/005/page07.html deleted file mode 100644 index c3043ee1fed..00000000000 --- a/docs/tutorials/005/page07.html +++ /dev/null @@ -1,97 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="Billy Quinn"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> - <TITLE>ACE Tutorial 005</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 005</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>On the road to a multithreaded server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>And last (and probably least) is the <A HREF="../fix.Makefile">perl script</A> -that pulls the dependency stuff out of Makefile and into .depend. - -<P> -<HR WIDTH="100%"> -<PRE> -eval '(exit $?0)' && eval 'exec perl -w -S $0 ${1+"<font color=green>$@</font>"}' - & eval 'exec perl -S $0 $argv:q' - if 0; - -require "<font color=green>getopts.pl</font>"; -&Getopts("<font color=green>f:o:</font>"); - -$opt_f = "<font color=green>Makefile</font>" if( ! $opt_f ); -$opt_o = "<font color=green>.depend</font>" if( ! $opt_o ); - - # Open the Makefile that has been mangled by 'make depend' - # and suck it into a perl array. -open(IF,"<font color=green><$opt_f</font>") || die; -@makefile = <IF>; -close(IF); - - # Now open our .depend file and a temporary Makefile. - # We'll split the original Makefile between these two. -open(DF,"<font color=green>>$opt_o</font>") || die; -open(MF,"<font color=green>>$opt_f.tmp</font>") || die; - - # For each line we read out of the original file... -foreach (@makefile) { - - # If we're into the dependency section, write the line - # into the .depend file. - # - if( $depend ) { - print DF $_; - } - else { - # If we haven't gotten to the dependency section yet - # then see if the current line is the separator that - # "<font color=green>make depend</font>" causes to be inserted. - # - if( m/^\Q# DO NOT DELETE THIS LINE -- g++dep uses it.\E/ ) { - - # If so, change our "<font color=green>mode</font>" and skip this line. - ++$depend; - next; - } - - # Also skip the "<font color=green>include .depend</font>" that we insert. If we - # don't do this, it is possible to have a bunch of these - # inserted into the output when we read an unmangled Makefile - next if( m/^include $opt_o/ ); - - # Print the non-dependency info to the temporary Makefile - print MF $_; - } -} - -# Tell our new Makefile to include the dependency file -print MF "<font color=green>include $opt_o\n</font>"; - -# Close the two output files... -close(DF); -close(MF); - -# Unlink (remove) the original Makefile and rename our -# temporary file. There's obviously room for error checking -# here but we've got the Makefile checked into some revision -# control system anyway. Don't we? - -unlink("<font color=green>$opt_f</font>"); -rename("<font color=green>$opt_f.tmp</font>","<font color=green>$opt_f</font>"); - -exit(0); -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page08.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/005/page08.html b/docs/tutorials/005/page08.html deleted file mode 100644 index 602c436d0de..00000000000 --- a/docs/tutorials/005/page08.html +++ /dev/null @@ -1,49 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="Billy Quinn"> - <META NAME="Description" CONTENT="A first step towards using ACE productively"> - <TITLE>ACE Tutorial 005</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 005</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>On the road to a multithreaded server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>That's it for Tutorial 5. In this tutorial we've built a single-threaded -reactor-based server. We've done a couple of things that aren't exactly -necessary for such an implementation but I plan to build on that as -we explore two other concurrency strategies: thread per connection -and thread pool. - -<P>For reference, here's the file list again: -<UL> -<LI> -<A HREF="Makefile">Makefile</A></LI> - -<LI> -<A HREF="client_acceptor.h">client_acceptor.h</A></LI> - -<LI> -<A HREF="client_handler.cpp">client_handler.cpp</A></LI> - -<LI> -<A HREF="client_handler.h">client_handler.h</A></LI> - -<LI> -<A HREF="server.cpp">server.cpp</A></LI> - -<LI> -<A HREF="../fix.Makefile">fix.Makefile</A></LI> -</UL> - -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/005/server.brk b/docs/tutorials/005/server.brk deleted file mode 100644 index ba3d878a1da..00000000000 --- a/docs/tutorials/005/server.brk +++ /dev/null @@ -1,154 +0,0 @@ - -#include "ace/Acceptor.h" -#include "ace/SOCK_Acceptor.h" -#include "ace/Reactor.h" -#include "ace/Thread.h" - - -ACE_Reactor * g_reactor; - -static sig_atomic_t finished = 0; - -class Logging_Handler; - -extern "C" void handler (int) { finished = 1; } - - - -class Reactor_Derived : public ACE_Reactor -{ - -public : - Reactor_Derived() : () - { - counter = 0; - } - - virtual ~Reactor_Derived() - { - cout << "*****Calling the reactor destructor*****" << endl; - } - -private : - friend class Logging_Handler; - - // counter is used to keep track of the number of service handlers - // registered with this reactor (Surely theres a better way ;-) - int counter; -}; - -class Logging_Handler : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> -{ - -public: - - Logging_Handler (void) { }; - - virtual void destroy (void) - { - if (this->thread_reactorP->remove_handler(this, - ACE_Event_Handler::READ_MASK | ACE_Event_Handler::DONT_CALL) == -1 - ) - ACE_ERROR_RETURN ((LM_ERROR, "can'(%P|%t) t remove service from reactor\n"), -1); - - // Decrement the handler tracking variable in the reactor to - // indicate this service handler has terminated - --thread_reactorP->counter; - - this->peer ().close (); - delete this; - } - - static void *run_thread(Logging_Handler *this_) - { - Reactor_Derived thread_reactor; - - this_->thread_reactorP = &thread_reactor; - - // Increment our handler counter to account for this service handler - ++thread_reactor.counter; - - if (thread_reactor.register_handler(this_, ACE_Event_Handler::READ_MASK) == -1) - ACE_ERROR_RETURN ((LM_ERROR,"can'(%P|%t) t register with reactor\n"), -1); - - while( thread_reactor.counter > 0 ) - { - // If thread_reactor.counter = 0 then we have no more service - // handlers connected to the reactor. We set a timeout value - // of 1 second so that the handle_events loop break out every - // second to check on the count ( because of it blocking - // even when there are no connections we need to do this) - thread_reactor.handle_events(ACE_Time_Value(1,0)); - } - } - - virtual int open (void *) - { - ACE_Thread::spawn(&Logging_Handler::run_thread,this); - return 0; - } - - virtual int close (u_long) - { - this->destroy (); - return 0; - } - -protected: - - virtual int handle_input (ACE_HANDLE) - { - char buf[128]; - memset(buf,0,sizeof(buf)); - - switch( this->peer().recv(buf,sizeof buf) ) - { - case -1: - ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p bad read\n", "client logger"), -1); - case 0: - ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) closing log daemon (fd = %d)\n", this->get_handle ()), -1); - default: - ACE_DEBUG ((LM_DEBUG, "(%p|%t) from client : %s",buf)); - } - - return 0; - } - - -private: - Reactor_Derived *thread_reactorP; -}; - - -typedef ACE_Acceptor <Logging_Handler, ACE_SOCK_ACCEPTOR> Logging_Acceptor; - - -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -int main (int argc, char *argv[]) -{ - g_reactor = new ACE_Reactor; - - // Acceptor factory. - Logging_Acceptor peer_acceptor; - - if (peer_acceptor.open (ACE_INET_Addr (PORT)) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), -1); - - else if (g_reactor->register_handler (&peer_acceptor, ACE_Event_Handler::READ_MASK) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "registering service with ACE_Reactor\n"), -1); - - ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT); - - // Run forever, performing logging service. - - ACE_DEBUG ((LM_DEBUG, "(%P|%t) starting up server logging daemon\n")); - - // Perform logging service until QUIT_HANDLER receives SIGINT. - while ( !finished ) - g_reactor->handle_events (); - - ACE_DEBUG ((LM_DEBUG, "(%P|%t) shutting down server logging daemon\n")); - - return 0; -} diff --git a/docs/tutorials/005/server.cpp b/docs/tutorials/005/server.cpp deleted file mode 100644 index dee968339d7..00000000000 --- a/docs/tutorials/005/server.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// $Id$ - -/* 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 "real work". */ - -#include "client_acceptor.h" - -/* 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. */ - -static sig_atomic_t finished = 0; -extern "C" void handler (int) -{ - finished = 1; -} - -/* 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 not what we want to focus on, - so we're taking the easy way out. */ - -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -/* 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. */ - -int -main (int argc, char *argv[]) -{ - ACE_UNUSED_ARG(argc); - ACE_UNUSED_ARG(argv); - - /* 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. */ - ACE_Reactor reactor; - - /* 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.) */ - Client_Acceptor peer_acceptor; - - /* 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 "well known" 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. */ - if (peer_acceptor.open (ACE_INET_Addr (PORT), - &reactor) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "open"), - -1); - - /* Here, we know that the open was successful. If it had failed, we - would have exited above. A nice side-effect of the open() is that - we're already registered with the reactor we provided it. */ - - /* 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 "real" work. Our simple - flag-setter doesn't justify deriving from ACE_Event_Handler and - providing a callback function though. */ - ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT); - - /* 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. */ - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) starting up server daemon\n")); - - /* This will loop "forever" 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 'restart' flag on the - open() method of ACE_Reactor if you're interested.) */ - while (!finished) - reactor.handle_events (); - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) shutting down server daemon\n")); - - return 0; -} - -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR>; -template class ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>; -#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> -#pragma instantiate ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> -#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/docs/tutorials/006/006.dsp b/docs/tutorials/006/006.dsp deleted file mode 100644 index fe6c488995d..00000000000 --- a/docs/tutorials/006/006.dsp +++ /dev/null @@ -1,112 +0,0 @@ -# Microsoft Developer Studio Project File - Name="006" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=006 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "006.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "006.mak" CFG="006 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "006 - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "006 - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "006 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "006 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"server.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "006 - Win32 Release"
-# Name "006 - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\client_handler.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\server.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\client_acceptor.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\client_handler.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/006/Makefile b/docs/tutorials/006/Makefile deleted file mode 100644 index 57a90088d72..00000000000 --- a/docs/tutorials/006/Makefile +++ /dev/null @@ -1,114 +0,0 @@ -#---------------------------------------------------------------------------- -# $Id$ -#---------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -# You can generally find a Makefile in the ACE examples, tests or the library -# itself that will satisfy our application needs. This one was taken from -# one of the examples. - - # Define the name of the binary we want to create. There has to be - # a CPP file $(BIN).cpp but it doesn't necessarily have to have your - # main() in it. Most of the time, though, it will. -BIN = server - - # Few applications will have a single source file. We use the FILES - # macro to build up a list of additional files to compile. Notice - # that we leave off the extension just as with BIN -FILES = -FILES += client_handler - - # The BUILD macro is used by the ACE makefiles. Basically, it tells - # the system what to build. I don't really know what VBIN is other - # than it is constructed from the value of BIN. Just go with it... -BUILD = $(VBIN) - - # Here we use some GNU make extensions to build the SRC macro. Basically, - # we're just adding .cpp to the value of BIN and for each entry of the - # FILES macro. -SRC = $(addsuffix .cpp,$(BIN)) $(addsuffix .cpp,$(FILES)) - - # This is used by my Indent target below. It's not a part of standard - # ACE and you don't need it yourself. -HDR = *.h - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - - # This is where the real power lies! These included makefile components - # are similar to the C++ templates in ACE. That is, they do a tremendous - # amount of work for you and all you have to do is include them. - # As a matter of fact, in our project, I created a single file named - # "app.mk" that includes all of these. Our project makefiles then just - # need to include app.mk to get everything they need. - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - - # Sometimes I like to reformat my code to make it more readable. This is - # more useful for the comments than anything else. Unfortunately, the - # "indent" program doesn't quite grok C++ so I have to post-process it's - # output just a bit. -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - - # One of the targets in the ACE makefiles is "depend". It will invoke - # your compiler in a way that will generate a list of dependencies for - # you. This is a great thing! Unfortunately, it puts all of that mess - # directly into the Makefile. I prefer my Makefile to stay clean and - # 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. -Depend : depend - perl ../fix.Makefile - -.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) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - - # Don't put anything below here. Between the "depend" target and fix.Makefile - # it's guaranteed to be lost! - - # This is inserted by the fix.Makefile script -include .depend diff --git a/docs/tutorials/006/client_acceptor.h b/docs/tutorials/006/client_acceptor.h deleted file mode 100644 index 4a50de72952..00000000000 --- a/docs/tutorials/006/client_acceptor.h +++ /dev/null @@ -1,74 +0,0 @@ -// $Id$ - -#ifndef CLIENT_ACCEPTOR_H -#define CLIENT_ACCEPTOR_H - -/* The ACE_Acceptor<> template lives in the ace/Acceptor.h header - file. You'll find a very consistent 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. */ - -#include "ace/Acceptor.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -/* Since we want to work with sockets, we'll need a SOCK_Acceptor to - allow the clients to connect to us. */ -#include "ace/SOCK_Acceptor.h" - -/* The Client_Handler object we develop will be used to handle clients - once they're connected. The ACE_Acceptor<> 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. */ -#include "client_handler.h" - -/* Parameterize the ACE_Acceptor<> 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<> was available. You'll - get spoiled using the ACE templates because they take away a lot of - the tedious details! */ -typedef ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> Client_Acceptor_Base; - -/* Here, we use the parameterized ACE_Acceptor<> 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. */ -class Client_Acceptor : public Client_Acceptor_Base -{ -public: - /* - This is always a good idea. If nothing else, it makes your code more - orthogonal no matter what baseclasses your objects have. - */ - typedef Client_Acceptor_Base inherited; - - /* - 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. - */ - Client_Acceptor (int thread_per_connection = 1) - : thread_per_connection_ (thread_per_connection) - { - } - - /* 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. */ - int thread_per_connection (void) - { - return this->thread_per_connection_; - } - -protected: - int thread_per_connection_; -}; - -#endif /* CLIENT_ACCEPTOR_H */ diff --git a/docs/tutorials/006/client_handler.cpp b/docs/tutorials/006/client_handler.cpp deleted file mode 100644 index 9d6b5362d63..00000000000 --- a/docs/tutorials/006/client_handler.cpp +++ /dev/null @@ -1,293 +0,0 @@ -// $Id$ - -/* 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. - - We know that including client_handler.h is redundant because - client_acceptor.h includes it. Still, the sentry prevents - double-inclusion from causing problems and it's sometimes good to - be explicit about what 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" - -/* 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) -{ -} - -/* 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) -{ -} - -/* 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) -{ - /* 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! */ - this->reactor ()->remove_handler (this, - ACE_Event_Handler::READ_MASK - | ACE_Event_Handler::DONT_CALL); - - /* 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. */ - delete this; -} - -/* 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 *void_acceptor) -{ - /* 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. */ - ACE_INET_Addr addr; - - /* 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 - 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. */ - if (this->peer ().get_remote_addr (addr) == -1) - return -1; - - /* Convert the void* to a Client_Acceptor*. You should probably use - those fancy ACE_*_cast macros 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. */ - Client_Acceptor *acceptor = (Client_Acceptor *) void_acceptor; - - /* 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 svc() method will then begin - executing in that thread. - - If we are told to use the single-threaded strategy, there is no - difference between this and the Tutorial 5 implementation. - - Note that if we're in thread-per-connection mode, open() is exited - at this point. Furthermore, thread-per-connection mode does not - use the reactor which means that handle_input() and it's fellows - are not invoked. */ - if (acceptor->thread_per_connection ()) - return this->activate (THR_DETACHED); - - // ************************************************************************ - // From here on, we're doing the traditional reactor thing. If - // you're operating in thread-per-connection mode, this code does - // not apply. - // ************************************************************************ - - /* Our reactor reference will be set when we register ourselves but - I decided to go ahead and set it here. No good reason really... */ - this->reactor (acceptor->reactor ()); - - /* 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 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 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 correct thing to do. */ - if (this->reactor ()->register_handler (this, - ACE_Event_Handler::READ_MASK) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) can't register with reactor\n"), - -1); - - /* 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 ())); - - /* Always return zero on success. */ - return 0; -} - -/* 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) -{ - ACE_UNUSED_ARG (flags); - - /* 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. */ - this->destroy (); - - /* 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! */ - return 0; -} - -/* 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. - - Again, this is not used if we're in thread-per-connection mode. */ -int -Client_Handler::handle_input (ACE_HANDLE handle) -{ - /* Some compilers don't like it when you fail to use a parameter. - This macro will keep 'em quiet for you. */ - ACE_UNUSED_ARG (handle); - - /* 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. */ - char buf[BUFSIZ]; - - /* 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. */ - return this->process (buf, sizeof (buf)); -} - -/* 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) -{ - ACE_UNUSED_ARG (handle); - ACE_UNUSED_ARG (mask); - - this->destroy (); - return 0; -} - -/* The ACE_Svc_Handler<> is ultimately derived from ACE_Task<>. 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. - - Of course, this is only valid if we're in thread-per-connection - mode. If we're using the reactor model, then svc() never comes - into play. */ -int -Client_Handler::svc(void) -{ - /* 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(). */ - char buf[BUFSIZ]; - - // Forever... - while( 1 ) - { - /* Invoke the process() 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 concurrency strategy. Since process() - has all of our application-level logic, it's nice that it - doesn't have to change when we decide to go multi-threaded. - - 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. */ - if (this->process(buf, sizeof (buf)) == -1) - return -1; - } - - return 0; -} - -/* 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) -{ - /* 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 something wrong has happened. The reactor - wouldn't have called us if there wasn't some kind of read activity - but there wouldn't be activity if there were no bytes to read... - - On the other hand, if we got some data then we can display it in a - debug message for everyone to see. */ - ssize_t bytes_read; - switch ( (bytes_read = this->peer ().recv (rdbuf, rdbuf_len)) ) - { - case -1: - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) %p bad read\n", - "client"), - -1); - case 0: - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) closing daemon (fd = %d)\n", - this->get_handle ()), - -1); - default: - rdbuf[bytes_read] = 0; - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) from client: %s", - rdbuf)); - } - - return 0; -} diff --git a/docs/tutorials/006/client_handler.h b/docs/tutorials/006/client_handler.h deleted file mode 100644 index e8d3695d37c..00000000000 --- a/docs/tutorials/006/client_handler.h +++ /dev/null @@ -1,118 +0,0 @@ -// $Id$ - -#ifndef CLIENT_HANDLER_H -#define CLIENT_HANDLER_H - -/* 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 derive our Client_Handler directly from - ACE_Event_Handler but you still have to have an ACE_SOCK_Stream for - the actually connection. With a direct derivative of - ACE_Event_Handler, you'll have to contain and maintain an - 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. - - */ - -#include "ace/Svc_Handler.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "ace/SOCK_Stream.h" - -/* Another feature of ACE_Svc_Handler is it's ability to present the - ACE_Task<> 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 things 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> -{ -public: - typedef ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> inherited; - - // Constructor... - Client_Handler (void); - - /* 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. */ - void destroy (void); - - /* 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 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 - definition of open() you'll see how we get around that. */ - int open (void *acceptor); - - /* When an ACE_Task<> 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. */ - int close (u_long flags = 0); - - /* 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 clean itself - up. Since an event handler can be registered for more than one - type of callback, the callback mask is provided to inform - handle_close() exactly which method failed. That way, you don't - have to maintain state information between your handle_* method - calls. The <handle> parameter is explained below... 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! */ - virtual int handle_close (ACE_HANDLE handle = ACE_INVALID_HANDLE, - ACE_Reactor_Mask mask = ACE_Event_Handler::ALL_EVENTS_MASK); - -protected: - - /* 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. */ - int svc (void); - - /* 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 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 <handle> would - be important to us for reading the client's data. */ - int handle_input (ACE_HANDLE handle); - - /* 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. */ - int process (char *rdbuf, int rdbuf_len); - - /* 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. */ - ~Client_Handler (void); -}; - -#endif /* CLIENT_HANDLER_H */ diff --git a/docs/tutorials/006/combine.shar b/docs/tutorials/006/combine.shar deleted file mode 100644 index cc191f80850..00000000000 --- a/docs/tutorials/006/combine.shar +++ /dev/null @@ -1,508 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/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 -# 1971 -rw-rw-r-- page01.pre -# 252 -rw-rw-r-- page02.pre -# 507 -rw-rw-r-- page03.pre -# 227 -rw-rw-r-- page04.pre -# 225 -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 -# 1418 -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 _sh32413; 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 03191459100 '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. This implementation will create a new thread for each client -which connects to us. The ACE_Reactor is still used but only for -accepting new connections. The Client_Handler objects won't be registered -with the reactor. 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 03191459100 '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' -e9c9068f1265c1668c44f382786e1422 page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 1971 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '1971,' '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> 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 03191459100 '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. The primary reason is to allow us to select -the previous single-threaded implementation or our new thread-per-connection -implementation. Client_Acceptor itself doesn't use this information -but makes it available to the Client_Handler objects it creates. -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 03191459100 '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. 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 03191459100 '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. 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 03191459100 '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' -fe144564cd75e806b825ce878a09bfe3 page05.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`" - test 225 -eq "$shar_count" || - $echo 'page05.pre:' 'original size' '225,' '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. 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. 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 03191459100 '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 03191459100 '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. -Let's move on to the Client_Handler and see if it has changed any. -X -<P> -SHAR_EOF - $shar_touch -am 03191459100 '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(). -Let's move on to the object definition and see what all the fuss is about. -X -<P> -SHAR_EOF - $shar_touch -am 03191459100 '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%"> -<P> -X Did you notice the <i>THR_DETACHED</i> flag on the call to -X <i>activate()</i>? Threads, like any system resource, are a -X limited resource. Unless we intend to <i>join()</i> or -X <i>wait()</i> for the new thread later, we want use THR_DETACHED -X so that we don't cause a leak. In fact, in most cases, you'll -X want to specify THR_DETACHED because it's just easier. -<p> -X Another handy flag for use with <i>activate()</i> is -X <i>THR_NEW_LWP</i>. That's short for <i>Light Weight -X Process</i>. If you've got a multiprocessor, this flag will -X allocate a new schedulable process and decrease the odds of your -X threads all fighting for the same process. Of course, if you -X have a uni-processor, it will neither help nor hurt. Since I -X developed these on a uni-processor, I've been a bit inconsistent -X in the use of <i>THR_NEW_LWP</i>. -X -<P>Well, that's it! After all the talk & the hype, you would -have expected it to be more difficult to create a multi-threaded server. -Surprise! It really is that easy. You still have to handle -contention issues which we haven't addressed here and that is a rather -nasty topic. Still, for the simple case, this is all you have to -do. -X -<P>The next page is the last for this tutorial. Head on over there -& we'll round up the file list one last time. -X -<P> -SHAR_EOF - $shar_touch -am 03191459100 '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' -0589bdf4e09c3c1671f64fd98e8e7747 page05.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pst'`" - test 1418 -eq "$shar_count" || - $echo 'page05.pst:' 'original size' '1418,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh32413 -exit 0 diff --git a/docs/tutorials/006/page01.html b/docs/tutorials/006/page01.html deleted file mode 100644 index 8ea01994aab..00000000000 --- a/docs/tutorials/006/page01.html +++ /dev/null @@ -1,63 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 006</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a thread-per-connection server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>In this tutorial, we're going to extend Tutorial 5 to create a thread-per-connection -server. This implementation will create a new thread for each client -which connects to us. The ACE_Reactor is still used but only for -accepting new connections. The Client_Handler objects won't be registered -with the reactor. 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> -<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 deleted file mode 100644 index f6439297fe1..00000000000 --- a/docs/tutorials/006/page02.html +++ /dev/null @@ -1,149 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 006</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a thread-per-connection server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -<P>Again, we begin with <A HREF="server.cpp">server.cpp.</A> 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> -<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[]) -{ - ACE_UNUSED_ARG(argc); - ACE_UNUSED_ARG(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 <i>restart</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 <Client_Handler, ACE_SOCK_ACCEPTOR>; -template class ACE_Svc_Handler<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 <Client_Handler, ACE_SOCK_ACCEPTOR> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Svc_Handler<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> -<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 deleted file mode 100644 index 24a82ef36e4..00000000000 --- a/docs/tutorials/006/page03.html +++ /dev/null @@ -1,113 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 006</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a thread-per-connection server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -<P>In <A HREF="client_acceptor.h">client_acceptor.h</A>, we've extended -our object just a bit. The primary reason is to allow us to select -the previous single-threaded implementation or our new thread-per-connection -implementation. Client_Acceptor itself doesn't use this information -but makes it available to the Client_Handler objects it creates. -If we wanted a single-strategy implementation, we would have made no changes -to the Tutorial 5 version of this file. - -<P> -<HR WIDTH="100%"> -<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<> template lives in the ace/Acceptor.h header - file. You'll find a very consistent 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> "<A HREF="../../../ace/Acceptor.h">ace/Acceptor.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<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> "<A HREF="../../../ace/SOCK_Acceptor.h">ace/SOCK_Acceptor.h</A>" - -<font color=red>/* The Client_Handler object we develop will be used to handle clients - once they're connected. The ACE_Acceptor<> 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<> 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<> was available. You'll - get spoiled using the ACE templates because they take away a lot of - the tedious details! */</font> -typedef ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> Client_Acceptor_Base; - -<font color=red>/* Here, we use the parameterized ACE_Acceptor<> 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. -Let's move on to the Client_Handler and see if it has changed any. - -<P> -<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 deleted file mode 100644 index 9e707e03467..00000000000 --- a/docs/tutorials/006/page04.html +++ /dev/null @@ -1,154 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 006</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a thread-per-connection server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -<P><A HREF="client_handler.h">client_handler.h</A> -shows a few more changes than the previous sources. The important -change is the addition of a svc() method where our connection thread will -exist. - -<P> -<HR WIDTH="100%"> -<PRE> -<font color=red>// $Id$</font> - -<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 derive our Client_Handler directly from - ACE_Event_Handler but you still have to have an ACE_SOCK_Stream for - the actually connection. With a direct derivative of - ACE_Event_Handler, you'll have to contain and maintain an - 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> - -<font color=blue>#include</font> "<A HREF="../../../ace/Svc_Handler.h">ace/Svc_Handler.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" - -<font color=red>/* Another feature of ACE_Svc_Handler is it's ability to present the - ACE_Task<> 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 things ACE_NULL_SYNCH exists for but - stick around for Tutorial 7 and pay special attention to the - Thread_Pool object there for an explanation. */</font> -class Client_Handler : public ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> -{ -public: - typedef ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> inherited; - - <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 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 - definition of open() you'll see how we get around that. */</font> - int open (void *acceptor); - - <font color=red>/* When an ACE_Task<> 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 clean itself - up. Since an event handler can be registered for more than one - type of callback, the callback mask is provided to inform - handle_close() exactly which method failed. That way, you don't - have to maintain state information between your handle_* method - calls. The <handle> parameter is explained below... 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! */</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 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 <handle> 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); -}; - -<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(). -Let's move on to the object definition and see what all the fuss is about. - -<P> -<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 deleted file mode 100644 index 6dd179e3b15..00000000000 --- a/docs/tutorials/006/page05.html +++ /dev/null @@ -1,351 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 006</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a thread-per-connection server</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -<P><A HREF="client_handler.cpp">client_handler.cpp</A> exposes all the -things I've been hinting at. 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> - -<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. - - We know that including client_handler.h is redundant because - client_acceptor.h includes it. Still, the sentry prevents - double-inclusion from causing problems and it's sometimes good to - be explicit about what we're using. - - On the other hand, we don't directly include any ACE header files - here. */</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... */</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. */</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. */</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, - <font color=#008888>ACE_Event_Handler::READ_MASK</font> - | <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... */</font> -int -<font color=#008888>Client_Handler::open</font> (void *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 - 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 ACE_*_cast macros 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 *) void_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 svc() method will then begin - executing in that thread. - - If we are told to use the single-threaded strategy, there is no - difference between this and the Tutorial 5 implementation. - - Note that if we're in thread-per-connection mode, open() is exited - at this point. Furthermore, thread-per-connection mode does not - use the reactor which means that handle_input() and it's fellows - are not invoked. */</font> - if (acceptor->thread_per_connection ()) - return this->activate (THR_DETACHED); - - <font color=red>// ************************************************************************</font> - <font color=red>// From here on, we're doing the traditional reactor thing. If</font> - <font color=red>// you're operating in thread-per-connection mode, this code does</font> - <font color=red>// not apply.</font> - <font color=red>// ************************************************************************</font> - - <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 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 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 correct thing to do. */</font> - if (this->reactor ()->register_handler (this, - <font color=#008888>ACE_Event_Handler::READ_MASK</font>) == -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. */</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. */</font> -int -<font color=#008888>Client_Handler::close</font>(u_long flags) -{ - ACE_UNUSED_ARG (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. - - Again, this is not used if we're in thread-per-connection mode. */</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[BUFSIZ]; - - <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. */</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); - - this->destroy (); - return 0; -} - -<font color=red>/* The ACE_Svc_Handler<> is ultimately derived from ACE_Task<>. 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. - - Of course, this is only valid if we're in thread-per-connection - mode. If we're using the reactor model, then svc() never comes - into play. */</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[BUFSIZ]; - - <font color=red>// Forever...</font> - while( 1 ) - { - <font color=red>/* Invoke the process() 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 concurrency strategy. Since process() - has all of our application-level logic, it's nice that it - doesn't have to change when we decide to go multi-threaded. - - 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; - } - - 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. */</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 something wrong has happened. The reactor - wouldn't have called us if there wasn't some kind of read activity - but there wouldn't be activity if there were no bytes to read... - - On the other hand, if we got some data then we can display it in a - debug message for everyone to see. */</font> - ssize_t bytes_read; - switch ( (bytes_read = this->peer ().recv (rdbuf, rdbuf_len)) ) - { - case -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, - "<font color=green>(%P|%t) closing daemon (fd = %d)\n</font>", - this->get_handle ()), - -1); - default: - rdbuf[bytes_read] = 0; - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) from client: %s</font>", - rdbuf)); - } - - return 0; -} -</PRE> -<HR WIDTH="100%"> -<P> - Did you notice the <i>THR_DETACHED</i> flag on the call to - <i>activate()</i>? Threads, like any system resource, are a - limited resource. Unless we intend to <i>join()</i> or - <i>wait()</i> for the new thread later, we want use THR_DETACHED - so that we don't cause a leak. In fact, in most cases, you'll - want to specify THR_DETACHED because it's just easier. -<p> - Another handy flag for use with <i>activate()</i> is - <i>THR_NEW_LWP</i>. That's short for <i>Light Weight - Process</i>. If you've got a multiprocessor, this flag will - allocate a new schedulable process and decrease the odds of your - threads all fighting for the same process. Of course, if you - have a uni-processor, it will neither help nor hurt. Since I - developed these on a uni-processor, I've been a bit inconsistent - in the use of <i>THR_NEW_LWP</i>. - -<P>Well, that's it! After all the talk & the hype, you would -have expected it to be more difficult to create a multi-threaded server. -Surprise! It really is that easy. You still have to handle -contention issues which we haven't addressed here and that is a rather -nasty topic. Still, for the simple case, this is all you have to -do. - -<P>The next page is the last for this tutorial. Head on over there -& we'll round up the file list one last time. - -<P> -<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 deleted file mode 100644 index 2b647d9b5e5..00000000000 --- a/docs/tutorials/006/page06.html +++ /dev/null @@ -1,47 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 006</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. 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. In -Tutorial 7 we'll extend that again to allow a thread-pool choice in addition -to the current two. - -<P>For reference, here's the file list again: -<UL> -<LI> -<A HREF="Makefile">Makefile</A></LI> - -<LI> -<A HREF="client_acceptor.h">client_acceptor.h</A></LI> - -<LI> -<A HREF="client_handler.cpp">client_handler.cpp</A></LI> - -<LI> -<A HREF="client_handler.h">client_handler.h</A></LI> - -<LI> -<A HREF="server.cpp">server.cpp</A></LI> - -<LI> -<A HREF="fix.Makefile">fix.Makefile</A></LI> -</UL> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/006/server.cpp b/docs/tutorials/006/server.cpp deleted file mode 100644 index 6d0d7010228..00000000000 --- a/docs/tutorials/006/server.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// $Id$ - -/* 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 "real work". */ - -#include "client_acceptor.h" - -/* 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. */ - -static sig_atomic_t finished = 0; -extern "C" void handler (int) -{ - finished = 1; -} - -/* 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. */ - -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -/* 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. */ - -int -main (int argc, char *argv[]) -{ - ACE_UNUSED_ARG(argc); - ACE_UNUSED_ARG(argv); - - /* 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. */ - ACE_Reactor reactor; - - /* 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.) */ - Client_Acceptor peer_acceptor; - - /* 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 "well known" 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. */ - if (peer_acceptor.open (ACE_INET_Addr (PORT), - &reactor) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "open"), - -1); - - /* As with Tutorial 5, we know that we're now registered with our - reactor so we don't have to mess with that step. */ - - /* 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 "real" work. Our simple - flag-setter doesn't justify deriving from ACE_Event_Handler and - providing a callback function though. */ - ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT); - - /* 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. */ - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) starting up server daemon\n")); - - /* This will loop "forever" 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 <i>restart</i> flag on - the open() method of ACE_Reactor if you're interested.) */ - while (!finished) - reactor.handle_events (); - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) shutting down server daemon\n")); - - return 0; -} - -#if !defined(ACE_HAS_GNU_REPO) -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR>; -template class ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>; -#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> -#pragma instantiate ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> -#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ -#endif /* ACE_HAS_GNU_REPO */ diff --git a/docs/tutorials/007/007.dsp b/docs/tutorials/007/007.dsp deleted file mode 100644 index d069843ec50..00000000000 --- a/docs/tutorials/007/007.dsp +++ /dev/null @@ -1,124 +0,0 @@ -# Microsoft Developer Studio Project File - Name="007" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=007 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "007.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "007.mak" CFG="007 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "007 - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "007 - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "007 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "007 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"server.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "007 - Win32 Release"
-# Name "007 - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\client_acceptor.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\client_handler.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\server.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\thread_pool.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\client_acceptor.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\client_handler.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\thread_pool.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/007/Makefile b/docs/tutorials/007/Makefile deleted file mode 100644 index 7ed33571341..00000000000 --- a/docs/tutorials/007/Makefile +++ /dev/null @@ -1,116 +0,0 @@ -#---------------------------------------------------------------------------- -# $Id$ -#---------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -# You can generally find a Makefile in the ACE examples, tests or the library -# itself that will satisfy our application needs. This one was taken from -# one of the examples. - - # Define the name of the binary we want to create. There has to be - # a CPP file $(BIN).cpp but it doesn't necessarily have to have your - # main() in it. Most of the time, though, it will. -BIN = server - - # Few applications will have a single source file. We use the FILES - # macro to build up a list of additional files to compile. Notice - # that we leave off the extension just as with BIN -FILES = -FILES += client_handler -FILES += client_acceptor -FILES += thread_pool - - # The BUILD macro is used by the ACE makefiles. Basically, it tells - # the system what to build. I don't really know what VBIN is other - # than it is constructed from the value of BIN. Just go with it... -BUILD = $(VBIN) - - # Here we use some GNU make extensions to build the SRC macro. Basically, - # we're just adding .cpp to the value of BIN and for each entry of the - # FILES macro. -SRC = $(addsuffix .cpp,$(BIN)) $(addsuffix .cpp,$(FILES)) - - # This is used by my Indent target below. It's not a part of standard - # ACE and you don't need it yourself. -HDR = *.h - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - - # This is where the real power lies! These included makefile components - # are similar to the C++ templates in ACE. That is, they do a tremendous - # amount of work for you and all you have to do is include them. - # As a matter of fact, in our project, I created a single file named - # "app.mk" that includes all of these. Our project makefiles then just - # need to include app.mk to get everything they need. - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - - # Sometimes I like to reformat my code to make it more readable. This is - # more useful for the comments than anything else. Unfortunately, the - # "indent" program doesn't quite grok C++ so I have to post-process it's - # output just a bit. -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - - # One of the targets in the ACE makefiles is "depend". It will invoke - # your compiler in a way that will generate a list of dependencies for - # you. This is a great thing! Unfortunately, it puts all of that mess - # directly into the Makefile. I prefer my Makefile to stay clean and - # 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. -Depend : depend - perl ../fix.Makefile - -.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) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - - # Don't put anything below here. Between the "depend" target and fix.Makefile - # it's guaranteed to be lost! - - # This is inserted by the fix.Makefile script -include .depend diff --git a/docs/tutorials/007/client_acceptor.cpp b/docs/tutorials/007/client_acceptor.cpp deleted file mode 100644 index 9e7e6f7348f..00000000000 --- a/docs/tutorials/007/client_acceptor.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// $Id$ - -#include "client_acceptor.h" - -/* Construct ourselves with the chosen concurrency strategy. Notice - that we also set our Thread_Pool reference to our private instance. */ -Client_Acceptor::Client_Acceptor (int concurrency) - : concurrency_ (concurrency), - the_thread_pool_ (private_thread_pool_) -{ -} - -/* Construct ourselves with a reference to somebody else' Thread_Pool. - Obvioulsy our concurrency strategy is "thread_pool_" at this point. */ -Client_Acceptor::Client_Acceptor (Thread_Pool &thread_pool) - : concurrency_ (thread_pool_), - the_thread_pool_ (thread_pool) -{ -} - -/* When we're destructed, we may need to cleanup after ourselves. If - we're running with a thread pool that we own, it is up to us to - close it down. */ -Client_Acceptor::~Client_Acceptor (void) -{ - if (this->concurrency() == thread_pool_ && thread_pool_is_private ()) - thread_pool ()->close (); -} - -/* Similar to the destructor (and close() below) it is necessary for - us to open the thread pool in some circumstances. - - Notice how we delegate most of the open() work to the open() method - of our baseclass. */ -int -Client_Acceptor::open (const ACE_INET_Addr &addr, - ACE_Reactor *reactor, - int pool_size) -{ - if (this->concurrency() == thread_pool_ && thread_pool_is_private ()) - thread_pool ()->start (pool_size); - - return inherited::open (addr, reactor); -} - -/* Here again we find that we have to manage the thread pool. Like - open() we also delegate the other work to our baseclass. */ -int -Client_Acceptor::close (void) -{ - if (this->concurrency() == thread_pool_ && thread_pool_is_private ()) - thread_pool ()->stop (); - - return inherited::close (); -} - diff --git a/docs/tutorials/007/client_acceptor.h b/docs/tutorials/007/client_acceptor.h deleted file mode 100644 index fb591f548fb..00000000000 --- a/docs/tutorials/007/client_acceptor.h +++ /dev/null @@ -1,125 +0,0 @@ -// $Id$ - -#ifndef CLIENT_ACCEPTOR_H -#define CLIENT_ACCEPTOR_H - -/* 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. */ - -#include "ace/Acceptor.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -/* Since we want to work with sockets, we'll need a SOCK_Acceptor to - allow the clients to connect to us. */ -#include "ace/SOCK_Acceptor.h" - -/* The Client_Handler object we develop will be used to handle clients - once they're connected. The ACE_Acceptor<> 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. */ -#include "client_handler.h" - -/* Parameterize the ACE_Acceptor<> 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<> was available. You'll - get spoiled using the ACE templates because they take away a lot of - the tedious details! */ -typedef ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> Client_Acceptor_Base; - -#include "thread_pool.h" - -/* This time we've added quite a bit more to our acceptor. In - addition to providing a choice of concurrency strategies, we also - maintain a Thread_Pool object in case that strategy is chosen. The - object still isn't very complex but it's come a long way from the - simple typedef we had in Tutorial 5. - - Why keep the thread pool as a member? If we go back to the inetd - concept you'll recall that we need several acceptors to make that - work. We may have a situation in which our different client types - requre different resources. That is, we may need a large thread - pool for some client types and a smaller one for others. We could - share a pool but then the client types may have undesirable impact - on one another. - - Just in case you do want to share a single thread pool, there is a - constructor below that will let you do that. */ -class Client_Acceptor : public Client_Acceptor_Base -{ -public: - typedef Client_Acceptor_Base inherited; - - /* Now that we have more than two strategies, we need more than a - boolean to tell us what we're using. A set of enums is a good - choice because it allows us to use named values. Another option - would be a set of static const integers. */ - enum concurrency_t - { - single_threaded_, - thread_per_connection_, - thread_pool_ - }; - - /* The default constructor allows the programmer to choose the - concurrency strategy. Since we want to focus on thread-pool, - that's what we'll use if nothing is specified. */ - Client_Acceptor (int concurrency = thread_pool_); - - /* Another option is to construct the object with an existing thread - pool. The concurrency strategy is pretty obvious at that point. */ - Client_Acceptor (Thread_Pool &thread_pool); - - /* Our destructor will take care of shutting down the thread-pool if - applicable. */ - ~Client_Acceptor (void); - - /* Open ourselves and register with the given reactor. The thread - pool size can be specified here if you want to use that - concurrency strategy. */ - int open (const ACE_INET_Addr &addr, - ACE_Reactor *reactor, - int pool_size = Thread_Pool::default_pool_size_); - - /* Close ourselves and our thread pool if applicable */ - int close (void); - - /* What is our concurrency strategy? */ - int concurrency (void) - { - return this->concurrency_; - } - - /* Give back a pointer to our thread pool. Our Client_Handler - objects will need this so that their handle_input() methods can - put themselves into the pool. Another alternative would be a - globally accessible thread pool. ACE_Singleton<> is a way to - achieve that. */ - Thread_Pool *thread_pool (void) - { - return &this->the_thread_pool_; - } - - /* Since we can be constructed with a Thread_Pool reference, there - are times when we need to know if the thread pool we're using is - ours or if we're just borrowing it from somebody else. */ - int thread_pool_is_private (void) - { - return &the_thread_pool_ == &private_thread_pool_; - } - -protected: - int concurrency_; - - Thread_Pool private_thread_pool_; - - Thread_Pool &the_thread_pool_; -}; - -#endif /* CLIENT_ACCEPTOR_H */ diff --git a/docs/tutorials/007/client_handler.cpp b/docs/tutorials/007/client_handler.cpp deleted file mode 100644 index 6399c1636d1..00000000000 --- a/docs/tutorials/007/client_handler.cpp +++ /dev/null @@ -1,233 +0,0 @@ -// $Id$ - -/* Since this is the third time we've seen most of this, I'm going to - strip out almost all of the comments that you've already seen. - That way, you can concentrate on the new items. */ - -#include "client_acceptor.h" -#include "client_handler.h" - -/* We're going to be registering and unregistering a couple of times. - To make sure that we use the same flags every time, I've created - these handy macros. */ -#define REGISTER_MASK ACE_Event_Handler::READ_MASK -#define REMOVE_MASK (ACE_Event_Handler::READ_MASK | ACE_Event_Handler::DONT_CALL) - -/* Our constructor still doesn't really do anything. We simply - initialize the acceptor pointer to "null" and get our current - thread id. The static self() method of ACE_Thread will return you - a thread id native to your platform. */ -Client_Handler::Client_Handler (void) - : client_acceptor_(0), - creator_ (ACE_Thread::self ()) -{ -} - -Client_Handler::~Client_Handler (void) -{ - this->peer().close(); -} - -/* Query our acceptor for the concurrency strategy. Notice that we - don't bother to check that our acceptor pointer is valid. That is - proably a bad idea... */ -int -Client_Handler::concurrency(void) -{ - return this->client_acceptor ()->concurrency (); -} - -/* And here we ask the acceptor about the thread pool. */ -Thread_Pool * -Client_Handler::thread_pool (void) -{ - return this->client_acceptor ()->thread_pool (); -} - -/* Back to our open() method. This is straight out of Tutorial 6. - There's nothing additional here for the thread-pool implementation. */ -int -Client_Handler::open (void *acceptor) -{ - client_acceptor ((Client_Acceptor *) acceptor); - - if (concurrency () == Client_Acceptor::thread_per_connection_) - return this->activate (THR_DETACHED); - - this->reactor (client_acceptor()->reactor ()); - - ACE_INET_Addr addr; - - if (this->peer ().get_remote_addr (addr) == -1) - return -1; - - if (this->reactor ()->register_handler (this, - REGISTER_MASK) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) can't register with reactor\n"), - -1); - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) connected with %s\n", - addr.get_host_name ())); - return 0; -} - -/* The destroy() method will remove us from the reactor (with the - DONT_CALL flag set!) and then free our memory. This allows us to - be closed from outside of the reactor context without any danger. */ -void -Client_Handler::destroy (void) -{ - this->reactor ()->remove_handler (this, REMOVE_MASK); - delete this; -} - -/* As mentioned in the header, the typical way to close an object in a - threaded context is to invoke it's close() method. */ -int -Client_Handler::close (u_long flags) -{ - ACE_UNUSED_ARG(flags); - - /* - 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. - */ - this->destroy (); - - /* 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! */ - return 0; -} - -/* We will be called when handle_input() returns -1. That's our queue - to delete ourselves to prevent memory leaks. */ -int -Client_Handler::handle_close (ACE_HANDLE handle, - ACE_Reactor_Mask mask) -{ - ACE_UNUSED_ARG (handle); - ACE_UNUSED_ARG (mask); - - delete this; - - return 0; -} - -/* 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. - - You've read that much before... Now we have to do some extra stuff - in case we're using the thread-pool implementation. If we're - called by our creator thread then we must be in the reactor. In - that case, we arrange to be put into the thread pool. If we're not - in the creator thread then we must be in the thread pool and we can - do some work. */ -int -Client_Handler::handle_input (ACE_HANDLE handle) -{ - ACE_UNUSED_ARG (handle); - - /* Check our strategy. If we're using the thread pool and we're in - the creation thread then we know we were called by the reactor. */ - if (concurrency () == Client_Acceptor::thread_pool_) - { - if (ACE_OS::thr_equal (ACE_Thread::self(), - creator_)) - { - /* 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); - } - } - - /* Any strategy other than thread-per-connection will eventually get - here. If we're in the single-threaded implementation or the - thread-pool, we still have to pass this way. */ - - char buf[BUFSIZ]; - - /* Invoke the process() method to do the work but save it's return - value instead of returning it immediately. */ - - int rval = this->process (buf, sizeof (buf)); - - /* Now, we look again to see if we're in the thread-pool - implementation. If so then we need to re-register ourselves with - the reactor so that we can get more work when it is available. - (If suspend_handler() worked then we would use resume_handler() - here.) */ - if (concurrency () == Client_Acceptor::thread_pool_) - { - 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); - } - - /* Return the result of process() */ - return rval; -} - -/* Remember that when we leave our svc() method, the framework will - take care of calling our close() method so that we can cleanup - after ourselves. */ -int -Client_Handler::svc (void) -{ - char buf[BUFSIZ]; - - while (1) - if (this->process (buf, sizeof (buf)) == -1) - return -1; - - return 0; -} - -/* Once again, we see that the application-level logic has not been at - all affected by our choice of threading models. Of course, I'm not - sharing data between threads or anything. We'll leave locking - issues for a later tutorial. */ -int -Client_Handler::process (char *rdbuf, - int rdbuf_len) -{ - ssize_t bytes_read; - switch ( (bytes_read = this->peer ().recv (rdbuf, rdbuf_len)) ) - { - case -1: - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) %p bad read\n", - "client"), - -1); - case 0: - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) closing daemon (fd = %d)\n", - this->get_handle ()), - -1); - default: - rdbuf[bytes_read] = 0; - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) from client: %s", - rdbuf)); - } - - return 0; -} diff --git a/docs/tutorials/007/client_handler.h b/docs/tutorials/007/client_handler.h deleted file mode 100644 index 9bb4af24358..00000000000 --- a/docs/tutorials/007/client_handler.h +++ /dev/null @@ -1,156 +0,0 @@ -// $Id$ - -#ifndef CLIENT_HANDLER_H -#define CLIENT_HANDLER_H - -/* 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 derive our Client_Handler directly from - ACE_Event_Handler but you still have to have an ACE_SOCK_Stream for - the actually connection. With a direct derivative of - ACE_Event_Handler, you'll have to contain and maintain an - 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. */ - -#include "ace/Svc_Handler.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "ace/SOCK_Stream.h" - -class Client_Acceptor; -class Thread_Pool; - -/* Another feature of ACE_Svc_Handler is it's ability to present the - ACE_Task<> interface as well. That's what the ACE_NULL_SYNCH - parameter below is all about. That's beyond our scope here but - we'll come back to it in the next tutorial when we start looking at - concurrency options. */ -class Client_Handler : public ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> -{ -public: - typedef ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> inherited; - - // Constructor... - Client_Handler (void); - - /* 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. */ - void destroy (void); - - /* 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 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 - definition of open() you'll see how we get around that. */ - int open (void *acceptor); - - /* When an ACE_Task<> 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. */ - int close (u_long flags = 0); - - /* 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 clean itself - up. Since an event handler can be registered for more than one - type of callback, the callback mask is provided to inform - handle_close() exactly which method failed. That way, you don't - have to maintain state information between your handle_* method - calls. The <handle> parameter is explained below... 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); - - /* 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 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 <handle> would - be important to us for reading the client's data. */ - int handle_input (ACE_HANDLE handle); - -protected: - - /* 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. */ - int svc (void); - - /* 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 function. You can think of process() as - application-level code and everything elase as - application-framework code. */ - int process (char *rdbuf, int rdbuf_len); - - /* 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. */ - ~Client_Handler (void); - - /* When we get to the definition of Client_Handler we'll see that - there are several places where we go back to the Client_Acceptor - for information. It is generally a good idea to do that through - an accesor rather than using the member variable directly. */ - Client_Acceptor *client_acceptor (void) - { - return this->client_acceptor_; - } - - /* And since you shouldn't access a member variable directly, - neither should you set (mutate) it. Although it might seem silly - to do it this way, you'll thank yourself for it later. */ - void client_acceptor (Client_Acceptor *_client_acceptor) - { - this->client_acceptor_ = _client_acceptor; - } - - /* The concurrency() accessor tells us the current concurrency - strategy. It actually queries the Client_Acceptor for it but by - having the accessor in place, we could change our implementation - without affecting everything that needs to know. */ - int concurrency (void); - - /* Likewise for access to the Thread_Pool that we belong to. */ - Thread_Pool * thread_pool (void); - - Client_Acceptor *client_acceptor_; - - /* For some reason I didn't create accessor/mutator methods for - this. So much for consistency.... - - This variable is used to remember the thread in which we were - created: the "creator" thread in other words. handle_input() - needs to know if it is operating in the main reactor thread (which - is the one that created us) or if it is operating in one of the - thread pool threads. More on this when we get to handle_input(). */ - ACE_thread_t creator_; -}; - -#endif /* CLIENT_HANDLER_H */ diff --git a/docs/tutorials/007/combine.shar b/docs/tutorials/007/combine.shar deleted file mode 100644 index ba4dfe41b2b..00000000000 --- a/docs/tutorials/007/combine.shar +++ /dev/null @@ -1,685 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/007'. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 576 -rw-rw-r-- hdr -# 123 -rw-rw-r-- bodies -# 3383 -rw-rw-r-- page01.pre -# 87 -rw-rw-r-- page02.pre -# 120 -rw-rw-r-- page03.pre -# 171 -rw-rw-r-- page04.pre -# 105 -rw-rw-r-- page05.pre -# 160 -rw-rw-r-- page06.pre -# 340 -rw-rw-r-- page07.pre -# 377 -rw-rw-r-- page08.pre -# 2070 -rw-rw-r-- page09.pre -# 173 -rw-rw-r-- page02.pst -# 116 -rw-rw-r-- page03.pst -# 106 -rw-rw-r-- page04.pst -# 234 -rw-rw-r-- page05.pst -# 177 -rw-rw-r-- page06.pst -# 97 -rw-rw-r-- page07.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 _sh32447; 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 007</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> -X -<CENTER><B><FONT SIZE=+2>ACE Tutorial 007</FONT></B></CENTER> -X -<CENTER><B><FONT SIZE=+2>Creating a thread-pool server</FONT></B></CENTER> -<HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -151b1b4bda96cc1e3ef55356e819ca42 hdr -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`" - test 576 -eq "$shar_count" || - $echo 'hdr:' 'original size' '576,' '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_acceptor.cpp -client_handler.h -client_handler.cpp -thread_pool.h -thread_pool.cpp -X -SHAR_EOF - $shar_touch -am 0121152599 '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' -7675a97fa145886f534c43a8e1a0e6d1 bodies -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`" - test 123 -eq "$shar_count" || - $echo 'bodies:' 'original size' '123,' '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 -X -X -<P>In this tutorial, we're going to extend Tutorial 6 to add a third concurrency -strategy: thread-pool. Like Tutorial 6 did to Tutorial 5, we're -going to keep the existing strategies that we've already created and add -this one in as a "bonus". As you'll see, our basic objects will change -but not by a whole lot. To accomplish this, we'll introduce one new -major object that helps to abstract the thread pool concept. -<P> -Some folks have noted that this tutorial is a bit confusing if you -don't first know about ACE_Task. My advice is to give it all a good -read a couple of times. If you're still having problems, take a look -at the ACE_Task tests in $ACE_ROOT/tests or examples in $ACE_ROOT/examples. -<P> -Kirthika's Abstract: -<UL> -In this multithreaded server, the Client_Acceptor has the additional -strategy of managing a thread pool. This helps when two clients don't -want to share the same resources or when different clients -need to run in different priority threads. We could then pool all the -same priority clients into one thread-pool. The thread_pool class is a -new addition used to implement this strategy. It inherits from ACE_Task -with ACE_MT_SYNCH parameter which takes care of syncronization issues -amongst multiple threads. -<P> -ACE_Task follows the Active Object pattern and executes the methods on -the task object in a new thread of execution, i.e it decouples the -execution of a method from its invocation. An ACE_Task has an underlying -thread (or pool of threads) and a Message_Queue which is the only means -of communication among tasks. A Message_Queue consists of -Message_Blocks. -<P> -The Client_Acceptor is registered with the reactor waiting for -connection requests. -On some activity, the reactor calls the handle_input() method on the -Acceptor. The Client_Handler of the Acceptor (for the thread-pool -strategy) unregisters itself from the reactor and -enqueues itself in the Message_Queue of the thread-pool waiting for -svc() to call handle_input() on it. It would then process the data in -its new thread of execution. The ACE_MT_SYNCH option facilitates access -of the Mesage_Blocks across different Message_Queues (here from the main -thread to the one in the thread pool). -<P> -The thread_pool class derives from the ACE_Task class. Its svc() method -dequeues the threads in the Message_Queue and calls handle_input() on -them. The idle threads can take work from the queue while the other -threads are working. It also uses ACE_Atomic_Op as a counter for active -threads in the pool. Also, the ACE_Guard class has been used to provide -thread-safe counter-incrementation and destruction of the Message_Blocks -of the thread-pool. This class guards the critical section region by -acquiring the mutex lock on creation and releasing it as soon as it goes -out of scope. -<P> -Note: a sleep period before all the threads in the pool exit is -necessary for complete destruction of the thread pool. -<P> -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 03191459100 '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' -0bd3a7ce4fbd16691109b32892c3a864 page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 3383 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '3383,' '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>As usualy, we start with <A HREF="server.cpp">server.cpp</A> -<BR> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -37639524942e8882c94523e5189b22ff page02.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`" - test 87 -eq "$shar_count" || - $echo 'page02.pre:' 'original size' '87,' '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 -<P>Let's see what things we've had to add to <A HREF="client_acceptor.h">client_acceptor.h</A>. -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -64592ded5ea700b4147face8ad77018f page03.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`" - test 120 -eq "$shar_count" || - $echo 'page03.pre:' 'original size' '120,' '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 -<P>Something new this time is <A HREF="client_acceptor.cpp">client_acceptor.cpp</A>. -I finally had enough code to move it out of the header. -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -d5640eb97c0a746761c946c4e93db2e8 page04.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`" - test 171 -eq "$shar_count" || - $echo 'page04.pre:' 'original size' '171,' '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 -<P>As you might expect, <A HREF="client_handler.h">client_handler.h</A> -is next. -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -e882d389de5d95571737cfc58552153a page05.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`" - test 105 -eq "$shar_count" || - $echo 'page05.pre:' 'original size' '105,' '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 -<P><A HREF="client_handler.cpp">client_handler.cpp</A> -shows some of the changes due to the thread-pool. Just a few -though. -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -d884389625246dfcd8049f0fc648997d page06.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page06.pre'`" - test 160 -eq "$shar_count" || - $echo 'page06.pre:' 'original size' '160,' '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' && -<P>Two new files this time. The first is <A HREF="thread_pool.h">thread_pool.h</A> -where we declare our Thread_Pool object. This is responsible for -abstracting away the thread pool implementation details and allowing us -to make so few changes to the rest of the code. -X -<P> -<HR WIDTH="100%"><FONT FACE="Arial,Helvetica"></FONT> -X -SHAR_EOF - $shar_touch -am 03191459100 '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' -e5bcf4bee3e756dda50ccb69c18ac3a1 page07.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page07.pre'`" - test 340 -eq "$shar_count" || - $echo 'page07.pre:' 'original size' '340,' 'current size' "$shar_count!" - fi -fi -# ============= page08.pre ============== -if test -f 'page08.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page08.pre' '(file already exists)' -else - $echo 'x -' extracting 'page08.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page08.pre' && -X -<P>Finally, <A HREF="thread_pool.cpp">thread_pool.cpp</A> -where we have the Thread_Pool object implementation. -<P> -Remember back in <A HREF="../006/page01.html">Tutorial 6</A> when I -X was talking about <i>THR_NEW_LWP</i>? Look closely and you'll -X see it here. It's bitwise OR'd with <i>THR_DETACHED</i> just to -X keep things interesting. -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 'page08.pre' && - chmod 0664 'page08.pre' || - $echo 'restore of' 'page08.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 'page08.pre:' 'MD5 check failed' -09c4d5adcd767080e64649a01bd0957c page08.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page08.pre'`" - test 377 -eq "$shar_count" || - $echo 'page08.pre:' 'original size' '377,' 'current size' "$shar_count!" - fi -fi -# ============= page09.pre ============== -if test -f 'page09.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page09.pre' '(file already exists)' -else - $echo 'x -' extracting 'page09.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page09.pre' && -X -<P>That's it for Tutorial 7. As with Tutorial 6, we really didn't -have to change much to introduce a new threading strategy. Most of -the work was in creating the Thread_Pool object itself. Everything -else was just minor housekeeping. -X -<P>There is a fourth common thread strategy: thread-per-request. -It's not one of my favorites, so I wasn't planning to go into it. -If you want to contribute a tutorial on that topic though, I'll be glad -to include it here. -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_acceptor.cpp">client_acceptor.cpp</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="thread_pool.h">thread_pool.h</A></LI> -X -<LI> -<A HREF="thread_pool.cpp">thread_pool.cpp</A></LI> -X -</UL> -<P> -<HR WIDTH="100%"> -<P> -<center><h2>Danger, Warning!</h2></center> -Now that I've gone through all of this to create a thread pool server, -I have to point out that this isn't exactly the best or safest way to -do so. The biggest danger we face with this approach is the -possibility of an event handler existing in the thread pool's message -queue <i>after</i> it has been deleted. When the thread's svc() -method attempts to invoke <i>handle_input()</i> you will get a nasty -core dump. -<p> -The safest way to handle the situation is to use reference-counted -pointers everywhere a Client_Handler pointer would be used. That's -beyond the scope of the tutorial but I encourage you to give it a -try. If you want to contribute that back as an enhanced Tutorial, -I'll be glad to include it. -<p> -Another approach that should work quite well is to use the -ACE_TP_Reactor instead of just ACE_Reactor. This takes a little more -setup but results in a cleaner implementation. Again, I've not had -time to develop a Tutorial on the TP_Reactor but would welcome any -contributions. -SHAR_EOF - $shar_touch -am 03191459100 'page09.pre' && - chmod 0664 'page09.pre' || - $echo 'restore of' 'page09.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 'page09.pre:' 'MD5 check failed' -8649089f4b28456c033dede0e32276a8 page09.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page09.pre'`" - test 2070 -eq "$shar_count" || - $echo 'page09.pre:' 'original size' '2070,' '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>Hmmm... No change there. Maybe I should leave out comments -on the stuff I don't change. Let's take a look at client_acceptor.h. -X -<P> -SHAR_EOF - $shar_touch -am 03191459100 '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' -b6226123f4f50eeb16db2f7675aaa171 page02.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pst'`" - test 173 -eq "$shar_count" || - $echo 'page02.pst:' 'original size' '173,' '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>Well, except for the new Thread_Pool member variable, most of the changes -are informational. -X -SHAR_EOF - $shar_touch -am 03191459100 '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' -88a4cc7d635a4a6b7645011be580808f page03.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pst'`" - test 116 -eq "$shar_count" || - $echo 'page03.pst:' 'original size' '116,' '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>Nothing really surprising here. Most of it just manages the Thread_Pool. -X -<P> -SHAR_EOF - $shar_touch -am 03191459100 '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' -57acbd600df965b4dc96ef0ad7ea9390 page04.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pst'`" - test 106 -eq "$shar_count" || - $echo 'page04.pst:' 'original size' '106,' '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>Still, we're just not seeing a lot of changes due to introduction of -the thread pool. That's a good thing! You don't want to go turning -your application upside down just because you changed thread models. -X -SHAR_EOF - $shar_touch -am 03191459100 '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' -98cba63a4dffe925484ca86368c863bb page05.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pst'`" - test 234 -eq "$shar_count" || - $echo 'page05.pst:' 'original size' '234,' 'current size' "$shar_count!" - fi -fi -# ============= page06.pst ============== -if test -f 'page06.pst' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page06.pst' '(file already exists)' -else - $echo 'x -' extracting 'page06.pst' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page06.pst' && -<HR WIDTH="100%"> -X -<P>Ok, now we've gone and changed handle_input() so that it knows when -to do work and when to enqueue itself. Beyond that, we're still about -the same. -X -SHAR_EOF - $shar_touch -am 03191459100 'page06.pst' && - chmod 0664 'page06.pst' || - $echo 'restore of' 'page06.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 'page06.pst:' 'MD5 check failed' -bfbc05b1679c397403e7106ef12065d9 page06.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page06.pst'`" - test 177 -eq "$shar_count" || - $echo 'page06.pst:' 'original size' '177,' 'current size' "$shar_count!" - fi -fi -# ============= page07.pst ============== -if test -f 'page07.pst' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page07.pst' '(file already exists)' -else - $echo 'x -' extracting 'page07.pst' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page07.pst' && -<HR WIDTH="100%"> -X -<P>Well, that doesn't look too complex. What about the implementation? -X -SHAR_EOF - $shar_touch -am 03191459100 'page07.pst' && - chmod 0664 'page07.pst' || - $echo 'restore of' 'page07.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 'page07.pst:' 'MD5 check failed' -c1a7fbfe20f12e5a8bdeccc7c8e1af1c page07.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page07.pst'`" - test 97 -eq "$shar_count" || - $echo 'page07.pst:' 'original size' '97,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh32447 -exit 0 diff --git a/docs/tutorials/007/page01.html b/docs/tutorials/007/page01.html deleted file mode 100644 index c8aacc25752..00000000000 --- a/docs/tutorials/007/page01.html +++ /dev/null @@ -1,84 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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 007</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 007</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a thread-pool server</FONT></B></CENTER> -<HR> - - - -<P>In this tutorial, we're going to extend Tutorial 6 to add a third concurrency -strategy: thread-pool. Like Tutorial 6 did to Tutorial 5, we're -going to keep the existing strategies that we've already created and add -this one in as a "bonus". As you'll see, our basic objects will change -but not by a whole lot. To accomplish this, we'll introduce one new -major object that helps to abstract the thread pool concept. -<P> -Some folks have noted that this tutorial is a bit confusing if you -don't first know about ACE_Task. My advice is to give it all a good -read a couple of times. If you're still having problems, take a look -at the ACE_Task tests in $ACE_ROOT/tests or examples in $ACE_ROOT/examples. -<P> -Kirthika's Abstract: -<UL> -In this multithreaded server, the Client_Acceptor has the additional -strategy of managing a thread pool. This helps when two clients don't -want to share the same resources or when different clients -need to run in different priority threads. We could then pool all the -same priority clients into one thread-pool. The thread_pool class is a -new addition used to implement this strategy. It inherits from ACE_Task -with ACE_MT_SYNCH parameter which takes care of syncronization issues -amongst multiple threads. -<P> -ACE_Task follows the Active Object pattern and executes the methods on -the task object in a new thread of execution, i.e it decouples the -execution of a method from its invocation. An ACE_Task has an underlying -thread (or pool of threads) and a Message_Queue which is the only means -of communication among tasks. A Message_Queue consists of -Message_Blocks. -<P> -The Client_Acceptor is registered with the reactor waiting for -connection requests. -On some activity, the reactor calls the handle_input() method on the -Acceptor. The Client_Handler of the Acceptor (for the thread-pool -strategy) unregisters itself from the reactor and -enqueues itself in the Message_Queue of the thread-pool waiting for -svc() to call handle_input() on it. It would then process the data in -its new thread of execution. The ACE_MT_SYNCH option facilitates access -of the Mesage_Blocks across different Message_Queues (here from the main -thread to the one in the thread pool). -<P> -The thread_pool class derives from the ACE_Task class. Its svc() method -dequeues the threads in the Message_Queue and calls handle_input() on -them. The idle threads can take work from the queue while the other -threads are working. It also uses ACE_Atomic_Op as a counter for active -threads in the pool. Also, the ACE_Guard class has been used to provide -thread-safe counter-incrementation and destruction of the Message_Blocks -of the thread-pool. This class guards the critical section region by -acquiring the mutex lock on creation and releasing it as soon as it goes -out of scope. -<P> -Note: a sleep period before all the threads in the pool exit is -necessary for complete destruction of the thread pool. -<P> -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> -<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/page02.html b/docs/tutorials/007/page02.html deleted file mode 100644 index e9dc3693cce..00000000000 --- a/docs/tutorials/007/page02.html +++ /dev/null @@ -1,142 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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 007</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 007</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a thread-pool server</FONT></B></CENTER> -<HR> -<P>As usualy, we start with <A HREF="server.cpp">server.cpp</A> -<BR> -<HR WIDTH="100%"> -<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[]) -{ - ACE_UNUSED_ARG(argc); - ACE_UNUSED_ARG(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>/* 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 <i>restart</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_EXPLICIT_TEMPLATE_INSTANTIATION</font>) -template class ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR>; -template class ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>; -template class ACE_Guard<ACE_Mutex>; -template class ACE_Atomic_Op<ACE_Mutex, int>; -<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 <Client_Handler, ACE_SOCK_ACCEPTOR> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Guard<ACE_Mutex> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Atomic_Op<ACE_Mutex, int> -<font color=blue>#endif</font> <font color=red>/* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */</font> -</PRE> -<HR WIDTH="100%"> - -<P>Hmmm... No change there. Maybe I should leave out comments -on the stuff I don't change. Let's take a look at client_acceptor.h. - -<P> -<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/007/page03.html b/docs/tutorials/007/page03.html deleted file mode 100644 index 25ddbad3bd1..00000000000 --- a/docs/tutorials/007/page03.html +++ /dev/null @@ -1,155 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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 007</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 007</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a thread-pool server</FONT></B></CENTER> -<HR> - -<P>Let's see what things we've had to add to <A HREF="client_acceptor.h">client_acceptor.h</A>. - -<P> -<HR WIDTH="100%"> -<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<> 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> "<A HREF="../../../ace/Acceptor.h">ace/Acceptor.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<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> "<A HREF="../../../ace/SOCK_Acceptor.h">ace/SOCK_Acceptor.h</A>" - -<font color=red>/* The Client_Handler object we develop will be used to handle clients - once they're connected. The ACE_Acceptor<> 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<> 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<> was available. You'll - get spoiled using the ACE templates because they take away a lot of - the tedious details! */</font> -typedef ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> Client_Acceptor_Base; - -<font color=blue>#include</font> "<font color=green>thread_pool.h</font>" - -<font color=red>/* This time we've added quite a bit more to our acceptor. In - addition to providing a choice of concurrency strategies, we also - maintain a Thread_Pool object in case that strategy is chosen. The - object still isn't very complex but it's come a long way from the - simple typedef we had in Tutorial 5. - - Why keep the thread pool as a member? If we go back to the inetd - concept you'll recall that we need several acceptors to make that - work. We may have a situation in which our different client types - requre different resources. That is, we may need a large thread - pool for some client types and a smaller one for others. We could - share a pool but then the client types may have undesirable impact - on one another. - - Just in case you do want to share a single thread pool, there is a - constructor below that will let you do that. */</font> -class Client_Acceptor : public Client_Acceptor_Base -{ -public: - typedef Client_Acceptor_Base inherited; - - <font color=red>/* Now that we have more than two strategies, we need more than a - boolean to tell us what we're using. A set of enums is a good - choice because it allows us to use named values. Another option - would be a set of static const integers. */</font> - enum concurrency_t - { - single_threaded_, - thread_per_connection_, - thread_pool_ - }; - - <font color=red>/* The default constructor allows the programmer to choose the - concurrency strategy. Since we want to focus on thread-pool, - that's what we'll use if nothing is specified. */</font> - Client_Acceptor (int concurrency = thread_pool_); - - <font color=red>/* Another option is to construct the object with an existing thread - pool. The concurrency strategy is pretty obvious at that point. */</font> - Client_Acceptor (Thread_Pool &thread_pool); - - <font color=red>/* Our destructor will take care of shutting down the thread-pool if - applicable. */</font> - ~Client_Acceptor (void); - - <font color=red>/* Open ourselves and register with the given reactor. The thread - pool size can be specified here if you want to use that - concurrency strategy. */</font> - int open (const ACE_INET_Addr &addr, - ACE_Reactor *reactor, - int pool_size = <font color=#008888>Thread_Pool::default_pool_size_</font>); - - <font color=red>/* Close ourselves and our thread pool if applicable */</font> - int close (void); - - <font color=red>/* What is our concurrency strategy? */</font> - int concurrency (void) - { - return this->concurrency_; - } - - <font color=red>/* Give back a pointer to our thread pool. Our Client_Handler - objects will need this so that their handle_input() methods can - put themselves into the pool. Another alternative would be a - globally accessible thread pool. ACE_Singleton<> is a way to - achieve that. */</font> - Thread_Pool *thread_pool (void) - { - return &this->the_thread_pool_; - } - - <font color=red>/* Since we can be constructed with a Thread_Pool reference, there - are times when we need to know if the thread pool we're using is - ours or if we're just borrowing it from somebody else. */</font> - int thread_pool_is_private (void) - { - return &the_thread_pool_ == &private_thread_pool_; - } - -protected: - int concurrency_; - - Thread_Pool private_thread_pool_; - - Thread_Pool &the_thread_pool_; -}; - -<font color=blue>#endif</font> <font color=red>/* CLIENT_ACCEPTOR_H */</font> -</PRE> -<HR WIDTH="100%"> - -<P>Well, except for the new Thread_Pool member variable, most of the changes -are informational. - -<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/007/page04.html b/docs/tutorials/007/page04.html deleted file mode 100644 index 9e190725942..00000000000 --- a/docs/tutorials/007/page04.html +++ /dev/null @@ -1,87 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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 007</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 007</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a thread-pool server</FONT></B></CENTER> -<HR> - -<P>Something new this time is <A HREF="client_acceptor.cpp">client_acceptor.cpp</A>. -I finally had enough code to move it out of the header. - -<P> -<HR WIDTH="100%"> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>client_acceptor.h</font>" - -<font color=red>/* Construct ourselves with the chosen concurrency strategy. Notice - that we also set our Thread_Pool reference to our private instance. */</font> -<font color=#008888>Client_Acceptor::Client_Acceptor</font> (int concurrency) - : concurrency_ (concurrency), - the_thread_pool_ (private_thread_pool_) -{ -} - -<font color=red>/* Construct ourselves with a reference to somebody else' Thread_Pool. - Obvioulsy our concurrency strategy is "<font color=green>thread_pool_</font>" at this point. */</font> -<font color=#008888>Client_Acceptor::Client_Acceptor</font> (Thread_Pool &thread_pool) - : concurrency_ (thread_pool_), - the_thread_pool_ (thread_pool) -{ -} - -<font color=red>/* When we're destructed, we may need to cleanup after ourselves. If - we're running with a thread pool that we own, it is up to us to - close it down. */</font> -<font color=#008888>Client_Acceptor::~Client_Acceptor</font> (void) -{ - if (this->concurrency() == thread_pool_ && thread_pool_is_private ()) - thread_pool ()->close (); -} - -<font color=red>/* Similar to the destructor (and close() below) it is necessary for - us to open the thread pool in some circumstances. - - Notice how we delegate most of the open() work to the open() method - of our baseclass. */</font> -int -<font color=#008888>Client_Acceptor::open</font> (const ACE_INET_Addr &addr, - ACE_Reactor *reactor, - int pool_size) -{ - if (this->concurrency() == thread_pool_ && thread_pool_is_private ()) - thread_pool ()->start (pool_size); - - return <font color=#008888>inherited::open</font> (addr, reactor); -} - -<font color=red>/* Here again we find that we have to manage the thread pool. Like - open() we also delegate the other work to our baseclass. */</font> -int -<font color=#008888>Client_Acceptor::close</font> (void) -{ - if (this->concurrency() == thread_pool_ && thread_pool_is_private ()) - thread_pool ()->stop (); - - return <font color=#008888>inherited::close</font> (); -} - -</PRE> -<HR WIDTH="100%"> - -<P>Nothing really surprising here. Most of it just manages the Thread_Pool. - -<P> -<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/007/page05.html b/docs/tutorials/007/page05.html deleted file mode 100644 index 89307d103d5..00000000000 --- a/docs/tutorials/007/page05.html +++ /dev/null @@ -1,188 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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 007</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 007</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a thread-pool server</FONT></B></CENTER> -<HR> - -<P>As you might expect, <A HREF="client_handler.h">client_handler.h</A> -is next. - -<P> -<HR WIDTH="100%"> -<PRE> -<font color=red>// $Id$</font> - -<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 derive our Client_Handler directly from - ACE_Event_Handler but you still have to have an ACE_SOCK_Stream for - the actually connection. With a direct derivative of - ACE_Event_Handler, you'll have to contain and maintain an - 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> - -<font color=blue>#include</font> "<A HREF="../../../ace/Svc_Handler.h">ace/Svc_Handler.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" - -class Client_Acceptor; -class Thread_Pool; - -<font color=red>/* Another feature of ACE_Svc_Handler is it's ability to present the - ACE_Task<> interface as well. That's what the ACE_NULL_SYNCH - parameter below is all about. That's beyond our scope here but - we'll come back to it in the next tutorial when we start looking at - concurrency options. */</font> -class Client_Handler : public ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> -{ -public: - typedef ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> inherited; - - <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 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 - definition of open() you'll see how we get around that. */</font> - int open (void *acceptor); - - <font color=red>/* When an ACE_Task<> 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 clean itself - up. Since an event handler can be registered for more than one - type of callback, the callback mask is provided to inform - handle_close() exactly which method failed. That way, you don't - have to maintain state information between your handle_* method - calls. The <handle> parameter is explained below... 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! */</font> - int handle_close (ACE_HANDLE handle, - ACE_Reactor_Mask mask); - - <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 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 <handle> would - be important to us for reading the client's data. */</font> - int handle_input (ACE_HANDLE handle); - -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>/* 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 function. You can think of process() as - application-level code and everything elase as - application-framework code. */</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); - - <font color=red>/* When we get to the definition of Client_Handler we'll see that - there are several places where we go back to the Client_Acceptor - for information. It is generally a good idea to do that through - an accesor rather than using the member variable directly. */</font> - Client_Acceptor *client_acceptor (void) - { - return this->client_acceptor_; - } - - <font color=red>/* And since you shouldn't access a member variable directly, - neither should you set (mutate) it. Although it might seem silly - to do it this way, you'll thank yourself for it later. */</font> - void client_acceptor (Client_Acceptor *_client_acceptor) - { - this->client_acceptor_ = _client_acceptor; - } - - <font color=red>/* The concurrency() accessor tells us the current concurrency - strategy. It actually queries the Client_Acceptor for it but by - having the accessor in place, we could change our implementation - without affecting everything that needs to know. */</font> - int concurrency (void); - - <font color=red>/* Likewise for access to the Thread_Pool that we belong to. */</font> - Thread_Pool * thread_pool (void); - - Client_Acceptor *client_acceptor_; - - <font color=red>/* For some reason I didn't create accessor/mutator methods for - this. So much for consistency.... - - This variable is used to remember the thread in which we were - created: the "<font color=green>creator</font>" thread in other words. handle_input() - needs to know if it is operating in the main reactor thread (which - is the one that created us) or if it is operating in one of the - thread pool threads. More on this when we get to handle_input(). */</font> - ACE_thread_t creator_; -}; - -<font color=blue>#endif</font> <font color=red>/* CLIENT_HANDLER_H */</font> -</PRE> -<HR WIDTH="100%"> - -<P>Still, we're just not seeing a lot of changes due to introduction of -the thread pool. That's a good thing! You don't want to go turning -your application upside down just because you changed thread models. - -<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/007/page06.html b/docs/tutorials/007/page06.html deleted file mode 100644 index 2da15db1278..00000000000 --- a/docs/tutorials/007/page06.html +++ /dev/null @@ -1,266 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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 007</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 007</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a thread-pool server</FONT></B></CENTER> -<HR> - -<P><A HREF="client_handler.cpp">client_handler.cpp</A> -shows some of the changes due to the thread-pool. Just a few -though. - -<P> -<HR WIDTH="100%"> -<PRE> -<font color=red>// $Id$</font> - -<font color=red>/* Since this is the third time we've seen most of this, I'm going to - strip out almost all of the comments that you've already seen. - That way, you can concentrate on the new items. */</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>/* We're going to be registering and unregistering a couple of times. - To make sure that we use the same flags every time, I've created - these handy macros. */</font> -<font color=blue>#define</font> <font color=purple>REGISTER_MASK</font> <font color=#008888>ACE_Event_Handler::READ_MASK</font> -<font color=blue>#define</font> <font color=purple>REMOVE_MASK</font> (<font color=#008888>ACE_Event_Handler::READ_MASK</font> | ACE_Event_Handler::DONT_CALL) - -<font color=red>/* Our constructor still doesn't really do anything. We simply - initialize the acceptor pointer to "<font color=green>null</font>" and get our current - thread id. The static self() method of ACE_Thread will return you - a thread id native to your platform. */</font> -<font color=#008888>Client_Handler::Client_Handler</font> (void) - : client_acceptor_(0), - creator_ (<font color=#008888>ACE_Thread::self</font> ()) -{ -} - -<font color=#008888>Client_Handler::~Client_Handler</font> (void) -{ - this->peer().close(); -} - -<font color=red>/* Query our acceptor for the concurrency strategy. Notice that we - don't bother to check that our acceptor pointer is valid. That is - proably a bad idea... */</font> -int -<font color=#008888>Client_Handler::concurrency</font>(void) -{ - return this->client_acceptor ()->concurrency (); -} - -<font color=red>/* And here we ask the acceptor about the thread pool. */</font> -Thread_Pool * -<font color=#008888>Client_Handler::thread_pool</font> (void) -{ - return this->client_acceptor ()->thread_pool (); -} - -<font color=red>/* Back to our open() method. This is straight out of Tutorial 6. - There's nothing additional here for the thread-pool implementation. */</font> -int -<font color=#008888>Client_Handler::open</font> (void *acceptor) -{ - client_acceptor ((Client_Acceptor *) acceptor); - - if (concurrency () == <font color=#008888>Client_Acceptor::thread_per_connection_</font>) - return this->activate (THR_DETACHED); - - this->reactor (client_acceptor()->reactor ()); - - ACE_INET_Addr addr; - - if (this->peer ().get_remote_addr (addr) == -1) - return -1; - - if (this->reactor ()->register_handler (this, - REGISTER_MASK) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>(%P|%t) can't register with reactor\n</font>"), - -1); - - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) connected with %s\n</font>", - addr.get_host_name ())); - return 0; -} - -<font color=red>/* The destroy() method will remove us from the reactor (with the - DONT_CALL flag set!) and then free our memory. This allows us to - be closed from outside of the reactor context without any danger. */</font> -void -<font color=#008888>Client_Handler::destroy</font> (void) -{ - this->reactor ()->remove_handler (this, REMOVE_MASK); - delete this; -} - -<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. */</font> -int -<font color=#008888>Client_Handler::close</font> (u_long flags) -{ - ACE_UNUSED_ARG(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>/* We will be called when handle_input() returns -1. That's our queue - to delete ourselves to prevent memory leaks. */</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); - - delete this; - - 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. - - You've read that much before... Now we have to do some extra stuff - in case we're using the thread-pool implementation. If we're - called by our creator thread then we must be in the reactor. In - that case, we arrange to be put into the thread pool. If we're not - in the creator thread then we must be in the thread pool and we can - do some work. */</font> -int -<font color=#008888>Client_Handler::handle_input</font> (ACE_HANDLE handle) -{ - ACE_UNUSED_ARG (handle); - - <font color=red>/* Check our strategy. If we're using the thread pool and we're in - the creation thread then we know we were called by the reactor. */</font> - if (concurrency () == <font color=#008888>Client_Acceptor::thread_pool_</font>) - { - if (<font color=#008888>ACE_OS::thr_equal</font> (ACE_Thread::self(), - creator_)) - { - <font color=red>/* 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); - } - } - - <font color=red>/* Any strategy other than thread-per-connection will eventually get - here. If we're in the single-threaded implementation or the - thread-pool, we still have to pass this way. */</font> - - char buf[BUFSIZ]; - - <font color=red>/* Invoke the process() method to do the work but save it's return - value instead of returning it immediately. */</font> - - int rval = this->process (buf, sizeof (buf)); - - <font color=red>/* Now, we look again to see if we're in the thread-pool - implementation. If so then we need to re-register ourselves with - the reactor so that we can get more work when it is available. - (If suspend_handler() worked then we would use resume_handler() - here.) */</font> - if (concurrency () == <font color=#008888>Client_Acceptor::thread_pool_</font>) - { - 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); - } - - <font color=red>/* Return the result of process() */</font> - return rval; -} - -<font color=red>/* Remember that when we leave our svc() method, the framework will - take care of calling our close() method so that we can cleanup - after ourselves. */</font> -int -<font color=#008888>Client_Handler::svc</font> (void) -{ - char buf[BUFSIZ]; - - while (1) - if (this->process (buf, sizeof (buf)) == -1) - return -1; - - return 0; -} - -<font color=red>/* Once again, we see that the application-level logic has not been at - all affected by our choice of threading models. Of course, I'm not - sharing data between threads or anything. We'll leave locking - issues for a later tutorial. */</font> -int -<font color=#008888>Client_Handler::process</font> (char *rdbuf, - int rdbuf_len) -{ - ssize_t bytes_read; - switch ( (bytes_read = this->peer ().recv (rdbuf, rdbuf_len)) ) - { - case -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, - "<font color=green>(%P|%t) closing daemon (fd = %d)\n</font>", - this->get_handle ()), - -1); - default: - rdbuf[bytes_read] = 0; - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) from client: %s</font>", - rdbuf)); - } - - return 0; -} -</PRE> -<HR WIDTH="100%"> - -<P>Ok, now we've gone and changed handle_input() so that it knows when -to do work and when to enqueue itself. Beyond that, we're still about -the same. - -<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/007/page07.html b/docs/tutorials/007/page07.html deleted file mode 100644 index f0a14dac2fb..00000000000 --- a/docs/tutorials/007/page07.html +++ /dev/null @@ -1,112 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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 007</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 007</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a thread-pool server</FONT></B></CENTER> -<HR> -<P>Two new files this time. The first is <A HREF="thread_pool.h">thread_pool.h</A> -where we declare our Thread_Pool object. This is responsible for -abstracting away the thread pool implementation details and allowing us -to make so few changes to the rest of the code. - -<P> -<HR WIDTH="100%"><FONT FACE="Arial,Helvetica"></FONT> - -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>THREAD_POOL_H</font> -<font color=blue>#define</font> <font color=purple>THREAD_POOL_H</font> - -<font color=red>/* In order to implement a thread pool, we have to have an object that - can create a thread. The ACE_Task<> is the basis for doing just - such a thing. */</font> -<font color=blue>#include</font> "<A HREF="../../../ace/Task.h">ace/Task.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/Atomic_Op.h">ace/Atomic_Op.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=red>/* We need a forward reference for ACE_Event_Handler so that our - enqueue() method can accept a pointer to one. */</font> -class ACE_Event_Handler; - -<font color=red>/* Although we modified the rest of our program to make use of the - thread pool implementation, if you look closely you'll see that the - changes were rather minor. The "<font color=green>ACE way</font>" is generally to create a - helper object that abstracts away the details not relevant to your - application. That's what I'm trying to do here by creating the - Thread_Pool object. */</font> -class Thread_Pool : public ACE_Task<ACE_MT_SYNCH> -{ -public: - typedef ACE_Task<ACE_MT_SYNCH> inherited; - - <font color=red>/* Provide an enumeration for the default pool size. By doing this, - other objects can use the value when they want a default. */</font> - enum size_t - { - default_pool_size_ = 5 - }; - - <font color=red>// Basic constructor</font> - Thread_Pool (void); - - <font color=red>/* Starting the thread pool causes one or more threads to be - activated. When activated, they all execute the svc() method - declared below. */</font> - int start (int pool_size = default_pool_size_); - - <font color=red>/* - */</font> - virtual int stop (void); - - <font color=red>/* To use the thread pool, you have to put some unit of work into - it. Since we're dealing with event handlers (or at least their - derivatives), I've chosen to provide an enqueue() method that - takes a pointer to an ACE_Event_Handler. The handler's - handle_input() method will be called, so your object has to know - when it is being called by the thread pool. */</font> - int enqueue (ACE_Event_Handler *handler); - - <font color=red>/* Another handy ACE template is ACE_Atomic_Op<>. When - parameterized, this allows is to have a thread-safe counting - object. The typical arithmetic operators are all internally - thread-safe so that you can share it across threads without - worrying about any contention issues. */</font> - typedef ACE_Atomic_Op<ACE_Mutex, int> counter_t; - -protected: - - <font color=red>/* Our svc() method will dequeue the enqueued event handler objects - and invoke the handle_input() method on each. Since we're likely - running in more than one thread, idle threads can take work from - the queue while other threads are busy executing handle_input() on - some object. */</font> - int svc (void); - - <font color=red>/* We use the atomic op to keep a count of the number of threads in - which our svc() method is running. This is particularly important - when we want to close() it down! */</font> - counter_t active_threads_; -}; - -<font color=blue>#endif</font> <font color=red>/* THREAD_POOL_H */</font> -</PRE> -<HR WIDTH="100%"> - -<P>Well, that doesn't look too complex. What about the implementation? - -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page08.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/007/page08.html b/docs/tutorials/007/page08.html deleted file mode 100644 index 14c99353ad2..00000000000 --- a/docs/tutorials/007/page08.html +++ /dev/null @@ -1,280 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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 007</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 007</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a thread-pool server</FONT></B></CENTER> -<HR> - -<P>Finally, <A HREF="thread_pool.cpp">thread_pool.cpp</A> -where we have the Thread_Pool object implementation. -<P> -Remember back in <A HREF="../006/page01.html">Tutorial 6</A> when I - was talking about <i>THR_NEW_LWP</i>? Look closely and you'll - see it here. It's bitwise OR'd with <i>THR_DETACHED</i> just to - keep things interesting. -<P> -<HR WIDTH="100%"> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>thread_pool.h</font>" - -<font color=red>/* We need this header so that we can invoke handle_input() on the - objects we dequeue. */</font> -<font color=blue>#include</font> "<A HREF="../../../ace/Event_Handler.h">ace/Event_Handler.h</A>" - -<font color=red>/* All we do here is initialize our active thread counter. */</font> -<font color=#008888>Thread_Pool::Thread_Pool</font> (void) - : active_threads_ (0) -{ -} - -<font color=red>/* Our start() method is a thin disguise around the ACE_Task<> - activate() method. By hiding activate() in this way, the users of - Thread_Pool don't have to worry about the thread configuration - flags. */</font> -int -<font color=#008888>Thread_Pool::start</font> (int pool_size) -{ - return this->activate (THR_NEW_LWP|THR_DETACHED, pool_size); -} - -<font color=red>/* Closing the thread pool can be a tricky exercise. I've decided to - take an easy approach and simply enqueue a secret message for each - thread we have active. */</font> -int -<font color=#008888>Thread_Pool::stop</font> (void) -{ - <font color=red>/* Find out how many threads are currently active */</font> - int counter = active_threads_.value (); - - <font color=red>/* For each one of the active threads, enqueue a "<font color=green>null</font>" event - handler. Below, we'll teach our svc() method that "<font color=green>null</font>" means - "<font color=green>shutdown</font>". */</font> - while (counter--) - this->enqueue (0); - - <font color=red>/* As each svc() method exits, it will decrement the active thread - counter. We just wait here for it to reach zero. Since we don't - know how long it will take, we sleep for a quarter of a second - between tries. */</font> - while (active_threads_.value ()) - <font color=#008888>ACE_OS::sleep</font> (ACE_Time_Value (0, 250000)); - - return(0); -} - -<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 misuse it. */</font> -int -<font color=#008888>Thread_Pool::enqueue</font> (ACE_Event_Handler *handler) -{ - <font color=red>/* An ACE_Message_Block is a chunk of data. You put them into an - ACE_Message_Queue. ACE_Task<> has an ACE_Message_Queue built in. - In fact, the parameter to ACE_Task<> is passed directly to - ACE_Message_Queue. If you look back at our header file you'll see - that we used ACE_MT_SYNCH as the parameter indicating that we want - MultiThread Synch safety. This allows us to safely put - ACE_Message_Block objects into the message queue in one thread and - take them out in another. */</font> - - <font color=red>/* An ACE_Message_Block wants to have char* data. We don't have - that. We could cast our ACE_Event_Handler* directly to a char* - but I wanted to be more explicit. Since casting pointers around - is a dangerous thing, I've gone out of my way here to be very - clear about what we're doing. - - First: Cast the handler pointer to a void pointer. You can't do - any useful work on a void pointer, so this is a clear message that - we're making the pointer unusable. - - Next: Cast the void pointer to a char pointer that the ACE_Message_Block will accept. */</font> - void *v_data = (void *) handler; - char *c_data = (char *) v_data; - - ACE_Message_Block *mb; - - <font color=red>/* Construct a new ACE_Message_Block. For efficiency, you might - want to preallocate a stack of these and reuse them. For - simplicity, I'll just create what I need as I need it. */</font> - ACE_NEW_RETURN (mb, - ACE_Message_Block (c_data), - -1); - - <font color=red>/* Our putq() method is a wrapper around one of the enqueue methods - of the ACE_Message_Queue that we own. Like all good methods, it - returns -1 if it fails for some reason. */</font> - if (this->putq (mb) == -1) - { - <font color=red>/* Another trait of the ACE_Message_Block objects is that they - are reference counted. Since they're designed to be passed - around between various objects in several threads we can't - just delete them whenever we feel like it. The release() - method is similar to the destroy() method we've used - elsewhere. It watches the reference count and will delete the - object when possible. */</font> - mb->release (); - return -1; - } - - return 0; -} - -<font color=red>/* The "<font color=green>guard</font>" concept is very powerful and used throughout - multi-threaded applications. A guard normally does some operation - on an object at construction and the "<font color=green>opposite</font>" operation at - destruction. For instance, when you guard a mutex (lock) object, - the guard will acquire the lock on construction and release it on - destruction. In this way, your method can simply let the guard go - out of scope and know that the lock is released. - - Guards aren't only useful for locks however. In this application - I've created two guard objects for quite a different purpose. */</font> - -<font color=red>/* The Counter_Guard is constructed with a reference to the thread - pool's active thread counter. The guard increments the counter - when it is created and decrements it at destruction. By creating - one of these in svc(), I know that the counter will be decremented - no matter how or where svc() returns. */</font> -class Counter_Guard -{ -public: - Counter_Guard (<font color=#008888>Thread_Pool::counter_t</font> &counter) - : counter_ (counter) - { - ++counter_; - } - - ~Counter_Guard (void) - { - --counter_; - } - -protected: - <font color=#008888>Thread_Pool::counter_t</font> &counter_; -}; - -<font color=red>/* My Message_Block_Guard is also a little non-traditional. It - doesn't do anything in the constructor but it's destructor ensures - that the message block's release() method is called. This is a - cheap way to prevent a memory leak if I need an additional exit - point in svc(). */</font> -class Message_Block_Guard -{ -public: - Message_Block_Guard (ACE_Message_Block *&mb) - : mb_ (mb) - { - } - - ~Message_Block_Guard (void) - { - mb_->release (); - } - -protected: - ACE_Message_Block *&mb_; -}; - -<font color=red>/* Now we come to the svc() method. As I said, this is being executed - in each thread of the Thread_Pool. Here, we pull messages off of - our built-in ACE_Message_Queue and cause them to do work. */</font> -int -<font color=#008888>Thread_Pool::svc</font> (void) -{ - <font color=red>/* The getq() method takes a reference to a pointer. So... we need - a pointer to give it a reference to. */</font> - ACE_Message_Block *mb; - - <font color=red>/* Create the guard for our active thread counter object. No matter - where we choose to return() from svc(), we now know that the - counter will be decremented. */</font> - Counter_Guard counter_guard (active_threads_); - - <font color=red>/* Get messages from the queue until we have a failure. There's no - real good reason for failure so if it happens, we leave - immediately. */</font> - while (this->getq (mb) != -1) - { - <font color=red>/* A successful getq() will cause "<font color=green>mb</font>" to point to a valid - refernce-counted ACE_Message_Block. We use our guard object - here so that we're sure to call the release() method of that - message block and reduce it's reference count. Once the count - reaches zero, it will be deleted. */</font> - Message_Block_Guard message_block_guard (mb); - - <font color=red>/* As noted before, the ACE_Message_Block stores it's data as a - char*. We pull that out here and later turn it into an - ACE_Event_Handler* */</font> - char *c_data = mb->base (); - - <font color=red>/* We've chosen to use a "<font color=green>null</font>" value as an indication to leave. - If the data we got from the queue is not null then we have - some work to do. */</font> - if (c_data) - { - <font color=red>/* Once again, we go to great lengths to emphasize the fact - that we're casting pointers around in rather impolite - ways. We could have cast the char* directly to an - ACE_Event_Handler* but then folks might think that's an OK - thing to do. - - (Note: The correct way to use an ACE_Message_Block is to - write data into it. What I should have done was create a - message block big enough to hold an event handler pointer - and then written the pointer value into the block. When - we got here, I would have to read that data back into a - pointer. While politically correct, it is also a lot of - work. If you're careful you can get away with casting - pointers around.) */</font> - void *v_data = (void *) c_data; - - ACE_Event_Handler *handler = (ACE_Event_Handler *) v_data; - - <font color=red>/* Now that we finally have an event handler pointer, invoke - it's handle_input() method. Since we don't know it's - handle, we just give it a default. That's OK because we - know that we're not using the handle in the method anyway. */</font> - if (handler->handle_input (ACE_INVALID_HANDLE) == -1) - { - <font color=red>/* Tell the handler that it's time to go home. The - "<font color=green>normal</font>" method for shutting down a handler whose - handler failed is to invoke handle_close(). This will - take care of cleaning it up for us. Notice how we use - the handler's get_handle() method to populate it's - "<font color=green>handle</font>" parameter. Convenient isn't it? */</font> - handler->handle_close (handler->get_handle (), 0); - - <font color=red>/* Also notice that we don't exit the svc() method here! - The first time I did this, I was exiting. After a few - clients disconnect you have an empty thread pool. - Hard to do any more work after that... */</font> - } - } - else - <font color=red>/* If we get here, we were given a message block with "<font color=green>null</font>" - data. That is our signal to leave, so we return(0) to - leave gracefully. */</font> - return 0; <font color=red>// Ok, shutdown request</font> - - <font color=red>// message_block_guard goes out of scope here and releases the</font> - <font color=red>// message_block instance.</font> - } - - return 0; -} - -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page09.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/007/page09.html b/docs/tutorials/007/page09.html deleted file mode 100644 index a80bf7036ad..00000000000 --- a/docs/tutorials/007/page09.html +++ /dev/null @@ -1,79 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <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 007</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 007</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Creating a thread-pool server</FONT></B></CENTER> -<HR> - -<P>That's it for Tutorial 7. As with Tutorial 6, we really didn't -have to change much to introduce a new threading strategy. Most of -the work was in creating the Thread_Pool object itself. Everything -else was just minor housekeeping. - -<P>There is a fourth common thread strategy: thread-per-request. -It's not one of my favorites, so I wasn't planning to go into it. -If you want to contribute a tutorial on that topic though, I'll be glad -to include it here. - -<P>For reference, here's the file list again: -<UL> -<LI> -<A HREF="Makefile">Makefile</A></LI> - -<LI> -<A HREF="client_acceptor.h">client_acceptor.h</A></LI> - -<LI> -<A HREF="client_acceptor.cpp">client_acceptor.cpp</A></LI> - -<LI> -<A HREF="client_handler.cpp">client_handler.cpp</A></LI> - -<LI> -<A HREF="client_handler.h">client_handler.h</A></LI> - -<LI> -<A HREF="server.cpp">server.cpp</A></LI> - -<LI> -<A HREF="thread_pool.h">thread_pool.h</A></LI> - -<LI> -<A HREF="thread_pool.cpp">thread_pool.cpp</A></LI> - -</UL> -<P> -<HR WIDTH="100%"> -<P> -<center><h2>Danger, Warning!</h2></center> -Now that I've gone through all of this to create a thread pool server, -I have to point out that this isn't exactly the best or safest way to -do so. The biggest danger we face with this approach is the -possibility of an event handler existing in the thread pool's message -queue <i>after</i> it has been deleted. When the thread's svc() -method attempts to invoke <i>handle_input()</i> you will get a nasty -core dump. -<p> -The safest way to handle the situation is to use reference-counted -pointers everywhere a Client_Handler pointer would be used. That's -beyond the scope of the tutorial but I encourage you to give it a -try. If you want to contribute that back as an enhanced Tutorial, -I'll be glad to include it. -<p> -Another approach that should work quite well is to use the -ACE_TP_Reactor instead of just ACE_Reactor. This takes a little more -setup but results in a cleaner implementation. Again, I've not had -time to develop a Tutorial on the TP_Reactor but would welcome any -contributions. -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/007/server.cpp b/docs/tutorials/007/server.cpp deleted file mode 100644 index 4e61be6f23a..00000000000 --- a/docs/tutorials/007/server.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// $Id$ - -/* 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 "real work". */ - -#include "client_acceptor.h" - -/* 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. */ - -static sig_atomic_t finished = 0; -extern "C" void handler (int) -{ - finished = 1; -} - -/* 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. */ - -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -/* 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. */ - -int -main (int argc, char *argv[]) -{ - ACE_UNUSED_ARG(argc); - ACE_UNUSED_ARG(argv); - - /* 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. */ - ACE_Reactor reactor; - - /* 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.) */ - Client_Acceptor peer_acceptor; - - /* 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 "well known" 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. */ - if (peer_acceptor.open (ACE_INET_Addr (PORT), &reactor) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "open"), - -1); - - /* 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 "real" work. Our simple - flag-setter doesn't justify deriving from ACE_Event_Handler and - providing a callback function though. */ - ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT); - - /* 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. */ - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) starting up server daemon\n")); - - /* This will loop "forever" 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 <i>restart</i> flag on - the open() method of ACE_Reactor if you're interested.) */ - while (!finished) - reactor.handle_events (); - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) shutting down server daemon\n")); - - return 0; -} - -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR>; -template class ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>; -template class ACE_Guard<ACE_Mutex>; -template class ACE_Atomic_Op<ACE_Mutex, int>; -#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> -#pragma instantiate ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> -#pragma instantiate ACE_Guard<ACE_Mutex> -#pragma instantiate ACE_Atomic_Op<ACE_Mutex, int> -#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/docs/tutorials/007/thread_pool.cpp b/docs/tutorials/007/thread_pool.cpp deleted file mode 100644 index f66f0e966f9..00000000000 --- a/docs/tutorials/007/thread_pool.cpp +++ /dev/null @@ -1,250 +0,0 @@ -// $Id$ - -#include "thread_pool.h" - -/* We need this header so that we can invoke handle_input() on the - objects we dequeue. */ -#include "ace/Event_Handler.h" - -/* All we do here is initialize our active thread counter. */ -Thread_Pool::Thread_Pool (void) - : active_threads_ (0) -{ -} - -/* Our start() method is a thin disguise around the ACE_Task<> - activate() method. By hiding activate() in this way, the users of - Thread_Pool don't have to worry about the thread configuration - flags. */ -int -Thread_Pool::start (int pool_size) -{ - return this->activate (THR_NEW_LWP|THR_DETACHED, pool_size); -} - -/* Closing the thread pool can be a tricky exercise. I've decided to - take an easy approach and simply enqueue a secret message for each - thread we have active. */ -int -Thread_Pool::stop (void) -{ - /* Find out how many threads are currently active */ - int counter = active_threads_.value (); - - /* For each one of the active threads, enqueue a "null" event - handler. Below, we'll teach our svc() method that "null" means - "shutdown". */ - while (counter--) - this->enqueue (0); - - /* As each svc() method exits, it will decrement the active thread - counter. We just wait here for it to reach zero. Since we don't - know how long it will take, we sleep for a quarter of a second - between tries. */ - while (active_threads_.value ()) - ACE_OS::sleep (ACE_Time_Value (0, 250000)); - - return(0); -} - -/* 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 misuse it. */ -int -Thread_Pool::enqueue (ACE_Event_Handler *handler) -{ - /* An ACE_Message_Block is a chunk of data. You put them into an - ACE_Message_Queue. ACE_Task<> has an ACE_Message_Queue built in. - In fact, the parameter to ACE_Task<> is passed directly to - ACE_Message_Queue. If you look back at our header file you'll see - that we used ACE_MT_SYNCH as the parameter indicating that we want - MultiThread Synch safety. This allows us to safely put - ACE_Message_Block objects into the message queue in one thread and - take them out in another. */ - - /* An ACE_Message_Block wants to have char* data. We don't have - that. We could cast our ACE_Event_Handler* directly to a char* - but I wanted to be more explicit. Since casting pointers around - is a dangerous thing, I've gone out of my way here to be very - clear about what we're doing. - - First: Cast the handler pointer to a void pointer. You can't do - any useful work on a void pointer, so this is a clear message that - we're making the pointer unusable. - - Next: Cast the void pointer to a char pointer that the ACE_Message_Block will accept. */ - void *v_data = (void *) handler; - char *c_data = (char *) v_data; - - ACE_Message_Block *mb; - - /* Construct a new ACE_Message_Block. For efficiency, you might - want to preallocate a stack of these and reuse them. For - simplicity, I'll just create what I need as I need it. */ - ACE_NEW_RETURN (mb, - ACE_Message_Block (c_data), - -1); - - /* Our putq() method is a wrapper around one of the enqueue methods - of the ACE_Message_Queue that we own. Like all good methods, it - returns -1 if it fails for some reason. */ - if (this->putq (mb) == -1) - { - /* Another trait of the ACE_Message_Block objects is that they - are reference counted. Since they're designed to be passed - around between various objects in several threads we can't - just delete them whenever we feel like it. The release() - method is similar to the destroy() method we've used - elsewhere. It watches the reference count and will delete the - object when possible. */ - mb->release (); - return -1; - } - - return 0; -} - -/* The "guard" concept is very powerful and used throughout - multi-threaded applications. A guard normally does some operation - on an object at construction and the "opposite" operation at - destruction. For instance, when you guard a mutex (lock) object, - the guard will acquire the lock on construction and release it on - destruction. In this way, your method can simply let the guard go - out of scope and know that the lock is released. - - Guards aren't only useful for locks however. In this application - I've created two guard objects for quite a different purpose. */ - -/* The Counter_Guard is constructed with a reference to the thread - pool's active thread counter. The guard increments the counter - when it is created and decrements it at destruction. By creating - one of these in svc(), I know that the counter will be decremented - no matter how or where svc() returns. */ -class Counter_Guard -{ -public: - Counter_Guard (Thread_Pool::counter_t &counter) - : counter_ (counter) - { - ++counter_; - } - - ~Counter_Guard (void) - { - --counter_; - } - -protected: - Thread_Pool::counter_t &counter_; -}; - -/* My Message_Block_Guard is also a little non-traditional. It - doesn't do anything in the constructor but it's destructor ensures - that the message block's release() method is called. This is a - cheap way to prevent a memory leak if I need an additional exit - point in svc(). */ -class Message_Block_Guard -{ -public: - Message_Block_Guard (ACE_Message_Block *&mb) - : mb_ (mb) - { - } - - ~Message_Block_Guard (void) - { - mb_->release (); - } - -protected: - ACE_Message_Block *&mb_; -}; - -/* Now we come to the svc() method. As I said, this is being executed - in each thread of the Thread_Pool. Here, we pull messages off of - our built-in ACE_Message_Queue and cause them to do work. */ -int -Thread_Pool::svc (void) -{ - /* The getq() method takes a reference to a pointer. So... we need - a pointer to give it a reference to. */ - ACE_Message_Block *mb; - - /* Create the guard for our active thread counter object. No matter - where we choose to return() from svc(), we now know that the - counter will be decremented. */ - Counter_Guard counter_guard (active_threads_); - - /* Get messages from the queue until we have a failure. There's no - real good reason for failure so if it happens, we leave - immediately. */ - while (this->getq (mb) != -1) - { - /* A successful getq() will cause "mb" to point to a valid - refernce-counted ACE_Message_Block. We use our guard object - here so that we're sure to call the release() method of that - message block and reduce it's reference count. Once the count - reaches zero, it will be deleted. */ - Message_Block_Guard message_block_guard (mb); - - /* As noted before, the ACE_Message_Block stores it's data as a - char*. We pull that out here and later turn it into an - ACE_Event_Handler* */ - char *c_data = mb->base (); - - /* We've chosen to use a "null" value as an indication to leave. - If the data we got from the queue is not null then we have - some work to do. */ - if (c_data) - { - /* Once again, we go to great lengths to emphasize the fact - that we're casting pointers around in rather impolite - ways. We could have cast the char* directly to an - ACE_Event_Handler* but then folks might think that's an OK - thing to do. - - (Note: The correct way to use an ACE_Message_Block is to - write data into it. What I should have done was create a - message block big enough to hold an event handler pointer - and then written the pointer value into the block. When - we got here, I would have to read that data back into a - pointer. While politically correct, it is also a lot of - work. If you're careful you can get away with casting - pointers around.) */ - void *v_data = (void *) c_data; - - ACE_Event_Handler *handler = (ACE_Event_Handler *) v_data; - - /* Now that we finally have an event handler pointer, invoke - it's handle_input() method. Since we don't know it's - handle, we just give it a default. That's OK because we - know that we're not using the handle in the method anyway. */ - if (handler->handle_input (ACE_INVALID_HANDLE) == -1) - { - /* Tell the handler that it's time to go home. The - "normal" method for shutting down a handler whose - handler failed is to invoke handle_close(). This will - take care of cleaning it up for us. Notice how we use - the handler's get_handle() method to populate it's - "handle" parameter. Convenient isn't it? */ - handler->handle_close (handler->get_handle (), 0); - - /* Also notice that we don't exit the svc() method here! - The first time I did this, I was exiting. After a few - clients disconnect you have an empty thread pool. - Hard to do any more work after that... */ - } - } - else - /* If we get here, we were given a message block with "null" - data. That is our signal to leave, so we return(0) to - leave gracefully. */ - return 0; // Ok, shutdown request - - // message_block_guard goes out of scope here and releases the - // message_block instance. - } - - return 0; -} - diff --git a/docs/tutorials/007/thread_pool.h b/docs/tutorials/007/thread_pool.h deleted file mode 100644 index b83742511ac..00000000000 --- a/docs/tutorials/007/thread_pool.h +++ /dev/null @@ -1,81 +0,0 @@ -// $Id$ - -#ifndef THREAD_POOL_H -#define THREAD_POOL_H - -/* In order to implement a thread pool, we have to have an object that - can create a thread. The ACE_Task<> is the basis for doing just - such a thing. */ -#include "ace/Task.h" -#include "ace/Atomic_Op.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -/* We need a forward reference for ACE_Event_Handler so that our - enqueue() method can accept a pointer to one. */ -class ACE_Event_Handler; - -/* Although we modified the rest of our program to make use of the - thread pool implementation, if you look closely you'll see that the - changes were rather minor. The "ACE way" is generally to create a - helper object that abstracts away the details not relevant to your - application. That's what I'm trying to do here by creating the - Thread_Pool object. */ -class Thread_Pool : public ACE_Task<ACE_MT_SYNCH> -{ -public: - typedef ACE_Task<ACE_MT_SYNCH> inherited; - - /* Provide an enumeration for the default pool size. By doing this, - other objects can use the value when they want a default. */ - enum size_t - { - default_pool_size_ = 5 - }; - - // Basic constructor - Thread_Pool (void); - - /* Starting the thread pool causes one or more threads to be - activated. When activated, they all execute the svc() method - declared below. */ - int start (int pool_size = default_pool_size_); - - /* - Shut down the thread pool. - */ - virtual int stop (void); - - /* To use the thread pool, you have to put some unit of work into - it. Since we're dealing with event handlers (or at least their - derivatives), I've chosen to provide an enqueue() method that - takes a pointer to an ACE_Event_Handler. The handler's - handle_input() method will be called, so your object has to know - when it is being called by the thread pool. */ - int enqueue (ACE_Event_Handler *handler); - - /* Another handy ACE template is ACE_Atomic_Op<>. When - parameterized, this allows is to have a thread-safe counting - object. The typical arithmetic operators are all internally - thread-safe so that you can share it across threads without - worrying about any contention issues. */ - typedef ACE_Atomic_Op<ACE_Mutex, int> counter_t; - -protected: - - /* Our svc() method will dequeue the enqueued event handler objects - and invoke the handle_input() method on each. Since we're likely - running in more than one thread, idle threads can take work from - the queue while other threads are busy executing handle_input() on - some object. */ - int svc (void); - - /* We use the atomic op to keep a count of the number of threads in - which our svc() method is running. This is particularly important - when we want to close() it down! */ - counter_t active_threads_; -}; - -#endif /* THREAD_POOL_H */ diff --git a/docs/tutorials/008/008-broadcast.dsp b/docs/tutorials/008/008-broadcast.dsp deleted file mode 100644 index b7aafc7ba00..00000000000 --- a/docs/tutorials/008/008-broadcast.dsp +++ /dev/null @@ -1,102 +0,0 @@ -# Microsoft Developer Studio Project File - Name="008 broadcast" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=008 broadcast - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "008-broadcast.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "008-broadcast.mak" CFG="008 broadcast - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "008 broadcast - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "008 broadcast - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "008 broadcast - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "008 broadcast - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"../broadcast_client.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "008 broadcast - Win32 Release"
-# Name "008 broadcast - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=broadcast_client.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/008/008-direct.dsp b/docs/tutorials/008/008-direct.dsp deleted file mode 100644 index a8f6d2386ce..00000000000 --- a/docs/tutorials/008/008-direct.dsp +++ /dev/null @@ -1,102 +0,0 @@ -# Microsoft Developer Studio Project File - Name="008 direct" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=008 direct - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "008-direct.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "008-direct.mak" CFG="008 direct - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "008 direct - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "008 direct - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "008 direct - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "008 direct - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"../directed_client.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "008 direct - Win32 Release"
-# Name "008 direct - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=directed_client.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/008/008-server.dsp b/docs/tutorials/008/008-server.dsp deleted file mode 100644 index 8db64b2fa66..00000000000 --- a/docs/tutorials/008/008-server.dsp +++ /dev/null @@ -1,102 +0,0 @@ -# Microsoft Developer Studio Project File - Name="008 server" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=008 server - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "008-server.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "008-server.mak" CFG="008 server - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "008 server - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "008 server - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "008 server - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "008 server - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"../server.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "008 server - Win32 Release"
-# Name "008 server - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=server.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/008/Makefile b/docs/tutorials/008/Makefile deleted file mode 100644 index b595ecbc814..00000000000 --- a/docs/tutorials/008/Makefile +++ /dev/null @@ -1,74 +0,0 @@ -#---------------------------------------------------------------------------- -# $Id$ -#---------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = server directed_client broadcast_client - -FILES = - -BUILD = $(VBIN) - -HDR = *.h - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -bli0 -l80 -fca -fc1 -cli0 -cdb < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - -Depend : depend - perl ../fix.Makefile - -.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) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - - # Don't put anything below here. Between the "depend" target and fix.Makefile - # it's guaranteed to be lost! - - # This is inserted by the fix.Makefile script -include .depend diff --git a/docs/tutorials/008/broadcast_client.cpp b/docs/tutorials/008/broadcast_client.cpp deleted file mode 100644 index 3176de032a2..00000000000 --- a/docs/tutorials/008/broadcast_client.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// $Id$ - -#include "ace/Log_Msg.h" -#include "ace/SOCK_Dgram_Bcast.h" -#include "ace/INET_Addr.h" - -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -int -main (int argc,char *argv[]) -{ - ACE_UNUSED_ARG(argc); - ACE_UNUSED_ARG(argv); - - ACE_INET_Addr local ((u_short) 0); - - /* Instead of creating the ACE_SOCK_Dgram we created last time, - we'll create an ACE_SOCK_Dgram_Bcast. "Bcast" means, of course, - "Broadcast". This ACE object is clever enough to go out to the OS - and find all of the network interfaces. When you send() on a - Dgram_Bcast, it will send the datagram out on all of those - interfaces. This is quiet handy if you do it on a multi-homed - host that plays router... */ - ACE_SOCK_Dgram_Bcast dgram; - - if (dgram.open (local) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "datagram open"), - -1); - - char buf[BUFSIZ]; - - sprintf (buf, "Hello World!"); - - /* The only other difference between us and the directed client is - that we don't specify a host to receive the datagram. Instead, we - use the magic value "INADDR_BROADCAST". All hosts are obliged to - respond to datagrams directed to this address the same as they - would to datagrams sent to their hostname. - - Remember, the Dgram_Bcast will send a datagram to all interfaces - on the host. That's true even if the address is for a specific - host (and the host address makes sense for the interface). The - real power is in using an INADDR_BROADCAST addressed datagram - against all interfaces. */ - - ACE_INET_Addr remote (PORT, - INADDR_BROADCAST); - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Sending (%s) to the server.\n", - buf)); - - if (dgram.send (buf, - ACE_OS::strlen (buf) + 1, - remote) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "send"), - -1); - - if (dgram.recv (buf, - sizeof (buf), - remote) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "recv"), - -1); - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) The server said: %s\n", - buf)); - - /* Using the "remote" object instance, find out where the server - lives. We could then save this address and use directed datagrams - to chat with the server for a while. */ - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) The server can be found at: (%s:%d)\n", - remote.get_host_name(), - PORT)); - - return 0; -} diff --git a/docs/tutorials/008/combine.shar b/docs/tutorials/008/combine.shar deleted file mode 100644 index 972cbb7c6dd..00000000000 --- a/docs/tutorials/008/combine.shar +++ /dev/null @@ -1,465 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/008'. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 515 -rw-rw-r-- hdr -# 59 -rw-rw-r-- bodies -# 2767 -rw-rw-r-- page01.pre -# 416 -rw-rw-r-- page02.pre -# 345 -rw-rw-r-- page03.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 -# 1173 -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 _sh32494; 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 <TITLE>ACE Tutorial 008</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> -X -<CENTER><B><FONT SIZE=+2>ACE Tutorial 008</FONT></B></CENTER> -X -<CENTER><B><FONT SIZE=+2>Sending and receiving datagrams</FONT></B></CENTER> -X -X -<P> -<HR WIDTH="100%"> -X -SHAR_EOF - $shar_touch -am 03191459100 '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' -e74ecd3335da844c263f961a8ba5f867 hdr -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`" - test 515 -eq "$shar_count" || - $echo 'hdr:' 'original size' '515,' '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 -directed_client.cpp -broadcast_client.cpp -SHAR_EOF - $shar_touch -am 0121153799 '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' -707d1735ca25694e2b5fddc1f6e7e124 bodies -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`" - test 59 -eq "$shar_count" || - $echo 'bodies:' 'original size' '59,' '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 a lot of IPC programming, the clients know where the servers -are. A mail client, for instance, has a configuration file that says -where the mail host is. Your web browser has a "location" field that -you type into to give it a destination. -X -<P>What if you have written a server application and then you execute it -on several systems in your network? All of the instances are probably -more or less equal to the client's point of view, so you don't want to -"configure" the clients to a single server each. Likewise, you -want the ability to add and remove servers at any time so you can't just -give the clients a list to choose from. -X -<P>So... how do the clients know where the servers are? -X -<P>Let 'em ask! -X -<P>Datagrams are great for this. You can toss a datagram out onto -the network and any servers listening at the correct port will* hear it. -Like ACE_SOCK_Stream that we've seen before, you can get the peer address -from a datagram. With that, the server can send a response -back to the client. The client, in turn, can pull the peer address -out and know exactly where the server lives. -X -<P>In this tutorial we'll develop three applications: a server listening -for datagrams, a client that can send to a known host and a client that -can send to the entire (sub)network. In the next tutorial, we'll -expand on this to make the server a bit more prudish. -<P> -Kirthika's abstract: -<UL> -Here, we play with datagram sockets and use it for server discovery by -the client. Datagrams are used by UDP, which is an unreliable and -connectionless protocol. Datagrams packets are generally very small in -size and aren't designed to be used to handle serious communication -between the server and the client. -<P> -The server waits for datagrams to arrive at a fixed port. -The client either sends to a datagram to the server at a known host, -which is not really the case generally, as the client needs to discover -the server and so it needs to broadcast its datagram request in its -subnet. Then, all servers listening at that interface receive it. The -appropriate server will then handle the request. Remember that -no solid connection is made. On the recv() itself the server obtains the -address of the remote client and then communicates with it. -<P> -Thus, we get a fair glimpse of using another means of communication via -datagrams. -</UL> -<P><FONT SIZE=-1>* Actually, the servers <I>might</I> hear the datagram. -Datagrams are rather unreliable. (Sort of like some operating systems -I know.) Still, if the network traffic isn't too bad, they generally -get through. Your clients can always send out more queries if there -aren't any responses in a timely fashion.</FONT> -X -SHAR_EOF - $shar_touch -am 03191459100 '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' -0773df98f89130f72767715ed27516b6 page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 2767 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '2767,' '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 -<P>The first thing we want to look at is <A HREF="server.cpp">server.cpp</A>. -This is a pretty simple application that listens for datagrams at a known -port and sends back a response. In order to implement a true "discovery" -mechanism, the server will have to be a little bit more picky about who -it responds to. We'll tackle that issue in the next tutorial though... -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -6b27ef52d53a13d2d9e5a5ad16e9be4d page02.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`" - test 416 -eq "$shar_count" || - $echo 'page02.pre:' 'original size' '416,' '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 -<P>In <A HREF="directed_client.cpp">directed_client.cpp</A> we create a -client that knows how to send a datagram to a server on a known host. -This is a good thing if you know where the server lives and want to have -a conversation. The Unix <I>talk</I> utilitiy, for instance, -could be written this way. -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -aa0724ca0a09f5b5e6c7e3f355646111 page03.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`" - test 345 -eq "$shar_count" || - $echo 'page03.pre:' 'original size' '345,' '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' && -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. -I have to say <I>(sub)network</I> because broadcast datagrams typically -are not passed through routers. So, if your network admin has divided -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 03191459100 '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' -8811bded669a7a7be85a4878d5076190 page04.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`" - test 481 -eq "$shar_count" || - $echo 'page04.pre:' 'original size' '481,' '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' && -<BR>That's it for this tutorial. In the next one we'll add some intelligence -to the data put into the datagrams. By doing so, we'll be able to -classify our clients and servers into groups. By combining the data -content and the server's port we can get fairly fine-grained control over -who talks to who. -X -<P>For you convenience: -<UL> -<LI> -<A HREF="server.cpp">server.cpp</A></LI> -X -<LI> -<A HREF="directed_client.cpp">directed_client.cpp</A></LI> -X -<LI> -<A HREF="broadcast_client.cpp">broadcast_client.cpp</A></LI> -X -<LI> -<A HREF="Makefile">Makefile</A></LI> -</UL> -SHAR_EOF - $shar_touch -am 03191459100 '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' -b05fdac8c7eb81813c74eb99525cf601 page05.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`" - test 578 -eq "$shar_count" || - $echo 'page05.pre:' 'original size' '578,' '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>And that's really all there is to it. Obviously there is some -room for improvement. The most blatant is the somewhat small buffer -size for receiving the datagram. I've never been able to get a solid -answer on datagram sizes. The theoretical limit is just under 64k -but you have to deal with fragmentation. Some readings indicate that -8k is a reasonable size, others go much smaller. My general rule -of thumb is to keep datagrams relatively small (eg -- under 8k or so) and -test a lot. If you find that your routers are fragmenting your larger -datagrams, back off to something smaller. Of course, if you must -send 100k and can only do so 1k at a time, you'll have to worry about retransmissions -& reordering. At that point, you might consider going to TCP. -Remember: datagrams are unreliable! Don't try to make 'em do -something they werent' designed for! -SHAR_EOF - $shar_touch -am 03191459100 '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' -3cb7da5f75a40616f6cc498a731f4a16 page02.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pst'`" - test 952 -eq "$shar_count" || - $echo 'page02.pst:' 'original size' '952,' '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>That's all neat and good but the point of what we're doing here is not -to talk to a server we know about but to discover servers we don't know -about. Now, you could send a directed datagram to every possible -host address on your network but that's not a very nice thing to do. -On the next page, we'll find out the right approach... -X -SHAR_EOF - $shar_touch -am 03191459100 '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' -0fcbc10be47175a0d42590fb4adab43b page03.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pst'`" - test 367 -eq "$shar_count" || - $echo 'page03.pst:' 'original size' '367,' '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> About that subnet thing: -<BLOCKQUOTE>If you run this client on a host that has multiple network -interfaces, the broadcast will go to all of those (sub)networks. -What do you do, though, if you need to get past a router? My advice -is to write a server that will run on hosts on both sides of your router. -When a server on one side of the router receives a broadcast, it would -send a directed datagram to it's counterpart on the other side of the router. -The counterpart would then re-broadcast the original datagram on that sub-net. -Cheap, simple and effective.</BLOCKQUOTE> -One final word of warning: -<BLOCKQUOTE>When creating your broadcast datagrams you may see something -like this: <I>ACE_SOCK_Dgram_Bcast::mk_broadcast: Broadcast is not -enable for this interface.: Unknown error</I>. There are some interfaces -(ppp, slip) that don't support broadcast datagrams. 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 response could come from any -one of them. -</blockquote> -X -SHAR_EOF - $shar_touch -am 03191459100 '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' -2e01fc6b6638dfa77ed629c0e3e77e21 page04.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pst'`" - test 1173 -eq "$shar_count" || - $echo 'page04.pst:' 'original size' '1173,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh32494 -exit 0 diff --git a/docs/tutorials/008/directed_client.cpp b/docs/tutorials/008/directed_client.cpp deleted file mode 100644 index d7c02f69dd3..00000000000 --- a/docs/tutorials/008/directed_client.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// $Id$ - -#include "ace/Log_Msg.h" -#include "ace/SOCK_Dgram.h" -#include "ace/INET_Addr.h" - -/* Once again, we use the default server port. In a "real" system, - the server's port (or ports) would be published in some way so that - clients would know where to "look". We could even add entries to - the operating system's services file and use a service name instead - of a number. We'll come back to that in some other tutorial - though. For now, let's stay simple. */ -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -/* Our goal here is to develop a client that can send a datagram to a - server running on a known host. We'll use a command-line argument - to specify the hostname instead of hard-coding it. */ -int -main (int argc,char *argv[]) -{ - /* All datagrams must have a point of origin. Since we intend to - transmit instead of receive, we initialize an address with zero - and let the OS choose a port for us. We could have chosen our own - value between 1025 and 65535 as long as it isn't already in use. - - The biggest difference between client and server when datagrams - are used is the fact that servers tend to have a known/fixed - address at which they listen and clients tend to have arbitrary - addresses assigned by the OS. */ - ACE_INET_Addr local((u_short) 0); - - /* And here is our datagram object. */ - ACE_SOCK_Dgram dgram; - - /* Notice that this looks a lot like the server application. - There's no difference in creating server datagrams an client - datagrams. You can even use a zero-constructed address for your - server datagram as long as you tell the client where you're - listening (eg -- by writting into a file or some such). */ - if (dgram.open (local) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "datagram open"), - -1); - - /* Yep. We've seen this before too... */ - char buf[BUFSIZ]; - - /* Ok, now we're doing something different. */ - sprintf (buf, "Hello World!"); - - /* Just like sending a telegram, we have to address our datagram. - Here, we create an address object at the desired port on the - chosen host. To keep us from crashing, we'll provide a default - host name if we aren't given one. */ - ACE_INET_Addr remote (PORT, - argc > 1 ? argv[1] : "localhost"); - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Sending (%s) to the server.\n", - buf)); - /* Now we send our buffer of stuff to the remote address. This is - just exactly what the server did after receiving a client message. - Datagrams are rather orthogonal that way: they don't generally - make much of a fuss about being either client or server. */ - if (dgram.send (buf, - ACE_OS::strlen (buf) + 1, - remote) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "send"), - -1); - - /* Now we've turned around and put ourselves into "server mode" by - invoking the recv() method. We know our server is going to send - us something, so we hang out here and wait for it. Because we - know datagrams are unreliable, there is a chance that the server - will respond but we won't hear. You might consider providing a - timeout on the recv() in that case. If recv() fails due to - timeout it will return -1 and you can then resend your query and - attempt the recv() again. - - Like the server application, we have to give the recv() an - uninitialized addr object so that we can find out who is talking - back to us. */ - if (dgram.recv (buf, - sizeof (buf), - remote) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "recv"), - -1); - - /* Find out what the server had to say. */ - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) The server said: %s\n", - buf)); - - /* Using the "remote" object instance, find out where the server - lives. We could then save this address and use directed datagrams - to chat with the server for a while. */ - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) The server can be found at: (%s:%d)\n", - remote.get_host_name(), - PORT)); - - return 0; -} diff --git a/docs/tutorials/008/page01.html b/docs/tutorials/008/page01.html deleted file mode 100644 index 602ccdbf4a5..00000000000 --- a/docs/tutorials/008/page01.html +++ /dev/null @@ -1,75 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 008</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 008</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sending and receiving datagrams</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>In a lot of IPC programming, the clients know where the servers -are. A mail client, for instance, has a configuration file that says -where the mail host is. Your web browser has a "location" field that -you type into to give it a destination. - -<P>What if you have written a server application and then you execute it -on several systems in your network? All of the instances are probably -more or less equal to the client's point of view, so you don't want to -"configure" the clients to a single server each. Likewise, you -want the ability to add and remove servers at any time so you can't just -give the clients a list to choose from. - -<P>So... how do the clients know where the servers are? - -<P>Let 'em ask! - -<P>Datagrams are great for this. You can toss a datagram out onto -the network and any servers listening at the correct port will* hear it. -Like ACE_SOCK_Stream that we've seen before, you can get the peer address -from a datagram. With that, the server can send a response -back to the client. The client, in turn, can pull the peer address -out and know exactly where the server lives. - -<P>In this tutorial we'll develop three applications: a server listening -for datagrams, a client that can send to a known host and a client that -can send to the entire (sub)network. In the next tutorial, we'll -expand on this to make the server a bit more prudish. -<P> -Kirthika's abstract: -<UL> -Here, we play with datagram sockets and use it for server discovery by -the client. Datagrams are used by UDP, which is an unreliable and -connectionless protocol. Datagrams packets are generally very small in -size and aren't designed to be used to handle serious communication -between the server and the client. -<P> -The server waits for datagrams to arrive at a fixed port. -The client either sends to a datagram to the server at a known host, -which is not really the case generally, as the client needs to discover -the server and so it needs to broadcast its datagram request in its -subnet. Then, all servers listening at that interface receive it. The -appropriate server will then handle the request. Remember that -no solid connection is made. On the recv() itself the server obtains the -address of the remote client and then communicates with it. -<P> -Thus, we get a fair glimpse of using another means of communication via -datagrams. -</UL> -<P><FONT SIZE=-1>* Actually, the servers <I>might</I> hear the datagram. -Datagrams are rather unreliable. (Sort of like some operating systems -I know.) Still, if the network traffic isn't too bad, they generally -get through. Your clients can always send out more queries if there -aren't any responses in a timely fashion.</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/008/page02.html b/docs/tutorials/008/page02.html deleted file mode 100644 index 67ee0e7c4f9..00000000000 --- a/docs/tutorials/008/page02.html +++ /dev/null @@ -1,164 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 008</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 008</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sending and receiving datagrams</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - - -<P>The first thing we want to look at is <A HREF="server.cpp">server.cpp</A>. -This is a pretty simple application that listens for datagrams at a known -port and sends back a response. In order to implement a true "discovery" -mechanism, the server will have to be a little bit more picky about who -it responds to. We'll tackle that issue in the next tutorial though... - -<P> -<HR WIDTH="100%"> -<PRE> -<font color=red>// $Id$</font> - -<font color=red>/* Our datagram server will, of course, need to create a datagram. - We'll also need an address object so that we know where to listen. -*/</font> -<font color=blue>#include</font> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Dgram.h">ace/SOCK_Dgram.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/INET_Addr.h">ace/INET_Addr.h</A>" - -<font color=red>/* Use the typical TCP/IP port address for receiving datagrams. */</font> -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -int -main (int, char**) -{ - <font color=red>/* This is where we'll listen for datagrams coming from the clients. - We'll give this address to the open() method below to enable the - listener. */</font> - ACE_INET_Addr local (PORT); - - <font color=red>/* A simply constructed datagram that we'll listen with. */</font> - ACE_SOCK_Dgram dgram; - - <font color=red>/* Like most ACE objects, the datagram has to be opened before it - can be uses. Of course, -1 on failure. - - A datagram will fail to open if there is already a datagram - listening at the port we've chosen. It *is* OK to open a datagram - at a port where there is an ACE_SOCK_Stream though. This is - because datagrams are UDP and SOCK_Stream is TCP and the two don't - cross paths. */</font> - if (dgram.open (local) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>open</font>"), - -1); - - <font color=red>/* Create a simple buffer to receive the data. You generally need - to provide a buffer big enough for the largest datagram you expect - to receive. Some platforms will let you read a little and then - some more later but other platforms will throw out whatever part - of the datagram you don't get with the first read. (This is on a - per-datagram basis BTW.) The theoretical limit on a datagram is - about 64k. The realistic limit (because of routers & such) is - much smaller. Choose your buffer size based on your application's - needs. */</font> - char buf[BUFSIZ]; - - <font color=red>/* Unlike ACE_SOCK_Stream, datagrams are unconnected. That is, - there is no "<font color=green>virtual circuit</font>" between server and client. Because - of this, the server has to provide a placeholder for the OS to - fill in the source (client) address information on the recv. You - can initialize this INET_Addr to anything, it will be overwritten - when the data arrives. */</font> - ACE_INET_Addr remote; - - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) starting up server daemon\n</font>")); - - <font color=red>/* Receive datagrams as long as we're able. */</font> - while (dgram.recv (buf, - sizeof (buf), - remote) != -1) - { - <font color=red>/* Display a brief message about our progress. Notice how we - use the 'remote' object to display the address of the client. - With an ACE_SOCK_Stream we used get_remote_addr() to get the - address the socket is connected to. Because datagrams are - unconnected, we use the addr object provided to recv(). */</font> - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) Data (%s) from client (%s)\n</font>", - buf, - remote.get_host_name ())); - - <font color=red>/* To respond to the client's query, we have to become a client - ourselves. To do so, we need an anonymous local address from - which we'll send the response and a datagram in which to send - it. (An anonymous address is simply one where we let the OS - choose a port for us. We really don't care what it is. */</font> - ACE_INET_Addr local ((u_short) 0); - ACE_SOCK_Dgram client; - - <font color=red>/* Open up our response datagram as always. */</font> - if (client.open (local) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>client open</font>"), - -1); - return 0; - } - - <font color=red>/* Build a witty response... */</font> - sprintf (buf, - "<font color=green>I am here</font>"); - - <font color=red>/* and send it to the client. Notice the symmetry with the - recv() method. Again, the unconnected nature of datagrams - forces us to specify an address object with each read/write - operation. In the case of read (recv()) that's where the OS - stuffs the address of the datagram sender. In the case of - write (send()) that we're doing here, the address is where we - want the network to deliver the data. - - Of course, we're assuming that the client will be listening - for our reply... */</font> - if (client.send (buf, - <font color=#008888>ACE_OS::strlen</font> (buf) + 1, - remote) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>send</font>"), - -1); - } - - return 0; -} -</PRE> -<HR WIDTH="100%"> - -<P>And that's really all there is to it. Obviously there is some -room for improvement. The most blatant is the somewhat small buffer -size for receiving the datagram. I've never been able to get a solid -answer on datagram sizes. The theoretical limit is just under 64k -but you have to deal with fragmentation. Some readings indicate that -8k is a reasonable size, others go much smaller. My general rule -of thumb is to keep datagrams relatively small (eg -- under 8k or so) and -test a lot. If you find that your routers are fragmenting your larger -datagrams, back off to something smaller. Of course, if you must -send 100k and can only do so 1k at a time, you'll have to worry about retransmissions -& reordering. At that point, you might consider going to TCP. -Remember: datagrams are unreliable! Don't try to make 'em do -something they werent' designed for! -<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/008/page03.html b/docs/tutorials/008/page03.html deleted file mode 100644 index 04878414762..00000000000 --- a/docs/tutorials/008/page03.html +++ /dev/null @@ -1,148 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 008</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 008</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sending and receiving datagrams</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - - -<P>In <A HREF="directed_client.cpp">directed_client.cpp</A> we create a -client that knows how to send a datagram to a server on a known host. -This is a good thing if you know where the server lives and want to have -a conversation. The Unix <I>talk</I> utilitiy, for instance, -could be written this way. - -<P> -<HR WIDTH="100%"> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Dgram.h">ace/SOCK_Dgram.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/INET_Addr.h">ace/INET_Addr.h</A>" - -<font color=red>/* Once again, we use the default server port. In a "<font color=green>real</font>" system, - the server's port (or ports) would be published in some way so that - clients would know where to "<font color=green>look</font>". We could even add entries to - the operating system's services file and use a service name instead - of a number. We'll come back to that in some other tutorial - though. For now, let's stay simple. */</font> -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -<font color=red>/* Our goal here is to develop a client that can send a datagram to a - server running on a known host. We'll use a command-line argument - to specify the hostname instead of hard-coding it. */</font> -int -main (int argc,char *argv[]) -{ - <font color=red>/* All datagrams must have a point of origin. Since we intend to - transmit instead of receive, we initialize an address with zero - and let the OS choose a port for us. We could have chosen our own - value between 1025 and 65535 as long as it isn't already in use. - - The biggest difference between client and server when datagrams - are used is the fact that servers tend to have a known/fixed - address at which they listen and clients tend to have arbitrary - addresses assigned by the OS. */</font> - ACE_INET_Addr local((u_short) 0); - - <font color=red>/* And here is our datagram object. */</font> - ACE_SOCK_Dgram dgram; - - <font color=red>/* Notice that this looks a lot like the server application. - There's no difference in creating server datagrams an client - datagrams. You can even use a zero-constructed address for your - server datagram as long as you tell the client where you're - listening (eg -- by writting into a file or some such). */</font> - if (dgram.open (local) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>datagram open</font>"), - -1); - - <font color=red>/* Yep. We've seen this before too... */</font> - char buf[BUFSIZ]; - - <font color=red>/* Ok, now we're doing something different. */</font> - sprintf (buf, "<font color=green>Hello World!</font>"); - - <font color=red>/* Just like sending a telegram, we have to address our datagram. - Here, we create an address object at the desired port on the - chosen host. To keep us from crashing, we'll provide a default - host name if we aren't given one. */</font> - ACE_INET_Addr remote (PORT, - argc > 1 ? argv[1] : "<font color=green>localhost</font>"); - - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) Sending (%s) to the server.\n</font>", - buf)); - <font color=red>/* Now we send our buffer of stuff to the remote address. This is - just exactly what the server did after receiving a client message. - Datagrams are rather orthogonal that way: they don't generally - make much of a fuss about being either client or server. */</font> - if (dgram.send (buf, - <font color=#008888>ACE_OS::strlen</font> (buf) + 1, - remote) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>send</font>"), - -1); - - <font color=red>/* Now we've turned around and put ourselves into "<font color=green>server mode</font>" by - invoking the recv() method. We know our server is going to send - us something, so we hang out here and wait for it. Because we - know datagrams are unreliable, there is a chance that the server - will respond but we won't hear. You might consider providing a - timeout on the recv() in that case. If recv() fails due to - timeout it will return -1 and you can then resend your query and - attempt the recv() again. - - Like the server application, we have to give the recv() an - uninitialized addr object so that we can find out who is talking - back to us. */</font> - if (dgram.recv (buf, - sizeof (buf), - remote) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>recv</font>"), - -1); - - <font color=red>/* Find out what the server had to say. */</font> - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) The server said: %s\n</font>", - buf)); - - <font color=red>/* Using the "<font color=green>remote</font>" object instance, find out where the server - lives. We could then save this address and use directed datagrams - to chat with the server for a while. */</font> - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) The server can be found at: (%s:%d)\n</font>", - remote.get_host_name(), - PORT)); - - return 0; -} -</PRE> -<HR WIDTH="100%"> - -<P>That's all neat and good but the point of what we're doing here is not -to talk to a server we know about but to discover servers we don't know -about. Now, you could send a directed datagram to every possible -host address on your network but that's not a very nice thing to do. -On the next page, we'll find out the right approach... - -<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/008/page04.html b/docs/tutorials/008/page04.html deleted file mode 100644 index ec24576e73b..00000000000 --- a/docs/tutorials/008/page04.html +++ /dev/null @@ -1,139 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 008</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 008</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sending and receiving datagrams</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -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. -I have to say <I>(sub)network</I> because broadcast datagrams typically -are not passed through routers. So, if your network admin has divided -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. -<HR WIDTH="100%"> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Dgram_Bcast.h">ace/SOCK_Dgram_Bcast.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/INET_Addr.h">ace/INET_Addr.h</A>" - -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -int -main (int argc,char *argv[]) -{ - ACE_UNUSED_ARG(argc); - ACE_UNUSED_ARG(argv); - - ACE_INET_Addr local ((u_short) 0); - - <font color=red>/* Instead of creating the ACE_SOCK_Dgram we created last time, - we'll create an ACE_SOCK_Dgram_Bcast. "<font color=green>Bcast</font>" means, of course, - "<font color=green>Broadcast</font>". This ACE object is clever enough to go out to the OS - and find all of the network interfaces. When you send() on a - Dgram_Bcast, it will send the datagram out on all of those - interfaces. This is quiet handy if you do it on a multi-homed - host that plays router... */</font> - ACE_SOCK_Dgram_Bcast dgram; - - if (dgram.open (local) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>datagram open</font>"), - -1); - - char buf[BUFSIZ]; - - sprintf (buf, "<font color=green>Hello World!</font>"); - - <font color=red>/* The only other difference between us and the directed client is - that we don't specify a host to receive the datagram. Instead, we - use the magic value "<font color=green>INADDR_BROADCAST</font>". All hosts are obliged to - respond to datagrams directed to this address the same as they - would to datagrams sent to their hostname. - - Remember, the Dgram_Bcast will send a datagram to all interfaces - on the host. That's true even if the address is for a specific - host (and the host address makes sense for the interface). The - real power is in using an INADDR_BROADCAST addressed datagram - against all interfaces. */</font> - - ACE_INET_Addr remote (PORT, - INADDR_BROADCAST); - - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) Sending (%s) to the server.\n</font>", - buf)); - - if (dgram.send (buf, - <font color=#008888>ACE_OS::strlen</font> (buf) + 1, - remote) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>send</font>"), - -1); - - if (dgram.recv (buf, - sizeof (buf), - remote) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>recv</font>"), - -1); - - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) The server said: %s\n</font>", - buf)); - - <font color=red>/* Using the "<font color=green>remote</font>" object instance, find out where the server - lives. We could then save this address and use directed datagrams - to chat with the server for a while. */</font> - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) The server can be found at: (%s:%d)\n</font>", - remote.get_host_name(), - PORT)); - - return 0; -} -</PRE> -<HR WIDTH="100%"> - -<P> About that subnet thing: -<BLOCKQUOTE>If you run this client on a host that has multiple network -interfaces, the broadcast will go to all of those (sub)networks. -What do you do, though, if you need to get past a router? My advice -is to write a server that will run on hosts on both sides of your router. -When a server on one side of the router receives a broadcast, it would -send a directed datagram to it's counterpart on the other side of the router. -The counterpart would then re-broadcast the original datagram on that sub-net. -Cheap, simple and effective.</BLOCKQUOTE> -One final word of warning: -<BLOCKQUOTE>When creating your broadcast datagrams you may see something -like this: <I>ACE_SOCK_Dgram_Bcast::mk_broadcast: Broadcast is not -enable for this interface.: Unknown error</I>. There are some interfaces -(ppp, slip) that don't support broadcast datagrams. 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 response 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/008/page05.html b/docs/tutorials/008/page05.html deleted file mode 100644 index 63fa5943440..00000000000 --- a/docs/tutorials/008/page05.html +++ /dev/null @@ -1,41 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 008</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 008</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sending and receiving datagrams</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<BR>That's it for this tutorial. In the next one we'll add some intelligence -to the data put into the datagrams. By doing so, we'll be able to -classify our clients and servers into groups. By combining the data -content and the server's port we can get fairly fine-grained control over -who talks to who. - -<P>For you convenience: -<UL> -<LI> -<A HREF="server.cpp">server.cpp</A></LI> - -<LI> -<A HREF="directed_client.cpp">directed_client.cpp</A></LI> - -<LI> -<A HREF="broadcast_client.cpp">broadcast_client.cpp</A></LI> - -<LI> -<A HREF="Makefile">Makefile</A></LI> -</UL> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/008/server.cpp b/docs/tutorials/008/server.cpp deleted file mode 100644 index 7cacb040822..00000000000 --- a/docs/tutorials/008/server.cpp +++ /dev/null @@ -1,116 +0,0 @@ -// $Id$ - -/* Our datagram server will, of course, need to create a datagram. - We'll also need an address object so that we know where to listen. */ -#include "ace/Log_Msg.h" -#include "ace/SOCK_Dgram.h" -#include "ace/INET_Addr.h" - -/* Use the typical TCP/IP port address for receiving datagrams. */ -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -int -main (int, char**) -{ - /* This is where we'll listen for datagrams coming from the clients. - We'll give this address to the open() method below to enable the - listener. */ - ACE_INET_Addr local (PORT); - - /* A simply constructed datagram that we'll listen with. */ - ACE_SOCK_Dgram dgram; - - /* Like most ACE objects, the datagram has to be opened before it - can be uses. Of course, -1 on failure. - - A datagram will fail to open if there is already a datagram - listening at the port we've chosen. It *is* OK to open a datagram - at a port where there is an ACE_SOCK_Stream though. This is - because datagrams are UDP and SOCK_Stream is TCP and the two don't - cross paths. */ - if (dgram.open (local) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "open"), - -1); - - /* Create a simple buffer to receive the data. You generally need - to provide a buffer big enough for the largest datagram you expect - to receive. Some platforms will let you read a little and then - some more later but other platforms will throw out whatever part - of the datagram you don't get with the first read. (This is on a - per-datagram basis BTW.) The theoretical limit on a datagram is - about 64k. The realistic limit (because of routers & such) is - much smaller. Choose your buffer size based on your application's - needs. */ - char buf[BUFSIZ]; - - /* Unlike ACE_SOCK_Stream, datagrams are unconnected. That is, - there is no "virtual circuit" between server and client. Because - of this, the server has to provide a placeholder for the OS to - fill in the source (client) address information on the recv. You - can initialize this INET_Addr to anything, it will be overwritten - when the data arrives. */ - ACE_INET_Addr remote; - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) starting up server daemon\n")); - - /* Receive datagrams as long as we're able. */ - while (dgram.recv (buf, - sizeof (buf), - remote) != -1) - { - /* Display a brief message about our progress. Notice how we - use the 'remote' object to display the address of the client. - With an ACE_SOCK_Stream we used get_remote_addr() to get the - address the socket is connected to. Because datagrams are - unconnected, we use the addr object provided to recv(). */ - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Data (%s) from client (%s)\n", - buf, - remote.get_host_name ())); - - /* To respond to the client's query, we have to become a client - ourselves. To do so, we need an anonymous local address from - which we'll send the response and a datagram in which to send - it. (An anonymous address is simply one where we let the OS - choose a port for us. We really don't care what it is. */ - ACE_INET_Addr local ((u_short) 0); - ACE_SOCK_Dgram client; - - /* Open up our response datagram as always. */ - if (client.open (local) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "client open"), - -1); - return 0; - } - - /* Build a witty response... */ - sprintf (buf, - "I am here"); - - /* and send it to the client. Notice the symmetry with the - recv() method. Again, the unconnected nature of datagrams - forces us to specify an address object with each read/write - operation. In the case of read (recv()) that's where the OS - stuffs the address of the datagram sender. In the case of - write (send()) that we're doing here, the address is where we - want the network to deliver the data. - - Of course, we're assuming that the client will be listening - for our reply... */ - if (client.send (buf, - ACE_OS::strlen (buf) + 1, - remote) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "send"), - -1); - } - - return 0; -} diff --git a/docs/tutorials/009/009-broadcast.dsp b/docs/tutorials/009/009-broadcast.dsp deleted file mode 100644 index 14867d087a4..00000000000 --- a/docs/tutorials/009/009-broadcast.dsp +++ /dev/null @@ -1,102 +0,0 @@ -# Microsoft Developer Studio Project File - Name="009 broadcast" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=009 broadcast - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "009-broadcast.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "009-broadcast.mak" CFG="009 broadcast - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "009 broadcast - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "009 broadcast - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "009 broadcast - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "009 broadcast - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"../broadcast_client.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "009 broadcast - Win32 Release"
-# Name "009 broadcast - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=broadcast_client.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/009/009-directed.dsp b/docs/tutorials/009/009-directed.dsp deleted file mode 100644 index a2d80670af8..00000000000 --- a/docs/tutorials/009/009-directed.dsp +++ /dev/null @@ -1,102 +0,0 @@ -# Microsoft Developer Studio Project File - Name="009 directed" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=009 directed - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "009-directed.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "009-directed.mak" CFG="009 directed - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "009 directed - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "009 directed - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "009 directed - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "009 directed - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"../directed_client.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "009 directed - Win32 Release"
-# Name "009 directed - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=directed_client.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/009/009-server.dsp b/docs/tutorials/009/009-server.dsp deleted file mode 100644 index 051b3e9f357..00000000000 --- a/docs/tutorials/009/009-server.dsp +++ /dev/null @@ -1,102 +0,0 @@ -# Microsoft Developer Studio Project File - Name="009 server" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=009 server - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "009-server.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "009-server.mak" CFG="009 server - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "009 server - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "009 server - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "009 server - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "009 server - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"../server.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "009 server - Win32 Release"
-# Name "009 server - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=server.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/009/Makefile b/docs/tutorials/009/Makefile deleted file mode 100644 index b595ecbc814..00000000000 --- a/docs/tutorials/009/Makefile +++ /dev/null @@ -1,74 +0,0 @@ -#---------------------------------------------------------------------------- -# $Id$ -#---------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = server directed_client broadcast_client - -FILES = - -BUILD = $(VBIN) - -HDR = *.h - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -bli0 -l80 -fca -fc1 -cli0 -cdb < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - -Depend : depend - perl ../fix.Makefile - -.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) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - - # Don't put anything below here. Between the "depend" target and fix.Makefile - # it's guaranteed to be lost! - - # This is inserted by the fix.Makefile script -include .depend diff --git a/docs/tutorials/009/broadcast_client.cpp b/docs/tutorials/009/broadcast_client.cpp deleted file mode 100644 index 7eb282f6f73..00000000000 --- a/docs/tutorials/009/broadcast_client.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// $Id$ - -#include "ace/Log_Msg.h" -#include "ace/SOCK_Dgram_Bcast.h" -#include "ace/INET_Addr.h" - -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -int -main (int argc, char *argv[]) -{ - ACE_INET_Addr local ((u_short) 0); - ACE_INET_Addr remote (PORT, INADDR_BROADCAST); - ACE_SOCK_Dgram_Bcast dgram; - - if (dgram.open (local) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "open"), - -1); - char buf[BUFSIZ]; - - sprintf (buf, - argc > 1 ? argv[1] : "Hello World!"); - if (dgram.send (buf, - ACE_OS::strlen (buf) + 1, - remote) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "send"), - -1); - ACE_Time_Value timeout (2, 0); - if (dgram.recv (buf, - sizeof (buf), - remote, - 0, - &timeout) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "recv"), - -1); - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) The server at (%s) said (%s)\n", - remote.get_host_name (), - buf)); - return 0; -} diff --git a/docs/tutorials/009/combine.shar b/docs/tutorials/009/combine.shar deleted file mode 100644 index e0b7604a183..00000000000 --- a/docs/tutorials/009/combine.shar +++ /dev/null @@ -1,394 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/009'. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 520 -rw-rw-r-- hdr -# 59 -rw-rw-r-- bodies -# 2184 -rw-rw-r-- page01.pre -# 188 -rw-rw-r-- page02.pre -# 296 -rw-rw-r-- page03.pre -# 301 -rw-rw-r-- page04.pre -# 995 -rw-rw-r-- page05.pre -# 81 -rw-rw-r-- page02.pst -# 96 -rw-rw-r-- page03.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 _sh32524; 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 <TITLE>ACE Tutorial 009</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> -X -<CENTER><B><FONT SIZE=+2>ACE Tutorial 009</FONT></B></CENTER> -X -<CENTER><B><FONT SIZE=+2>Sending and receiving datagrams again</FONT></B></CENTER> -X -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -808b7f288617f5b0a55256542f242912 hdr -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`" - test 520 -eq "$shar_count" || - $echo 'hdr:' 'original size' '520,' '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 -directed_client.cpp -broadcast_client.cpp -SHAR_EOF - $shar_touch -am 0121195199 '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' -707d1735ca25694e2b5fddc1f6e7e124 bodies -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`" - test 59 -eq "$shar_count" || - $echo 'bodies:' 'original size' '59,' '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 our previous tutorial, we created a datagram listener and a couple -of clients that would send it datagrams. That server would respond -to any datagram sent to the TCP/IP port at which the server was listening. -What we really want to do, however, is to have the server only respond -to clients that meet some criteria. -X -<P>Why is this important? -X -<P>Imagine you're writting a distributed system that will have many server -applications. Each of those will probably listen at different (and -well-known) TCP/IP addresses so that clients can find each server -without confusion. However... In a large system you might have -several <I>versions</I> of the same server running at the same time*. -You probably don't want those servers running at different addresses since -that breaks the well-known address requirement. -X -<P>By creating a datagram listener similar to the last tutorial, a client -can send broadcast datagrams to locate all of the servers listening at -the well-known address. By adding a thin protocol layer into -the datagram contents, the servers can be selective about which clients -they respond to. Thus, if each client sends its version signature -in the broadcast, then the servers can choose to respond only to clients -with matching versions. -<P> -Kirthika's Abstract: -<UL> -Here, the client uses datagrams for discovery of the server in the -subnet and also sends a signature for authentification. The server -decides on replying to the client depending on the signature. The only -changes from the previous tutorial are in the addition of an extra -signature matching portion on the server side and providing timeout -values on the client side which allows the send() and recv() calls to -return on a timeout if the target party fails to respond. -<P> -This feature of discrimnation depending on the client signature could be -used for security reasons or version confirmation by the server. -</UL> -<P><FONT SIZE=-1>*Note: I'm making the assumption that your multiple -server versions will be running on different hosts since you can only have -one server listening at the well-known address on a given host.</FONT> -X -SHAR_EOF - $shar_touch -am 03191459100 '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' -fa884a9f35740c89bf25c5eed9ba1ebd page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 2184 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '2184,' '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 -<P>Let's take a look at our new <A HREF="server.cpp">server.cpp</A> where -we add in just a bit of code to examine the datagram contents before responding. -X -<P> -<HR WIDTH="100%"><TT></TT> -SHAR_EOF - $shar_touch -am 03191459100 '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' -76a728cf5d0f42ca9b7d7a6fa0637384 page02.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`" - test 188 -eq "$shar_count" || - $echo 'page02.pre:' 'original size' '188,' '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 -<P>Our new <A HREF="directed_client.cpp">directed_client.cpp</A> -is very much like our previous one. The primary difference is the -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. -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -c89d6d6f4acee2953a95469a3fe6965f page03.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`" - test 296 -eq "$shar_count" || - $echo 'page03.pre:' 'original size' '296,' '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 -<P>As you can see in <A HREF="broadcast_client.cpp">broadcast_client.cpp</A>, -there isn't enough difference to even comment on! Look back to the -Tutorial 8 version of this file. The only difference is the addition -of the timeout variable passed to recv(). -X -<P> -<HR WIDTH="100%"><TT></TT> -SHAR_EOF - $shar_touch -am 03191459100 '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' -8c92e7ef51e85491bc2d7991a5b62cbb page04.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`" - test 301 -eq "$shar_count" || - $echo 'page04.pre:' 'original size' '301,' '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' && -In this tutorial we've expanded on Tutorial 8 to provide a more discriminating -server application. The changes to the clients were trivial, amounting -to not much more than the addition of a timeout when reading a server's -potential response. The server change was a bit more since it had -to compare the clients' query with it's own signature. -X -<P>In a "real" system, the signatures you swap would probably include version -information. You could even use a major/minor scheme where an exact -match isn't necessary. Another upgrade might be to have a set of -signatures at one or both ends of the conversation. The level of -service provided by the server would be determined by the signature pair -match. -X -<P>Here's the final file list: -<UL> -<LI> -<A HREF="Makefile">Makefile</A></LI> -X -<LI> -<A HREF="server.cpp">server.cpp</A></LI> -X -<LI> -<A HREF="directed_client.cpp">directed_client.cpp</A></LI> -X -<LI> -<A HREF="broadcast_client.cpp">broadcast_client.cpp</A></LI> -</UL> -X -SHAR_EOF - $shar_touch -am 03191459100 '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' -835e97e1b6ac1747ef9508936a56a6cc page05.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`" - test 995 -eq "$shar_count" || - $echo 'page05.pre:' 'original size' '995,' '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 on and see what changes the clients require... -X -SHAR_EOF - $shar_touch -am 03191459100 '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' -76a64b9c5c1d1baa1425085b1649fb31 page02.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pst'`" - test 81 -eq "$shar_count" || - $echo 'page02.pst:' 'original size' '81,' '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>On the next page, we see that the directed_client gets similar upgrades. -X -SHAR_EOF - $shar_touch -am 03191459100 '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' -11fda077df9a3ef7155f33e75cc9b6b6 page03.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pst'`" - test 96 -eq "$shar_count" || - $echo 'page03.pst:' 'original size' '96,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh32524 -exit 0 diff --git a/docs/tutorials/009/directed_client.cpp b/docs/tutorials/009/directed_client.cpp deleted file mode 100644 index 7ec65ee23ff..00000000000 --- a/docs/tutorials/009/directed_client.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// $Id$ - -#include "ace/Log_Msg.h" -#include "ace/SOCK_Dgram.h" -#include "ace/INET_Addr.h" - -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -int -main (int argc, char *argv[]) -{ - ACE_INET_Addr local ((u_short) 0); - ACE_INET_Addr remote (PORT, - argc > 1 ? argv[1] : "localhost"); - ACE_SOCK_Dgram dgram; - - if (dgram.open (local) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "open"), - -1); - - char buf[BUFSIZ]; - - /* In order to conform to the "protocol" required by the server, we - allow the user to specify a signature. A default matching the - server's default is also available. */ - sprintf (buf, - argc > 2 ? argv[2] : "Hello World!"); - - if (dgram.send (buf, - ACE_OS::strlen (buf) + 1, - remote) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "send"), - -1); - - /* Because we may have sent a signature that the server doesn't - honor, we have to have some way to get out of the recv(). Most - ACE objects that have potential for infinite blocking give you the - option of providing a timeout. recv() is no exception. Here, we - construct an ACE_Time_Value representing two seconds and no - micro-seconds. If recv() fails to get a response within the two - seconds, it will return -1. */ - ACE_Time_Value timeout (2, 0); - if (dgram.recv (buf, - sizeof (buf), - remote, - 0, - &timeout) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "recv"), - -1); - - /* Note: The fourth parameter to recv() is for flags. These flags - are passed directly to the underlying recv() or recvfrom() system - call. For Linux, resonable values are: MSG_OOB process - out-of-band data MSG_PEEK peek at incoming message (but leave it - in the OS buffers) MSG_WAITALL wait for full request or error See - your system documentation for the gory details. */ - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) The server said (%s)\n", - buf)); - - return 0; -} diff --git a/docs/tutorials/009/page01.html b/docs/tutorials/009/page01.html deleted file mode 100644 index cf6d5f38515..00000000000 --- a/docs/tutorials/009/page01.html +++ /dev/null @@ -1,62 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 009</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 009</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sending and receiving datagrams again</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>In our previous tutorial, we created a datagram listener and a couple -of clients that would send it datagrams. That server would respond -to any datagram sent to the TCP/IP port at which the server was listening. -What we really want to do, however, is to have the server only respond -to clients that meet some criteria. - -<P>Why is this important? - -<P>Imagine you're writting a distributed system that will have many server -applications. Each of those will probably listen at different (and -well-known) TCP/IP addresses so that clients can find each server -without confusion. However... In a large system you might have -several <I>versions</I> of the same server running at the same time*. -You probably don't want those servers running at different addresses since -that breaks the well-known address requirement. - -<P>By creating a datagram listener similar to the last tutorial, a client -can send broadcast datagrams to locate all of the servers listening at -the well-known address. By adding a thin protocol layer into -the datagram contents, the servers can be selective about which clients -they respond to. Thus, if each client sends its version signature -in the broadcast, then the servers can choose to respond only to clients -with matching versions. -<P> -Kirthika's Abstract: -<UL> -Here, the client uses datagrams for discovery of the server in the -subnet and also sends a signature for authentification. The server -decides on replying to the client depending on the signature. The only -changes from the previous tutorial are in the addition of an extra -signature matching portion on the server side and providing timeout -values on the client side which allows the send() and recv() calls to -return on a timeout if the target party fails to respond. -<P> -This feature of discrimnation depending on the client signature could be -used for security reasons or version confirmation by the server. -</UL> -<P><FONT SIZE=-1>*Note: I'm making the assumption that your multiple -server versions will be running on different hosts since you can only have -one server listening at the well-known address on a given host.</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/009/page02.html b/docs/tutorials/009/page02.html deleted file mode 100644 index 438f580c32a..00000000000 --- a/docs/tutorials/009/page02.html +++ /dev/null @@ -1,113 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 009</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 009</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sending and receiving datagrams again</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>Let's take a look at our new <A HREF="server.cpp">server.cpp</A> where -we add in just a bit of code to examine the datagram contents before responding. - -<P> -<HR WIDTH="100%"><TT></TT> -<PRE> -<font color=red>// $Id$</font> - -<font color=red>/* The actual datagram operations here are exactly the same as those - used in the previous tutorial. What we've added is some logic that - will prevent this server from responding to just any old datagram. - I'll limit my comments to those pieces of code. */</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Dgram.h">ace/SOCK_Dgram.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/INET_Addr.h">ace/INET_Addr.h</A>" - -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -<font color=red>/* In order to be more selective, our server will be started with a - "<font color=green>signature</font>". If none is given, we'll use the one here instead. */</font> -static const char *default_signature = "<font color=green>Hello World!</font>"; - -int -main (int argc, char *argv[]) -{ - ACE_INET_Addr local (PORT); - ACE_SOCK_Dgram dgram; - - if (dgram.open (local) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>open</font>"), - -1); - - char buf[BUFSIZ]; - ACE_INET_Addr remote; - - while (dgram.recv (buf, - sizeof (buf), - remote) != -1) - { - <font color=red>/* What did the client say? */</font> - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) Received (%s) from (%s)\n</font>", - buf, - remote.get_host_name ())); - - <font color=red>/* Use a simple string-op to decide if the client is one of our - own. Of course, you could have sent numeric values or even a - struct of data. For this simple exercise, however, strings are - just fine. */</font> - if (<font color=#008888>ACE_OS::strcmp</font> (buf, - argc > 1 ? argv[1] : default_signature)) - { - <font color=red>/* If the client didn't say something we like then log it - * and move on. - */</font> - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) Client query does not match our signature (%s). Response not sent.\n</font>", - argc > 1 ? argv[1] : default_signature)); - } - else - { - <font color=red>/* As before, we respond to the client's query. */</font> - - ACE_INET_Addr local ((u_short) 0); - ACE_SOCK_Dgram peer; - if (peer.open (local) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>response open</font>"), - -1); - sprintf (buf, - "<font color=green>I am here</font>"); - if (peer.send (buf, - <font color=#008888>ACE_OS::strlen</font> (buf) + 1, - remote) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>response send</font>"), - -1); - } - } - - return 0; -} -</PRE> -<HR WIDTH="100%"> - -<P>Let's move on and see what changes the clients require... - -<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/009/page03.html b/docs/tutorials/009/page03.html deleted file mode 100644 index 8f138282c1b..00000000000 --- a/docs/tutorials/009/page03.html +++ /dev/null @@ -1,103 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 009</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 009</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sending and receiving datagrams again</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>Our new <A HREF="directed_client.cpp">directed_client.cpp</A> -is very much like our previous one. The primary difference is the -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> -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Dgram.h">ace/SOCK_Dgram.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/INET_Addr.h">ace/INET_Addr.h</A>" - -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -int -main (int argc, char *argv[]) -{ - ACE_INET_Addr local ((u_short) 0); - ACE_INET_Addr remote (PORT, - argc > 1 ? argv[1] : "<font color=green>localhost</font>"); - ACE_SOCK_Dgram dgram; - - if (dgram.open (local) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>open</font>"), - -1); - - char buf[BUFSIZ]; - - <font color=red>/* In order to conform to the "<font color=green>protocol</font>" required by the server, we - allow the user to specify a signature. A default matching the - server's default is also available. */</font> - sprintf (buf, - argc > 2 ? argv[2] : "<font color=green>Hello World!</font>"); - - if (dgram.send (buf, - <font color=#008888>ACE_OS::strlen</font> (buf) + 1, - remote) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>send</font>"), - -1); - - <font color=red>/* Because we may have sent a signature that the server doesn't - honor, we have to have some way to get out of the recv(). Most - ACE objects that have potential for infinite blocking give you the - option of providing a timeout. recv() is no exception. Here, we - construct an ACE_Time_Value representing two seconds and no - micro-seconds. If recv() fails to get a response within the two - seconds, it will return -1. */</font> - ACE_Time_Value timeout (2, 0); - if (dgram.recv (buf, - sizeof (buf), - remote, - 0, - &timeout) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>recv</font>"), - -1); - - <font color=red>/* Note: The fourth parameter to recv() is for flags. These flags - are passed directly to the underlying recv() or recvfrom() system - call. For Linux, resonable values are: MSG_OOB process - out-of-band data MSG_PEEK peek at incoming message (but leave it - in the OS buffers) MSG_WAITALL wait for full request or error See - your system documentation for the gory details. */</font> - - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) The server said (%s)\n</font>", - buf)); - - return 0; -} -</PRE> -<HR WIDTH="100%"> - -<P>On the next page, we see that the directed_client gets similar upgrades. - -<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/009/page04.html b/docs/tutorials/009/page04.html deleted file mode 100644 index 9148829167e..00000000000 --- a/docs/tutorials/009/page04.html +++ /dev/null @@ -1,77 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 009</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 009</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sending and receiving datagrams again</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -<P>As you can see in <A HREF="broadcast_client.cpp">broadcast_client.cpp</A>, -there isn't enough difference to even comment on! Look back to the -Tutorial 8 version of this file. The only difference is the addition -of the timeout variable passed to recv(). - -<P> -<HR WIDTH="100%"><TT></TT> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Dgram_Bcast.h">ace/SOCK_Dgram_Bcast.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/INET_Addr.h">ace/INET_Addr.h</A>" - -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -int -main (int argc, char *argv[]) -{ - ACE_INET_Addr local ((u_short) 0); - ACE_INET_Addr remote (PORT, INADDR_BROADCAST); - ACE_SOCK_Dgram_Bcast dgram; - - if (dgram.open (local) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>open</font>"), - -1); - char buf[BUFSIZ]; - - sprintf (buf, - argc > 1 ? argv[1] : "<font color=green>Hello World!</font>"); - if (dgram.send (buf, - <font color=#008888>ACE_OS::strlen</font> (buf) + 1, - remote) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>send</font>"), - -1); - ACE_Time_Value timeout (2, 0); - if (dgram.recv (buf, - sizeof (buf), - remote, - 0, - &timeout) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>recv</font>"), - -1); - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) The server at (%s) said (%s)\n</font>", - remote.get_host_name (), - buf)); - return 0; -} -</PRE> -<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/page05.html b/docs/tutorials/009/page05.html deleted file mode 100644 index 6defc777d51..00000000000 --- a/docs/tutorials/009/page05.html +++ /dev/null @@ -1,48 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 009</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 009</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sending and receiving datagrams again</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -In this tutorial we've expanded on Tutorial 8 to provide a more discriminating -server application. The changes to the clients were trivial, amounting -to not much more than the addition of a timeout when reading a server's -potential response. The server change was a bit more since it had -to compare the clients' query with it's own signature. - -<P>In a "real" system, the signatures you swap would probably include version -information. You could even use a major/minor scheme where an exact -match isn't necessary. Another upgrade might be to have a set of -signatures at one or both ends of the conversation. The level of -service provided by the server would be determined by the signature pair -match. - -<P>Here's the final file list: -<UL> -<LI> -<A HREF="Makefile">Makefile</A></LI> - -<LI> -<A HREF="server.cpp">server.cpp</A></LI> - -<LI> -<A HREF="directed_client.cpp">directed_client.cpp</A></LI> - -<LI> -<A HREF="broadcast_client.cpp">broadcast_client.cpp</A></LI> -</UL> - -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/009/server.cpp b/docs/tutorials/009/server.cpp deleted file mode 100644 index ee6dc1be311..00000000000 --- a/docs/tutorials/009/server.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// $Id$ - -/* The actual datagram operations here are exactly the same as those - used in the previous tutorial. What we've added is some logic that - will prevent this server from responding to just any old datagram. - I'll limit my comments to those pieces of code. */ - -#include "ace/Log_Msg.h" -#include "ace/SOCK_Dgram.h" -#include "ace/INET_Addr.h" - -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -/* In order to be more selective, our server will be started with a - "signature". If none is given, we'll use the one here instead. */ -static const char *default_signature = "Hello World!"; - -int -main (int argc, char *argv[]) -{ - ACE_INET_Addr local (PORT); - ACE_SOCK_Dgram dgram; - - if (dgram.open (local) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "open"), - -1); - - char buf[BUFSIZ]; - ACE_INET_Addr remote; - - while (dgram.recv (buf, - sizeof (buf), - remote) != -1) - { - /* What did the client say? */ - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Received (%s) from (%s)\n", - buf, - remote.get_host_name ())); - - /* Use a simple string-op to decide if the client is one of our - own. Of course, you could have sent numeric values or even a - struct of data. For this simple exercise, however, strings are - just fine. */ - if (ACE_OS::strcmp (buf, - argc > 1 ? argv[1] : default_signature)) - { - /* If the client didn't say something we like then log it - * and move on. - */ - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Client query does not match our signature (%s). Response not sent.\n", - argc > 1 ? argv[1] : default_signature)); - } - else - { - /* As before, we respond to the client's query. */ - - ACE_INET_Addr local ((u_short) 0); - ACE_SOCK_Dgram peer; - if (peer.open (local) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "response open"), - -1); - sprintf (buf, - "I am here"); - if (peer.send (buf, - ACE_OS::strlen (buf) + 1, - remote) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "response send"), - -1); - } - } - - return 0; -} diff --git a/docs/tutorials/010/010.dsp b/docs/tutorials/010/010.dsp deleted file mode 100644 index 85a15e7585a..00000000000 --- a/docs/tutorials/010/010.dsp +++ /dev/null @@ -1,112 +0,0 @@ -# Microsoft Developer Studio Project File - Name="010" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=010 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "010.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "010.mak" CFG="010 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "010 - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "010 - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "010 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "010 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"message_queue.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "010 - Win32 Release"
-# Name "010 - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\message_queue.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\task.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\block.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\task.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/010/Makefile b/docs/tutorials/010/Makefile deleted file mode 100644 index 41d9ecfb6bd..00000000000 --- a/docs/tutorials/010/Makefile +++ /dev/null @@ -1,73 +0,0 @@ - -# $Id$ - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = message_queue - -FILES = -FILES += task - -BUILD = $(VBIN) - -SRC = $(addsuffix .cpp,$(BIN)) $(addsuffix .cpp,$(FILES)) - -HDR = *.h - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb -ts2 -bl -bli0 < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - -e 's/ / /g' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - -Depend : depend - perl ../fix.Makefile - -.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) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - -include .depend diff --git a/docs/tutorials/010/block.h b/docs/tutorials/010/block.h deleted file mode 100644 index 7288c18724b..00000000000 --- a/docs/tutorials/010/block.h +++ /dev/null @@ -1,42 +0,0 @@ -// $Id$ - -#ifndef BLOCK_H -#define BLOCK_H - -#include "ace/Message_Block.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -/* 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. */ -class Block : public ACE_Message_Block -{ -public: - Block (void) - { - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Block ctor 0x%x\n", - (void *) this)); - } - - Block (size_t size) - : ACE_Message_Block (size) - { - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Block ctor 0x%x\n", - (void *) this)); - } - - virtual ~Block (void) - { - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Block dtor 0x%x\n", - (void *) this)); - } -}; - -#endif /* BLOCK_H */ diff --git a/docs/tutorials/010/combine.shar b/docs/tutorials/010/combine.shar deleted file mode 100644 index 7679c94e0e3..00000000000 --- a/docs/tutorials/010/combine.shar +++ /dev/null @@ -1,550 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/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 -# 2242 -rw-rw-r-- page01.pre -# 84 -rw-rw-r-- page02.pre -# 231 -rw-rw-r-- page03.pre -# 138 -rw-rw-r-- page04.pre -# 606 -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 -# 647 -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 _sh32552; 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 03191459100 '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 03191459100 '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' -a59ecff5ebb6cd48d96531f70c504ffc page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 2242 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '2242,' '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 03191459100 '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 03191459100 '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 03191459100 '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> -Something to look at here is the ACE_Barrier usage. In the -constructor, we tell the barrier how many threads we're using. Then, -in the svc() method, we use the barrier's wait() method. You can -think of the barrier as a semaphore initialized to the thread count. -X Each time wait() -is invoked, the semaphore is decremented and the thread is blocked. -X When the count equals zero, all threads are unblocked and allowed to -continue. -<P> -<font size=-1>Note: This isn't the way ACE_Barrier really works, it's -just an analogy</font> -X -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -ff8fe38f39f3860bcd45aa450cb754da page05.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`" - test 606 -eq "$shar_count" || - $echo 'page05.pre:' 'original size' '606,' '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 03191459100 '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 03191459100 '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 03191459100 '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 03191459100 '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' -fe792e145798cee96c099bf4026cf8ef 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 03191459100 '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. -<P> -Also notice that we haven't used <i>THR_DETACHED</i> in this -X tutorial. Why? Because in <i>message_queue.cpp</i> we call -X <i>wait()</i> to wait for all of the task's threads to exit. -X That prevents the leak that we normally avoid by using <i>THR_DETACHED</i>. -SHAR_EOF - $shar_touch -am 03191459100 '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' -802d999314ebcf28ebbffe6fb6dedcfa page05.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pst'`" - test 647 -eq "$shar_count" || - $echo 'page05.pst:' 'original size' '647,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh32552 -exit 0 diff --git a/docs/tutorials/010/message_queue.cpp b/docs/tutorials/010/message_queue.cpp deleted file mode 100644 index f16f2606da7..00000000000 --- a/docs/tutorials/010/message_queue.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// $Id$ - -/* To illustrate the ACE_Message_Queue, we use a derivative of - ACE_Task<>. We also derive from ACE_Message_Block to show that we - don't have memory leaks. */ -#include "task.h" -#include "block.h" - -int -run_test (int iterations, - int threads) -{ - /* Create and start an instance of our Task object. */ - Task task (threads); - - if (task.open () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "open"), - -1); - - /* 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)); - - int i; - for (i = 0; i < iterations; ++i) - { - /* Create a new message block to hold our data. Here, we ask - for a block that has 128 bytes of data space. */ - Block *message; - ACE_NEW_RETURN (message, - Block (128), - -1); - - /* Grab the "write pointer". 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); - message->wr_ptr (ACE_OS::strlen (message->rd_ptr ())); - - /* 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. */ - if (task.putq (message) == -1) - break; - } - - /* 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 MB_DATA, so when the tasks - get a MB_HANGUP type, they know to go away. */ - Block *message; - - ACE_NEW_RETURN (message, - Block (), - -1); - message->msg_type (ACE_Message_Block::MB_HANGUP); - task.putq (message); - - /* Wait for the threads in our task object to go away. */ - task.wait (); - - return 0; -} - -int -main (int argc, char *argv[]) -{ - /* Set the number of iterations through our putq() loop and the - number of threads to use in our Task<> derivative. */ - int iterations = argc > 1 ? ACE_OS::atoi (argv[1]) : 9; - int threads = argc > 2 ? ACE_OS::atoi (argv[2]) : 2; - - run_test (iterations, threads); - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Application exiting\n")); - - return 0; -} diff --git a/docs/tutorials/010/page01.html b/docs/tutorials/010/page01.html deleted file mode 100644 index e1c705b3846..00000000000 --- a/docs/tutorials/010/page01.html +++ /dev/null @@ -1,62 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 010</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 010</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing chunks of data through an ACE_Message_Queue</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -<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> - 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 deleted file mode 100644 index a674dee7954..00000000000 --- a/docs/tutorials/010/page02.html +++ /dev/null @@ -1,127 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 010</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 010</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing chunks of data through an ACE_Message_Queue</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -We'll look first at <A HREF="message_queue.cpp">main()</A>. -<P> - -<HR WIDTH="100%"> -<PRE> -<font color=red>// $Id$</font> - -<font color=red>/* To illustrate the ACE_Message_Queue, we use a derivative of - ACE_Task<>. We also derive from ACE_Message_Block to show that we - don't have memory leaks. */</font> -<font color=blue>#include</font> "<font color=green>task.h</font>" -<font color=blue>#include</font> "<font color=green>block.h</font>" - -int -run_test (int iterations, - int threads) -{ - <font color=red>/* Create and start an instance of our Task object. */</font> - Task task (threads); - - if (task.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. */</font> - <font color=#008888>ACE_OS::sleep</font> (ACE_Time_Value (1)); - - int i; - for (i = 0; i < 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; - ACE_NEW_RETURN (message, - Block (128), - -1); - - <font color=red>/* Grab the "<font color=green>write pointer</font>". This is a pointer into the data - area where we can write our data. After writting the data you - have to increment the wr_ptr() so that subsequent writes won't - clobber what you've put there. */</font> - <font color=#008888>ACE_OS::sprintf</font> (message->wr_ptr (), - "<font color=green>This is message %d.</font>", - i); - message->wr_ptr (<font color=#008888>ACE_OS::strlen</font> (message->rd_ptr ())); - - <font color=red>/* Put the message block into the queue. One of the threads in - the Task object will pick up the block and "<font color=green>do work</font>" on it. */</font> - if (task.putq (message) == -1) - break; - } - - <font color=red>/* Once we're done, we have to signal the Task objects to shut - down. There are several choices including: - Send a message of - zero length - Send a message with a special content I don't like - these choices because they're likely to interfere with application - logic. Instead, I use the message type feature to send a message - of type "<font color=green>hangup</font>". The default type is MB_DATA, so when the tasks - get a MB_HANGUP type, they know to go away. */</font> - Block *message; - - ACE_NEW_RETURN (message, - Block (), - -1); - message->msg_type (<font color=#008888>ACE_Message_Block::MB_HANGUP</font>); - task.putq (message); - - <font color=red>/* Wait for the threads in our task object to go away. */</font> - task.wait (); - - return 0; -} - -int -main (int argc, char *argv[]) -{ - <font color=red>/* Set the number of iterations through our putq() loop and the - number of threads to use in our Task<> derivative. */</font> - int iterations = argc > 1 ? atoi (argv[1]) : 9; - int threads = argc > 2 ? atoi (argv[2]) : 2; - - run_test (iterations, threads); - - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) Application exiting\n</font>")); - - return 0; -} -</PRE> -<HR WIDTH="100%"> -<P> -This looks a lot like our thread-pool server and it even does some things -better. In particular, I've scoped the Task object so that it's destructor -will have a chance to get called before the application exits. -Notice how we write actual data into the message block though. In the thread-pool -server we just provided a pointer. Writting the data is actually a more correct -way of doing things since you don't get into strange pointer casting situations. -What if you want to put complex objects into the message block though? We'll do -that in the next tutorial, let's stick with the basics first. -<P> -On the next page we'll take a look at our Block object... -<P> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page03.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/010/page03.html b/docs/tutorials/010/page03.html deleted file mode 100644 index c755d2f9833..00000000000 --- a/docs/tutorials/010/page03.html +++ /dev/null @@ -1,75 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 010</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 010</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing chunks of data through an ACE_Message_Queue</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -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> - -<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> "<A HREF="../../../ace/Message_Block.h">ace/Message_Block.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<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, - "<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, - "<font color=green>(%P|%t) Block ctor 0x%x\n</font>", - (void *) this)); - } - - virtual ~Block (void) - { - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) Block dtor 0x%x\n</font>", - (void *) this)); - } -}; - -<font color=blue>#endif</font> <font color=red>/* BLOCK_H */</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> - diff --git a/docs/tutorials/010/page04.html b/docs/tutorials/010/page04.html deleted file mode 100644 index fe622fee13e..00000000000 --- a/docs/tutorials/010/page04.html +++ /dev/null @@ -1,78 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 010</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 010</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing chunks of data through an ACE_Message_Queue</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -Our <A HREF="task.h">Task</A> object executes in one or more threads -and reads from the message queue it contains. -<P> - -<HR WIDTH="100%"> -<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> "<A HREF="../../../ace/Task.h">ace/Task.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=red>/* Like the thread-pool server tutorial, we'll derive from ACE_Task<>. - 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<> */</font> -class Task : public ACE_Task <ACE_MT_SYNCH> -{ -public: - - typedef ACE_Task <ACE_MT_SYNCH> inherited; - - <font color=red>/* The constructor/destructor are simple but take care of some - necessary housekeeping. */</font> - Task (size_t n_threads); - ~Task (void); - - <font color=red>/* open() will kick off our thread pool for us. */</font> - int open (void * = 0); - - <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_; - - size_t n_threads_; - <font color=red>// Number of threads in the pool.</font> -}; - -<font color=blue>#endif</font> <font color=red>/* TASK_H */</font> -</PRE> -<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. -<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 deleted file mode 100644 index 1e9ddef1cc6..00000000000 --- a/docs/tutorials/010/page05.html +++ /dev/null @@ -1,171 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 010</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 010</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing chunks of data through an ACE_Message_Queue</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -Our <A HREF="task.cpp">Task</A> object definition. -<P> -Something to look at here is the ACE_Barrier usage. In the -constructor, we tell the barrier how many threads we're using. Then, -in the svc() method, we use the barrier's wait() method. You can -think of the barrier as a semaphore initialized to the thread count. - Each time wait() -is invoked, the semaphore is decremented and the thread is blocked. - When the count equals zero, all threads are unblocked and allowed to -continue. -<P> -<font size=-1>Note: This isn't the way ACE_Barrier really works, it's -just an analogy</font> - -<HR WIDTH="100%"> -<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=red>/* Set our housekeeping pointer to NULL and tell the user we exist. */</font> -<font color=#008888>Task::Task</font> (size_t n_threads) - : barrier_ (n_threads), - n_threads_ (n_threads) -{ - 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. */</font> -<font color=#008888>Task::~Task</font> (void) -{ - 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; - - <font color=red>/* Like the getq() in svc() below, this will block until a message - arrives. By blocking, we know that the destruction will be paused - until the last thread is done with the message block. */</font> - this->getq (message); - message->release (); -} - -<font color=red>/* Open the object to do work. Next, we activate the Task into the - number of requested threads. */</font> -int -<font color=#008888>Task::open</font> (void *unused) -{ - ACE_UNUSED_ARG (unused); - - return this->activate (THR_NEW_LWP, - n_threads_); -} - -<font color=red>/* Tell the user we're closing and invoke the baseclass' close() to - take care of things. */</font> -int -<font color=#008888>Task::close</font> (u_long 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. */</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, - "<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; - - for (;;) - { - <font color=red>/* Get a message from the queue. Note that getq() will block - until a message shows up. That makes us very - processor-friendly. */</font> - if (this->getq (message) == -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. */</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 (<font color=#008888>ACE_OS::strlen</font> (cp)); - - <font color=red>/* Display the block's address and data to the user. */</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. */</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 (); - } - - return 0; -} -</PRE> -<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. -<P> -Also notice that we haven't used <i>THR_DETACHED</i> in this - tutorial. Why? Because in <i>message_queue.cpp</i> we call - <i>wait()</i> to wait for all of the task's threads to exit. - That prevents the leak that we normally avoid by using <i>THR_DETACHED</i>. -<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 deleted file mode 100644 index 0a34657aca2..00000000000 --- a/docs/tutorials/010/page06.html +++ /dev/null @@ -1,58 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 010</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 010</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing chunks of data through an ACE_Message_Queue</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -Since I added Block just to give us output, let's take a look at that output. - -<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. -<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 deleted file mode 100644 index 7f3ea0c031f..00000000000 --- a/docs/tutorials/010/page07.html +++ /dev/null @@ -1,32 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 010</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 010</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing chunks of data through an ACE_Message_Queue</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -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> - -<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> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/010/task.cpp b/docs/tutorials/010/task.cpp deleted file mode 100644 index 238b1882727..00000000000 --- a/docs/tutorials/010/task.cpp +++ /dev/null @@ -1,123 +0,0 @@ -// $Id$ - -#include "task.h" -#include "block.h" - -/* Set our housekeeping pointer to NULL and tell the user we exist. */ -Task::Task (size_t n_threads) - : barrier_ (n_threads), - n_threads_ (n_threads) -{ - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Task ctor 0x%x\n", - (void *) this)); -} - -/* Take care of cleanup & tell the user we're going away. */ -Task::~Task (void) -{ - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Task dtor 0x%x\n", - (void *) this)); - - /* Get our shutdown notification out of the queue and release it. */ - ACE_Message_Block *message; - - /* Like the getq() in svc() below, this will block until a message - arrives. By blocking, we know that the destruction will be paused - until the last thread is done with the message block. */ - this->getq (message); - message->release (); -} - -/* Open the object to do work. Next, we activate the Task into the - number of requested threads. */ -int -Task::open (void *unused) -{ - ACE_UNUSED_ARG (unused); - - return this->activate (THR_NEW_LWP, - n_threads_); -} - -/* Tell the user we're closing and invoke the baseclass' close() to - take care of things. */ -int -Task::close (u_long flags) -{ - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Task close 0x%x\n", - (void *) this)); - return inherited::close (flags); -} - -/* Our svc() method waits for work on the queue and then processes - that work. */ -int -Task::svc (void) -{ - /* 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. */ - this->barrier_.wait (); - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Task 0x%x starts in thread %d\n", - (void *) this, - ACE_Thread::self ())); - - /* 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. */ - ACE_Message_Block *message; - - for (;;) - { - /* Get a message from the queue. Note that getq() will block - until a message shows up. That makes us very - processor-friendly. */ - if (this->getq (message) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "getq"), - -1); - /* If we got the shutdown request, we need to go away. */ - if (message->msg_type () == ACE_Message_Block::MB_HANGUP) - { - /* Forward the request to any peer threads. */ - this->putq (message); - - /* Leave the infinite loop so that the thread exits. */ - break; - } - - /* The message queue stores char* data. We use rd_ptr() to get - to the beginning of the data. */ - const char *cp = message->rd_ptr (); - - /* 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. */ - message->rd_ptr (ACE_OS::strlen (cp)); - - /* 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)); - - /* Pretend that it takes a while to process the data. */ - ACE_OS::sleep (ACE_Time_Value (0, 5000)); - - /* 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. */ - message->release (); - } - - return 0; -} diff --git a/docs/tutorials/010/task.h b/docs/tutorials/010/task.h deleted file mode 100644 index 4e0b974a60d..00000000000 --- a/docs/tutorials/010/task.h +++ /dev/null @@ -1,45 +0,0 @@ -// $Id$ - -#ifndef TASK_H -#define TASK_H - -#include "ace/Task.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -/* Like the thread-pool server tutorial, we'll derive from ACE_Task<>. - 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> -{ -public: - - typedef ACE_Task <ACE_MT_SYNCH> inherited; - - /* The constructor/destructor are simple but take care of some - necessary housekeeping. */ - Task (size_t n_threads); - ~Task (void); - - /* open() will kick off our thread pool for us. */ - int open (void * = 0); - - /* Our worker method */ - int svc (void); - - /* All we'll do here is print a message to the user. */ - int close (u_long flags = 0); - -protected: - /* Just to be clever, I'll use an ACE_Barrier to cause the threads - to sync in svc() before doing any real work. */ - ACE_Barrier barrier_; - - size_t n_threads_; - // Number of threads in the pool. -}; - -#endif /* TASK_H */ diff --git a/docs/tutorials/011/011.dsp b/docs/tutorials/011/011.dsp deleted file mode 100644 index 0118e99d156..00000000000 --- a/docs/tutorials/011/011.dsp +++ /dev/null @@ -1,116 +0,0 @@ -# Microsoft Developer Studio Project File - Name="011" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=011 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "011.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "011.mak" CFG="011 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "011 - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "011 - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "011 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "011 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"message_queue.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "011 - Win32 Release"
-# Name "011 - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\message_queue.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\task.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\block.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\data.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\task.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/011/Makefile b/docs/tutorials/011/Makefile deleted file mode 100644 index 41d9ecfb6bd..00000000000 --- a/docs/tutorials/011/Makefile +++ /dev/null @@ -1,73 +0,0 @@ - -# $Id$ - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = message_queue - -FILES = -FILES += task - -BUILD = $(VBIN) - -SRC = $(addsuffix .cpp,$(BIN)) $(addsuffix .cpp,$(FILES)) - -HDR = *.h - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb -ts2 -bl -bli0 < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - -e 's/ / /g' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - -Depend : depend - perl ../fix.Makefile - -.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) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - -include .depend diff --git a/docs/tutorials/011/block.h b/docs/tutorials/011/block.h deleted file mode 100644 index 28443494c93..00000000000 --- a/docs/tutorials/011/block.h +++ /dev/null @@ -1,38 +0,0 @@ -// $Id$ - -#ifndef BLOCK_H -#define BLOCK_H - -#include "ace/Message_Block.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -class Block : public ACE_Message_Block -{ -public: - Block (void) - { - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Block ctor 0x%x\n", - (void *) this)); - } - - Block (size_t size) - : ACE_Message_Block (size) - { - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Block ctor 0x%x\n", - (void *) this)); - } - - virtual ~Block (void) - { - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Block dtor 0x%x\n", - (void *) this)); - } -}; - -#endif /* BLOCK_H */ diff --git a/docs/tutorials/011/combine.shar b/docs/tutorials/011/combine.shar deleted file mode 100644 index 53cf2f988a2..00000000000 --- a/docs/tutorials/011/combine.shar +++ /dev/null @@ -1,489 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/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 -# 869 -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 -# 707 -rw-rw-r-- page06.pre -# 351 -rw-rw-r-- page02.pst -# 365 -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 _sh32588; 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 03191459100 '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. -<P> -A simple abstract for a simple tutorial: -<UL> -In this tutorial, we put some data into the blocks of the message queue. -We copy the data from a Data object into the block and put it on the -queue. The block is then dequeued by the thread which picks it up and -processes it. This tutorial is very similar to the previous -one with the extra touch being population of the blocks with data. -</UL> -(Abstract by Kirthika, as always.) -SHAR_EOF - $shar_touch -am 03191459100 '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' -58768929bbe513a9fa2302b1fe3170be page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 869 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '869,' '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 03191459100 '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 03191459100 '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 03191459100 '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 03191459100 '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 03191459100 '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' -17d64bbe275773a80d7d767e04e0474c page06.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page06.pre'`" - test 707 -eq "$shar_count" || - $echo 'page06.pre:' 'original size' '707,' '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 03191459100 '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> -Again, like <A HREF="../010/page01.html">Tutorial 10</A> we've skipped -<i>THR_DETACHED</i> because we <i>wait()</i> for the threads to exit -X elsewhere. -SHAR_EOF - $shar_touch -am 03191459100 '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' -1005245771b0756716fa87dfdf966155 page03.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pst'`" - test 365 -eq "$shar_count" || - $echo 'page03.pst:' 'original size' '365,' '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 03191459100 '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 _sh32588 -exit 0 diff --git a/docs/tutorials/011/data.h b/docs/tutorials/011/data.h deleted file mode 100644 index 098644c9a6f..00000000000 --- a/docs/tutorials/011/data.h +++ /dev/null @@ -1,73 +0,0 @@ -// $Id$ - -#ifndef DATA_H -#define DATA_H - -class DataBase -{ -public: - DataBase (void) - { - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) DataBase ctor 0x%x\n", - (void *) this)); - } - virtual ~DataBase (void) - { - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) DataBase dtor 0x%x\n", - (void *) this)); - } - - void who_am_i (void) - { - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) DataBase instance 0x%x\n", - (void *) this)); - } - - virtual void what_am_i (void) - { - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) I am a DataBase object\n")); - } - -}; - -class Data : public DataBase -{ -public: - Data (void) - : message_ (-1) - { - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Data ctor 0x%x\n", - (void *) this)); - } - - Data (int message) - : message_ (message) - { - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Data ctor 0x%x for message %d\n", - (void *) this, message_)); - } - virtual ~Data (void) - { - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Data dtor 0x%x\n", - (void *) this)); - } - - void what_am_i (void) - { - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) I am a Data object for message %d\n", - message_)); - } - -protected: - int message_; -}; - -#endif /* DATA_H */ diff --git a/docs/tutorials/011/message_queue.cpp b/docs/tutorials/011/message_queue.cpp deleted file mode 100644 index 168a9793f9f..00000000000 --- a/docs/tutorials/011/message_queue.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// $Id$ - -/* Most of this is the same as the previous tutorial, so I'll just - point out the differences. */ -#include "task.h" -#include "block.h" -#include "data.h" - - -static int -run_test (int iterations, - int threads) - -{ - Task task (threads); - - if (task.open () == -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; - - ACE_NEW_RETURN (message, - Block (sizeof (data) + 128), - -1); - - /* 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 (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) - break; - } - - Block *message; - ACE_NEW_RETURN (message, - Block, - -1); - message->msg_type (ACE_Message_Block::MB_HANGUP); - task.putq (message); - - task.wait (); - - return 0; -} - -int -main (int argc, char *argv[]) -{ - int iterations = argc > 1 ? ACE_OS::atoi (argv[1]) : 4; - int threads = argc > 2 ? ACE_OS::atoi (argv[2]) : 2; - - run_test (iterations, - threads); - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Application exiting\n")); - - return 0; -} diff --git a/docs/tutorials/011/page01.html b/docs/tutorials/011/page01.html deleted file mode 100644 index 9fdddc8f189..00000000000 --- a/docs/tutorials/011/page01.html +++ /dev/null @@ -1,37 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 011</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 011</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing non-trivial data through an ACE_Message_Queue</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -<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. -<P> -A simple abstract for a simple tutorial: -<UL> -In this tutorial, we put some data into the blocks of the message queue. -We copy the data from a Data object into the block and put it on the -queue. The block is then dequeued by the thread which picks it up and -processes it. This tutorial is very similar to the previous -one with the extra touch being population of the blocks with data. -</UL> -(Abstract by Kirthika, as always.) -<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 deleted file mode 100644 index 63d55989641..00000000000 --- a/docs/tutorials/011/page02.html +++ /dev/null @@ -1,117 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 011</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 011</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing non-trivial data through an ACE_Message_Queue</FONT></B></CENTER> - - -<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%"> -<PRE> -<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>" - - -static int -run_test (int iterations, - int threads) - -{ - Task task (threads); - - if (task.open () == -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 < iterations; ++i) - { - <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; - - ACE_NEW_RETURN (message, - Block (sizeof (data) + 128), - -1); - - <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 (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; - ACE_NEW_RETURN (message, - Block, - -1); - message->msg_type (<font color=#008888>ACE_Message_Block::MB_HANGUP</font>); - task.putq (message); - - task.wait (); - - return 0; -} - -int -main (int argc, char *argv[]) -{ - int iterations = argc > 1 ? atoi (argv[1]) : 4; - int threads = argc > 2 ? atoi (argv[2]) : 2; - - run_test (iterations, - threads); - - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) Application exiting\n</font>")); - - return 0; -} -</PRE> -<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. -<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 deleted file mode 100644 index 6426920642c..00000000000 --- a/docs/tutorials/011/page03.html +++ /dev/null @@ -1,189 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 011</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 011</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing non-trivial data through an ACE_Message_Queue</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -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> -<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> "<A HREF="../../../ace/Task.h">ace/Task.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -class Task : public ACE_Task <ACE_MT_SYNCH> -{ -public: - - typedef ACE_Task <ACE_MT_SYNCH> inherited; - - Task (size_t n_threads); - ~Task (void); - - int open (void * = 0); - - int svc (void); - - int close (u_long flags = 0); - -protected: - ACE_Barrier barrier_; - - size_t n_threads_; -}; - -<font color=blue>#endif</font> <font color=red>/* TASK_H */</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> (size_t n_threads) - : barrier_ (n_threads), - n_threads_ (n_threads) -{ - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) Task ctor 0x%x\n</font>", - (void *) this)); -} - -<font color=#008888>Task::~Task</font> (void) -{ - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) Task dtor 0x%x\n</font>", - (void *) this)); - - ACE_Message_Block *message; - this->getq (message); - message->release (); -} - -int -<font color=#008888>Task::open</font> (void *) -{ - return this->activate (THR_NEW_LWP, - this->n_threads_); - -} - -int -<font color=#008888>Task::close</font> (u_long 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 -<font color=#008888>Task::svc</font> (void) -{ - this->barrier_.wait (); - - 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; - - for (;;) - { - if (this->getq (message) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>getq</font>"), - -1); - - if (message->msg_type () == <font color=#008888>ACE_Message_Block::MB_HANGUP</font>) - { - this->putq (message); - - break; - } - - const char *cp = message->rd_ptr (); - <font color=red>// Don't forget to skip the NULL we inserted</font> - message->rd_ptr (<font color=#008888>ACE_OS::strlen</font> (cp) + 1); - - 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. */</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; - data = (Data *)message->rd_ptr(); - data->who_am_i(); - data->what_am_i(); - message->rd_ptr(sizeof(Data)); - - Even though this cuts down on the number of copies & - constructions, I'm not real fond of it. You can get into - trouble in a hurry by treating memory blocks as multiple data - types... */</font> - - - <font color=#008888>ACE_OS::sleep</font> (ACE_Time_Value (0, 5000)); - - message->release (); - } - - return 0; -} -</PRE> -<HR WIDTH="100%"> -<P> -Notice how we had to create a temporary Data object to copy the stuff out -of the message block? Again, if there were non-trivial ctor/dtors involved -then this wouldn't work at all. -<P> -Again, like <A HREF="../010/page01.html">Tutorial 10</A> we've skipped -<i>THR_DETACHED</i> because we <i>wait()</i> for the threads to exit - elsewhere. -<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 deleted file mode 100644 index 04fb9f8a006..00000000000 --- a/docs/tutorials/011/page04.html +++ /dev/null @@ -1,105 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 011</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 011</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing non-trivial data through an ACE_Message_Queue</FONT></B></CENTER> - - -<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. - -<P> -<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, - "<font color=green>(%P|%t) DataBase ctor 0x%x\n</font>", - (void *) this)); - } - virtual ~DataBase (void) - { - 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, - "<font color=green>(%P|%t) DataBase instance 0x%x\n</font>", - (void *) this)); - } - - virtual void what_am_i (void) - { - ACE_DEBUG ((LM_DEBUG, - "<font color=green>(%P|%t) I am a DataBase object\n</font>")); - } - -}; - -class Data : public DataBase -{ -public: - Data (void) - : message_ (-1) - { - 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, - "<font color=green>(%P|%t) Data ctor 0x%x for message %d\n</font>", - (void *) this, message_)); - } - virtual ~Data (void) - { - 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, - "<font color=green>(%P|%t) I am a Data object for message %d\n</font>", - message_)); - } - -protected: - int message_; -}; - -<font color=blue>#endif</font> <font color=red>/* DATA_H */</font> -</PRE> -<HR WIDTH="100%"> -<P> -Ok, no mysterious magic on this one. Just a simple object and derivative -that report their existence. -<P> -<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 deleted file mode 100644 index 3bd035d4bd1..00000000000 --- a/docs/tutorials/011/page05.html +++ /dev/null @@ -1,94 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 011</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 011</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing non-trivial data through an ACE_Message_Queue</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> - -Let's take a look at this new program's output: - -<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> -<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 deleted file mode 100644 index 691facfbe80..00000000000 --- a/docs/tutorials/011/page06.html +++ /dev/null @@ -1,37 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 011</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 011</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing non-trivial data through an ACE_Message_Queue</FONT></B></CENTER> - - -<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 -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> - -<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> - -* 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/011/task.cpp b/docs/tutorials/011/task.cpp deleted file mode 100644 index 76d77caf860..00000000000 --- a/docs/tutorials/011/task.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// $Id$ - -#include "task.h" -#include "block.h" -#include "data.h" - -Task::Task (size_t n_threads) - : barrier_ (n_threads), - n_threads_ (n_threads) -{ - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Task ctor 0x%x\n", - (void *) this)); -} - -Task::~Task (void) -{ - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Task dtor 0x%x\n", - (void *) this)); - - ACE_Message_Block *message; - this->getq (message); - message->release (); -} - -int -Task::open (void *) -{ - return this->activate (THR_NEW_LWP, - this->n_threads_); - -} - -int -Task::close (u_long flags) -{ - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Task close 0x%x\n", - (void *) this)); - return inherited::close (flags); -} - -int -Task::svc (void) -{ - this->barrier_.wait (); - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Task 0x%x starts in thread %d\n", - (void *) this, - ACE_Thread::self ())); - - ACE_Message_Block *message; - - for (;;) - { - if (this->getq (message) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "getq"), - -1); - - if (message->msg_type () == ACE_Message_Block::MB_HANGUP) - { - this->putq (message); - - break; - } - - const char *cp = message->rd_ptr (); - // Don't forget to skip the NULL we inserted - message->rd_ptr (ACE_OS::strlen (cp) + 1); - - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) Block 0x%x contains (%s)\n", - (void *) message, - cp)); - - /* Create a Data object into which we can extract the message - block contents. */ - Data data; - - /* Use the rd_ptr() to access the message block data. Note that - we've already moved it past the text string in the block. */ - ACE_OS::memmove ((char *) &data, - message->rd_ptr (), - sizeof (data)); - message->rd_ptr (sizeof (data)); // Move the rd_ptr() beyond the data. - - /* Invoke a couple of method calls on the object we constructed. */ - data.who_am_i (); - data.what_am_i (); - - /* An alternate approach: - - Data * data; - data = (Data *)message->rd_ptr(); - data->who_am_i(); - data->what_am_i(); - message->rd_ptr(sizeof(Data)); - - Even though this cuts down on the number of copies & - constructions, I'm not real fond of it. You can get into - trouble in a hurry by treating memory blocks as multiple data - types... */ - - - ACE_OS::sleep (ACE_Time_Value (0, 5000)); - - message->release (); - } - - return 0; -} diff --git a/docs/tutorials/011/task.h b/docs/tutorials/011/task.h deleted file mode 100644 index 2350b0be230..00000000000 --- a/docs/tutorials/011/task.h +++ /dev/null @@ -1,33 +0,0 @@ -// $Id$ - -#ifndef TASK_H -#define TASK_H - -#include "ace/Task.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -class Task : public ACE_Task <ACE_MT_SYNCH> -{ -public: - - typedef ACE_Task <ACE_MT_SYNCH> inherited; - - Task (size_t n_threads); - ~Task (void); - - int open (void * = 0); - - int svc (void); - - int close (u_long flags = 0); - -protected: - ACE_Barrier barrier_; - - size_t n_threads_; -}; - -#endif /* TASK_H */ diff --git a/docs/tutorials/012/012.dsp b/docs/tutorials/012/012.dsp deleted file mode 100644 index 3e3fbb7c250..00000000000 --- a/docs/tutorials/012/012.dsp +++ /dev/null @@ -1,112 +0,0 @@ -# Microsoft Developer Studio Project File - Name="012" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=012 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "012.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "012.mak" CFG="012 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "012 - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "012 - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "012 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "012 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"message_queue.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "012 - Win32 Release"
-# Name "012 - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\message_queue.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\task.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\data.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\task.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/012/Makefile b/docs/tutorials/012/Makefile deleted file mode 100644 index 41d9ecfb6bd..00000000000 --- a/docs/tutorials/012/Makefile +++ /dev/null @@ -1,73 +0,0 @@ - -# $Id$ - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = message_queue - -FILES = -FILES += task - -BUILD = $(VBIN) - -SRC = $(addsuffix .cpp,$(BIN)) $(addsuffix .cpp,$(FILES)) - -HDR = *.h - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb -ts2 -bl -bli0 < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - -e 's/ / /g' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - -Depend : depend - perl ../fix.Makefile - -.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) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - -include .depend diff --git a/docs/tutorials/012/block.h b/docs/tutorials/012/block.h deleted file mode 100644 index 06179af2757..00000000000 --- a/docs/tutorials/012/block.h +++ /dev/null @@ -1,65 +0,0 @@ - -// $Id$ - -#ifndef BLOCK_H -#define BLOCK_H - -#include "work.h" - -/* - 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 - 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. -*/ -class Message_Block : public ACE_Message_Block -{ -public: - typedef ACE_Message_Block inherited; - - /* - 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. - */ - 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_)); - } - - ~Message_Block(void) - { - ACE_DEBUG ((LM_DEBUG, "(%P|%t) Message_Block dtor 0x%x for 0x%x\n", (void *) this, data_)); - delete data_; - } - - /* - Return the Unit_Of_Work so that the task can invoke methods on - it. - */ - Unit_Of_Work * data(void) - { - return this->data_; - } - -protected: - Unit_Of_Work * data_; - - /* - 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. - */ - Message_Block &operator= (const Message_Block &); - Message_Block (const Message_Block &); -}; - -#endif diff --git a/docs/tutorials/012/combine.shar b/docs/tutorials/012/combine.shar deleted file mode 100644 index 05fb1da2f06..00000000000 --- a/docs/tutorials/012/combine.shar +++ /dev/null @@ -1,466 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/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 -# 1090 -rw-rw-r-- page01.pre -# 262 -rw-rw-r-- page02.pre -# 395 -rw-rw-r-- page03.pre -# 154 -rw-rw-r-- page04.pre -# 182 -rw-rw-r-- page05.pre -# 448 -rw-rw-r-- page06.pre -# 393 -rw-rw-r-- page02.pst -# 398 -rw-rw-r-- page03.pst -# 162 -rw-rw-r-- page04.pst -# 447 -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 _sh32620; 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 03191459100 '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> -Kirthika's abstract: -<UL> -Here, a Message_Block class is derived from ACE_Message_Block and is -used to hold a pointer to the object of class Work. Also, the block has -a header containing text. This example simply illustrates a cleaner way -of utilizing Message_Blocks to store objects rather than copying their -contents. -<P> -The ACE_Barrier class has been used in the Task class which blocks the -threads until all of them are rearing to go and grab a block from the -queue and process it. -<P> -Thus a message queue can be used to accomplish a variety of tasks by -storing a object pointer in the blocks. -</UL> -SHAR_EOF - $shar_touch -am 03191459100 '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' -c9933ac2153b0a56043967ea9c7eb0c9 page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 1090 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '1090,' '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 03191459100 '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' -91f6bbd4cdf687d420bd52bf6685e2d2 page02.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`" - test 262 -eq "$shar_count" || - $echo 'page02.pre:' 'original size' '262,' '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 03191459100 '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' -134a60947715be2de3ca2589a3e652e2 page03.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`" - test 395 -eq "$shar_count" || - $echo 'page03.pre:' 'original size' '395,' '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 03191459100 '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 03191459100 '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' -ed1b82e232cc376efa7b78f391c893bd page05.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`" - test 182 -eq "$shar_count" || - $echo 'page05.pre:' 'original size' '182,' '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 03191459100 '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 03191459100 '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' -ab34347fca8c20953552cf0ecebd394f page02.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pst'`" - test 393 -eq "$shar_count" || - $echo 'page02.pst:' 'original size' '393,' '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 03191459100 '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' -01e400b5683e0e1c3dfa25cc8120bfa6 page03.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pst'`" - test 398 -eq "$shar_count" || - $echo 'page03.pst:' 'original size' '398,' '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 03191459100 '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 03191459100 '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' -a7f519237d11a25b28af7aa33f5aaf30 page05.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pst'`" - test 447 -eq "$shar_count" || - $echo 'page05.pst:' 'original size' '447,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh32620 -exit 0 diff --git a/docs/tutorials/012/message_queue.cpp b/docs/tutorials/012/message_queue.cpp deleted file mode 100644 index 8410d92ad5f..00000000000 --- a/docs/tutorials/012/message_queue.cpp +++ /dev/null @@ -1,97 +0,0 @@ - -// $Id$ - -#include "block.h" -#include "work.h" -#include "task.h" - -/* - 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() -*/ -int run_test (int iterations, int threads) -{ - /* - Create the Task which is our thread pool for doing work - */ - Task task; - - if (task.start (threads) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "start"), -1); - } - - /* - 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)); - - for (int i = 0; i < iterations; ++i) - { - /* - 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. - */ - Work * data = new Work(i); - - /* - Create a block that contains our Work object but also has - enough room for a text message. - */ - Message_Block *message = new Message_Block (128, data); - - /* - 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 ())+1); - - /* - Add the work to our thread pool - */ - if (task.putq (message) == -1) - { - break; - } - } - - /* - Insert a HANGUP message block to tell the thread pool to shut - itself down. - */ - Message_Block *message = new Message_Block (0,0); - message->msg_type (ACE_Message_Block::MB_HANGUP); - task.putq (message); - - /* - 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. - */ - task.wait (); - - return (0); -} - -int main (int argc, char *argv[]) -{ - /* - Give the user a chance to override the default number of - iterations and pool threads. - */ - int iterations = argc > 1 ? ACE_OS::atoi (argv[1]) : 4; - int threads = argc > 2 ? ACE_OS::atoi (argv[2]) : 2; - - /* - 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. - */ - (void) run_test (iterations, threads); - - ACE_DEBUG ((LM_DEBUG, "(%P|%t) Application exiting\n")); - - return (0); -} diff --git a/docs/tutorials/012/page01.html b/docs/tutorials/012/page01.html deleted file mode 100644 index 1650f371399..00000000000 --- a/docs/tutorials/012/page01.html +++ /dev/null @@ -1,45 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 012</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 012</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing classes through ACE_Message_Queue</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -<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> -Kirthika's abstract: -<UL> -Here, a Message_Block class is derived from ACE_Message_Block and is -used to hold a pointer to the object of class Work. Also, the block has -a header containing text. This example simply illustrates a cleaner way -of utilizing Message_Blocks to store objects rather than copying their -contents. -<P> -The ACE_Barrier class has been used in the Task class which blocks the -threads until all of them are rearing to go and grab a block from the -queue and process it. -<P> -Thus a message queue can be used to accomplish a variety of tasks by -storing a object pointer in the blocks. -</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/012/page02.html b/docs/tutorials/012/page02.html deleted file mode 100644 index d1323b24464..00000000000 --- a/docs/tutorials/012/page02.html +++ /dev/null @@ -1,113 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 012</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 012</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing classes through ACE_Message_Queue</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -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%"> -<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> "<A HREF="../../../ace/Message_Block.h">ace/Message_Block.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<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, "<font color=green>(%P|%t) Unit_Of_Work ctor 0x%x\n</font>", (void *) this)); - } - virtual ~ Unit_Of_Work (void) - { - 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, "<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, "<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 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, "<font color=green>(%P|%t) Work ctor 0x%x\n</font>", (void *) this)); - } - - Work (int message) - : message_ (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, "<font color=green>(%P|%t) Work dtor 0x%x\n</font>", (void *) this)); - } - - void what_am_i (void) - { - 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> -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> -<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 deleted file mode 100644 index 185c28c1ff8..00000000000 --- a/docs/tutorials/012/page03.html +++ /dev/null @@ -1,107 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 012</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 012</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing classes through ACE_Message_Queue</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -<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%"> -<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 - 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, "<font color=green>(%P|%t) Message_Block ctor 0x%x for 0x%x\n</font>", (void *) this, data_)); - } - - ~Message_Block(void) - { - 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_; - } - -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> -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> -<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 deleted file mode 100644 index 6db332f3bcb..00000000000 --- a/docs/tutorials/012/page04.html +++ /dev/null @@ -1,128 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 012</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 012</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing classes through ACE_Message_Queue</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -<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%"> -<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.start (threads) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>start</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. - */</font> - <font color=#008888>ACE_OS::sleep</font> (ACE_Time_Value (1)); - - for (int i = 0; i < 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. - */</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 (<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); -} - -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 - "<font color=green>exiting</font>" message below. - */</font> - (void) run_test (iterations, threads); - - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Application exiting\n</font>")); - - return (0); -} -</PRE> -<HR WIDTH="100%"> -<P> -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> -<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 deleted file mode 100644 index 12e41c383e0..00000000000 --- a/docs/tutorials/012/page05.html +++ /dev/null @@ -1,234 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 012</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 012</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing classes through ACE_Message_Queue</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -<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%"> -<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> "<A HREF="../../../ace/Task.h">ace/Task.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<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 - "<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 "<font color=green>work by thread</font>" statistics if they start out together. -*/</font> -class Task : public ACE_Task < ACE_MT_SYNCH > -{ -public: - - typedef ACE_Task < ACE_MT_SYNCH > inherited; - - Task (void); - ~Task (void); - - <font color=red>/* - I really wanted this to be called open() but that was already - claimed by the Task framework. start() will kick off our thread - pool for us. - */</font> - int start (int threads = 1); - - virtual int svc (void); - - virtual 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>work.h</font>" - -<font color=red>/* - Boring default constructor. Be sure our barrier_ is initialized in - case we get destructed before opened. -*/</font> -<font color=#008888>Task::Task</font> (void) -: barrier_ (0) -{ - 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 - shutdown request left in the queue when we get here. Just to be - polite, we'll go ahead and get that message and release it. - - We also delete the barrier_ object we used to synch the svc() - methods. -*/</font> -<font color=#008888>Task::~Task</font> (void) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Task dtor 0x%x\n</font>", (void *) this)); - - ACE_Message_Block *message; - this->getq (message); - message->release (); - - 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(). -*/</font> -int <font color=#008888>Task::start</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. -*/</font> -int <font color=#008888>Task::close</font> (u_long 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. -*/</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, "<font color=green>(%P|%t) Task 0x%x starts in thread %u\n</font>", (void *) this, <font color=#008888>ACE_Thread::self</font> ())); - - <font color=red>// Where we getq() the message</font> - ACE_Message_Block *message; - <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; - <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) - { - <font color=red>// Get the message...</font> - if (this->getq (message) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>getq</font>"), -1); - } - - <font color=red>// Is it a shutdown request?</font> - if (message->msg_type () == <font color=#008888>ACE_Message_Block::MB_HANGUP</font>) - { - <font color=red>// Send the shutdown to all of our pool peers</font> - this->putq (message); - break; - } - - <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 (); - <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, "<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. - */</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 (); - } - - return (0); -} -</PRE> -<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> -<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 deleted file mode 100644 index ba5369830e3..00000000000 --- a/docs/tutorials/012/page06.html +++ /dev/null @@ -1,32 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 012</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 012</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Passing classes through ACE_Message_Queue</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -<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> -<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 deleted file mode 100644 index 5f7d040237e..00000000000 --- a/docs/tutorials/012/task.cpp +++ /dev/null @@ -1,145 +0,0 @@ - -// $Id$ - -#include "task.h" -#include "block.h" -#include "work.h" - -/* - Boring default constructor. Be sure our barrier_ is initialized in - case we get destructed before opened. -*/ -Task::Task (void) -: barrier_ (0) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task ctor 0x%x\n", (void *) this)); -} - -/* - 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 - shutdown request left in the queue when we get here. Just to be - polite, we'll go ahead and get that message and release it. - - We also delete the barrier_ object we used to synch the svc() - methods. -*/ -Task::~Task (void) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task dtor 0x%x\n", (void *) this)); - - ACE_Message_Block *message; - this->getq (message); - message->release (); - - delete barrier_; -} - -/* - 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::start (int threads) -{ - barrier_ = new ACE_Barrier (threads); - return this->activate (THR_NEW_LWP, threads); -} - -/* - We don't really do anything here but I wanted to provide a message - in the output. -*/ -int Task::close (u_long flags) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task close 0x%x\n", (void *) this)); - return inherited::close (flags); -} - -/* - Now the svc() method where everything interesting happens. -*/ -int Task::svc (void) -{ - /* - All of the threads will block here until the last thread - arrives. They will all then be free to begin doing work. - */ - this->barrier_->wait (); - - ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task 0x%x starts in thread %u\n", (void *) this, ACE_Thread::self ())); - - // Where we getq() the message - 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 - 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. - Unit_Of_Work * unit_of_work; - - while (1) - { - // Get the message... - if (this->getq (message) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "getq"), -1); - } - - // Is it a shutdown request? - if (message->msg_type () == ACE_Message_Block::MB_HANGUP) - { - // Send the shutdown to all of our pool peers - 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 - message_block = (Message_Block*)message; - - /* - 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. - */ - const char *cp = message_block->rd_ptr (); - // Don't forget to skip the NULL we inserted - message_block->rd_ptr (strlen (cp) + 1); - - /* - 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. - */ - unit_of_work = message_block->data(); - - /* - Invoke a couple of method calls on the object we constructed. - */ - 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)); - - /* - 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)); - - /* - Release the message block and allow the unit of work to also go - away. - */ - message->release (); - } - - return (0); -} diff --git a/docs/tutorials/012/task.h b/docs/tutorials/012/task.h deleted file mode 100644 index afeed1bbf1d..00000000000 --- a/docs/tutorials/012/task.h +++ /dev/null @@ -1,47 +0,0 @@ - -// $Id$ - -#ifndef TASK_H -#define TASK_H - -#include "ace/Task.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -/* - 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 - 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 > -{ -public: - - typedef ACE_Task < ACE_MT_SYNCH > inherited; - - Task (void); - ~Task (void); - - /* - I really wanted this to be called open() but that was already - claimed by the Task framework. start() will kick off our thread - pool for us. - */ - int start (int threads = 1); - - virtual int svc (void); - - virtual int close (u_long flags = 0); - -protected: - ACE_Barrier * barrier_; -}; - -#endif diff --git a/docs/tutorials/012/work.h b/docs/tutorials/012/work.h deleted file mode 100644 index 6ee772dede7..00000000000 --- a/docs/tutorials/012/work.h +++ /dev/null @@ -1,78 +0,0 @@ - -// $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 */ - -#include "ace/Log_Msg.h" - -/* - 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 diff --git a/docs/tutorials/013/013.dsp b/docs/tutorials/013/013.dsp deleted file mode 100644 index 92f6469a27e..00000000000 --- a/docs/tutorials/013/013.dsp +++ /dev/null @@ -1,132 +0,0 @@ -# Microsoft Developer Studio Project File - Name="013" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=013 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "013.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "013.mak" CFG="013 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "013 - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "013 - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "013 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "013 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"message_queue.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "013 - Win32 Release"
-# Name "013 - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\block.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\message_queue.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mld.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\task.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\work.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\block.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mld.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\task.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\work.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/013/Makefile b/docs/tutorials/013/Makefile deleted file mode 100644 index c150df6639c..00000000000 --- a/docs/tutorials/013/Makefile +++ /dev/null @@ -1,74 +0,0 @@ - -# $Id$ - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = message_queue - -FILES = task block work mld - -BUILD = $(VBIN) - -SRC = $(addsuffix .cpp,$(BIN)) -SRC += $(addsuffix .cpp,$(FILES)) - -HDR = *.h - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb -ts2 -bl -bli0 < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - -e 's/ / /g' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - -Depend : depend - perl ../fix.Makefile - -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) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -.depend : # - touch .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - -include .depend diff --git a/docs/tutorials/013/block.cpp b/docs/tutorials/013/block.cpp deleted file mode 100644 index e652d33643a..00000000000 --- a/docs/tutorials/013/block.cpp +++ /dev/null @@ -1,81 +0,0 @@ - -// $Id$ - -#include "block.h" - -/* - Construct a Dat_Block to contain a unit of work. Note the careful - construction of the baseclass to set the block type and the locking - strategy. - */ -Data_Block::Data_Block (Unit_Of_Work * _data) - : ACE_Data_Block (0, ACE_Message_Block::MB_DATA, 0, 0, new Lock (), 0, 0) - ,data_ (_data) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x Data_Block ctor for 0x%x\n", (void *) this, (void *) data_)); -} - -/* - The Lock object created in the constructor is stored in the baseclass and - available through the locking_strategy() method. We can cast it's value to - our Lock object and invoke the destroy() to indicate that we want it to go - away when the lock is released. - */ -Data_Block::~Data_Block (void) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x Data_Block dtor for 0x%x\n", (void *) this, (void *) data_)); - ((Lock *) locking_strategy ())->destroy (); - delete data_; -} - -/* - Return the data - */ -Unit_Of_Work *Data_Block::data (void) -{ - return this->data_; -} - -Data_Block:: Lock::Lock (void) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x Lock ctor\n", (void *) this)); -} - -Data_Block:: Lock::~Lock (void) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x Lock dtor\n", (void *) this)); -} - -/* - Delete ourselves to prevent any memory leak - */ -int Data_Block::Lock::destroy (void) -{ - delete this; - return (0); -} - -/* - Create an baseclass unit of work when we instantiate a hangup message. - */ -Message_Block::Message_Block (void) - :ACE_Message_Block (new Data_Block (new Unit_Of_Work ())) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x Message_Block ctor for shutdown\n", (void *) this)); - this->msg_type (MB_HANGUP); -} - -/* - Store the unit of work in a Data_Block and initialize the baseclass with - that data. - */ -Message_Block::Message_Block (Unit_Of_Work * _data) - :ACE_Message_Block (new Data_Block (_data)) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x Message_Block ctor for 0x%x\n", (void *) this, (void *) _data)); -} - -Message_Block::~Message_Block (void) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x Message_Block dtor\n", (void *) this)); -} diff --git a/docs/tutorials/013/block.h b/docs/tutorials/013/block.h deleted file mode 100644 index 91261c3ecd0..00000000000 --- a/docs/tutorials/013/block.h +++ /dev/null @@ -1,84 +0,0 @@ - -// $Id$ - -#ifndef BLOCK_H -#define BLOCK_H - -#include "ace/Message_Block.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "ace/Synch.h" -#include "mld.h" -#include "work.h" - -/* - In this Tutorial, we derive from ACE_Data_Block for our special data. With - the possiblilty that our Task object may forward the unit of work on to - another thread pool, we have to make sure that the data object doesn't go - out of scope unexpectedly. An ACE_Message_Block will be deleted as soon as - it's release() method is called but the ACE_Data_Blocks it uses are - reference counted and only delete when the last reference release()es the - block. We use that trait to simplify our object memory management. - */ -class Data_Block : public ACE_Data_Block -{ -public: - typedef ACE_Data_Block inherited; - - // Create a data block with a unit of work to be done - Data_Block (Unit_Of_Work * _data); - - ~Data_Block (void); - - // Returns the work pointer - Unit_Of_Work *data (void); - -protected: - Unit_Of_Work * data_; - MLD; // Our memory leak detector - - // The ACE_Data_Block allows us to choose a locking strategy - // for making the reference counting thread-safe. The - // ACE_Lock_Adaptor<> template adapts the interface of a - // number of lock objects so that the ACE_Message_Block will - // have an interface it can use. - class Lock : public ACE_Lock_Adapter < ACE_Mutex > - { - public: - typedef ACE_Lock_Adapter < ACE_Mutex > inherited; - - Lock (void); - ~Lock (void); - - // destroy() will be called to explicitly delete the - // lock when we no longer need it. The method will then - // cleanup to prevent any memory leaks. - int destroy (void); - - protected: - MLD; - }; -}; - -/* - This simple derivative of ACE_Message_Block will construct our Data_Block - object to contain a unit of work. - */ -class Message_Block : public ACE_Message_Block -{ -public: - typedef ACE_Message_Block inherited; - - Message_Block (void); - Message_Block (Unit_Of_Work * _data); - - ~Message_Block (void); - -protected: - MLD; -}; - -#endif diff --git a/docs/tutorials/013/combine.shar b/docs/tutorials/013/combine.shar deleted file mode 100644 index 48895131550..00000000000 --- a/docs/tutorials/013/combine.shar +++ /dev/null @@ -1,661 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/013'. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 386 -rw-rw-r-- hdr -# 89 -rw-rw-r-- bodies -# 2412 -rw-rw-r-- page01.pre -# 432 -rw-rw-r-- page02.pre -# 1424 -rw-rw-r-- page03.pre -# 1048 -rw-rw-r-- page04.pre -# 268 -rw-rw-r-- page05.pre -# 914 -rw-rw-r-- page06.pre -# 1360 -rw-rw-r-- page07.pre -# 860 -rw-rw-r-- page08.pre -# 204 -rw-rw-r-- page02.pst -# 704 -rw-rw-r-- page04.pst -# 385 -rw-rw-r-- page06.pst -# 369 -rw-rw-r-- page07.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 _sh32654; 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 013</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> -X -<CENTER><B><FONT SIZE=+2>ACE Tutorial 013</FONT></B></CENTER> -X -<CENTER><B><FONT SIZE=+2>Multiple thread pools</FONT></B></CENTER> -SHAR_EOF - $shar_touch -am 03191459100 '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' -abef9831eba4051526151ff2343730d7 hdr -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`" - test 386 -eq "$shar_count" || - $echo 'hdr:' 'original size' '386,' '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 -mld.h mld.cpp -block.h -block.cpp -task.h task.cpp -work.h work.cpp -SHAR_EOF - $shar_touch -am 1114230198 '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' -826e1e15e593f64228b867cb6143f179 bodies -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`" - test 89 -eq "$shar_count" || - $echo 'bodies:' 'original size' '89,' '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> -<HR WIDTH="100%"> -<P> -My intent with this tutorial was to derive from ACE_Data_Block instead -of ACE_Message_Block so that we could leverage the reference counting -nature of that object. -<P> -Along the way, I sort of got distracted... What I ended up with is a -poor excuse for ACE_Stream that implements a simple state machine. -<P> -The application is built around a thread pool where the pool's svc() -method takes work units from the message queue for processing. As -each unit is taken from the queue, the process() method is invoked to -do some work. The twist is that after processing the message, we -enqueue it into another thread pool to do more work. This continues -through a chain of thread pools until the last where the unit's fini() -method is called for finishing up any outstanding work. -<P> -The chain of thread pools is uni-directional using a singly-linked -list of Task derivatives. Each pool has the same number of tasks in -order to keep things simple. -<P> -Kirthika's abstract: -<UL> -In this tutorial, a singly linked list of thread-pools, each of which is -a subtask and which acts as the finite state machine node, is used to -simulate a finite state machine. -<P> -A task is created with a number of subtasks. Once the message block is -obtained from the queue, it is verified to see whether a task has a -subtask. If so, it is forwarded to the subtask. Thus the mesage -traverses over the whole list. As a safety measure for destroying the -block after it goes through the whole list, an effective and simple -Memory Leak Detector has been implemented. It is a counter which -increments when the object where it resides is created and decrements on -its deletion. -<P> -Another optimisation from the previous tutorials on Message Queues, is -the bundling of the Data block within the Message Block. The Data block -provides reference counting, so duplication of data is avoided. It is -deleted only when its reference count drops to zero. Now updating -this count between threads call for synchronisation and in comes the -ACE_Mutex, a lock which takes care that the counting is thread-safe. -<P> -Although the example isn't a full-fledged Finite State Machine, -i.e. it has to be tweaked to be able to jump states on different inputs, -it definitely proves to be a great lesson and introduces us to quite a -few new ACE classes and the ways they can be mixed and matched to -produce the end-system desired. -</ul> -SHAR_EOF - $shar_touch -am 03191459100 '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' -a78a6c7a7841ee5d8ce2a87a55cd456f page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 2412 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '2412,' '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 -X -<P> -<HR WIDTH="100%"> -<P> -We'll go back to our tradition of looking at main() first. The only -change here from our "normal" thread pool is the ability to specify -the number of subtasks for the pool. (Each subtask is another thread -pool in the chain. I suppose I should have named that better...) -I've still got the custom Message_Block so that, at this level, we -don't even know about custom Data_Blocks. -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -6f4a2e24d7d776b1ec17a07f00f409f8 page02.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`" - test 432 -eq "$shar_count" || - $echo 'page02.pre:' 'original size' '432,' '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 -X -<P> -<HR WIDTH="100%"> -<P> -I did eventually create that ACE_Data_Block derivative that I wanted. -My purpose in doing so was to use the reference-counting -that is provided by ACE_Data_Block and ACE_Message_Block interactions. -X When you're working with an object in a single -thread, it's generally not so difficult to manage it's lifetime. -That is, it doesn't tend to go out of scope or get destroyed unless -you do it on purpose. -<P> -On the other hand, if you're passing data between several threads, it -is easy to loose track of who "owns" the data at any one time. All -too frequently, data will be deleted by one thread while another is -still using it. Reference counting can prevent that. The rule of -thumb is that you increment the reference count of the object when you -hand it off to a new thread. You then decrement the count when you're -done with the object and let the object delete itself when there are -no more references. -<P> -To prove that all of that works correctly in the tutorial, I've -created a cheap Memory Leak Detector object. All mld instances -reference a thread-safe counter that is incremented when the mld is -constructed and decremented when destructed. I then insert an mld -into each of my dynamically created objects. If I get to the end of -main() and the counter isn't zero then I either didn't delete enough -or I deleted too many times. -<P> -Simple, cheap, effective. -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -545e09ebf801bfaea60bb1fb07c7ec9f page03.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`" - test 1424 -eq "$shar_count" || - $echo 'page03.pre:' 'original size' '1424,' '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 -X -<P> -<HR WIDTH="100%"> -<P> -Let's look now at the changes to our ACE_Message_Block derivative and -the new ACE_Data_Block derivative. -<P> -The important thing to remember is that the data block (not the -message block) is reference counted. When you instantiate a new -ACE_Message_Block, it will create one or more ACE_Data_Block objects -to contain the data you need. Optionally, you can provide it with a -pointer to a data block. -<P> -When you finish with a message block, you should use the release() -method to make it go away. Do not ever <em>delete</em> an instance of -a message block! When you invoke release(), the message block will -invoke release() on the data block(s) it contains. If the block's -reference count goes to zero as a result then the block will <em>delete</em> -itself. -<P> -To increment the reference count of a data block, use the -duplicate() method of the message block (or blocks) to get a new -message block referencing the same data block. This is very efficient -since the actual data is not copied. -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -c8b4750a824380f2effc43557c8540ad page04.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`" - test 1048 -eq "$shar_count" || - $echo 'page04.pre:' 'original size' '1048,' '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 -X -<P> -<HR WIDTH="100%"> -<P> -On this page we have the code for the Data_Block and Message_Block -objects. As you probably suspect from the header on the previous -page, the complicated part is in the construction and destruction of -the Data_Block. -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -a95fdcd3db2356b091228728f4f3f130 page05.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`" - test 268 -eq "$shar_count" || - $echo 'page05.pre:' 'original size' '268,' '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 -X -<P> -<HR WIDTH="100%"> -<P> -Let's take a look now at the new Task object. This will obviously be -different from the Tasks we've created before but I think you'll be -surprised at how relatively simple it actually is. -<P> -Remember that the goal of this tutorial was to use the reference -counting abilities of the ACE_Data_Block. The only way to show that -effectively is to have a data block passed between different threads. -A thread pool isn't really going to do that so, instead, our new Task -can be part of a chain of tasks. In that way, each Task can pass the -data on to another and satisfy our need for moving the ACE_Data_Block -around. -If we've done the reference counting correctly then none of our tasks -will be trying to work with deleted data and we won't have any memory -leaks at the end. -<P> -There's not much to the header, so I've included it and the cpp file -on this one page. -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -a4c9b50df3240c5134733d2033fd5f03 page06.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page06.pre'`" - test 914 -eq "$shar_count" || - $echo 'page06.pre:' 'original size' '914,' '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 -X -<P> -<HR WIDTH="100%"> -<P> -I've been trying to justify the chain of tasks by talking about a -Work object that implements a state machine. The idea is that your -Work object has to perform a series of discrete steps to complete it's -function. Traditionally, all of those steps would take place in one -thread of execution. That thread would probably be one from a Task -thread pool. -<P> -Suppose, however, that some of those steps spend a lot of time waiting -for disk IO. You could find that all of your thread-pool threads -are just sitting there waiting for the disk. You might then be -tempted to increase the thread pool size to get more work through. -However, if some of the stages are memory intensive, you could run out -of memory if all of the workers get to that state at the same time. -<P> -One solution might be to have different thread pools for each state. -Each pool could have it's size tuned appropriately for the work that -would be done there. That's where the chain of Tasks comes in. -X In this tutorial's implementation I've taken the -easy route and set all of the thread pools to the same size but a more -realistic solution would be to set each thread pool in the chain to a -specific size as needed by that state of operation. -<P> -There's not much to this header either so I've combined it with the -cpp file as with task. -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -17c1c426089b288e418c3f62fdc09744 page07.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page07.pre'`" - test 1360 -eq "$shar_count" || - $echo 'page07.pre:' 'original size' '1360,' 'current size' "$shar_count!" - fi -fi -# ============= page08.pre ============== -if test -f 'page08.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page08.pre' '(file already exists)' -else - $echo 'x -' extracting 'page08.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page08.pre' && -X -X -<P> -<HR WIDTH="100%"> -<P> -And that's the end of another tutorial. This one is probably the most -complicated so far because I've introduced or expanded upon -a number of different -concepts. Namely: state machines, reference counting and task -chaining. I hope I didn't complicate things to the point where the -lesson got lost in the noise. As always, feel free to drop a note to -the ACE-Users mailing list if you feel that some of this could use a -little more explaination. -X -<P> -<UL> -<LI><A HREF="Makefile">Makefile</A> -<LI><A HREF="block.cpp">block.cpp</A> -<LI><A HREF="block.h">block.h</A> -<LI><A HREF="message_queue.cpp">message_queue.cpp</A> -<LI><A HREF="mld.cpp">mld.cpp</A> -<LI><A HREF="mld.h">mld.h</A> -<LI><A HREF="task.cpp">task.cpp</A> -<LI><A HREF="task.h">task.h</A> -<LI><A HREF="work.cpp">work.cpp</A> -<LI><A HREF="work.h">work.h</A> -</UL> -<P> -SHAR_EOF - $shar_touch -am 03191459100 'page08.pre' && - chmod 0664 'page08.pre' || - $echo 'restore of' 'page08.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 'page08.pre:' 'MD5 check failed' -b761e40eff75cbf3174b53b4b0c5c172 page08.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page08.pre'`" - test 860 -eq "$shar_count" || - $echo 'page08.pre:' 'original size' '860,' '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> -Nothing really surprising here... Just remember that your total -number of threads is ( ( 1 + subtasks ) * threads ). You probably -don't want to get too carried away with that! -<P> -SHAR_EOF - $shar_touch -am 03191459100 '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' -a8c43c5c68518f6eb8c03701d1603a92 page02.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pst'`" - test 204 -eq "$shar_count" || - $echo 'page02.pst:' 'original size' '204,' '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> -One of the most difficult parts of this to get right was the Lock -object. I didn't even have it in the beginning but I soon realized -that the reference counts were getting weird. A little careful -reading of the comments and the source informed me that some sort of -locking is necessary to keep the counter sane. The simplest thing at -that point was to use the ACE_Lock_Adaptor<> to adapt ACE_Mutex -appropriately. The next trick was to ensure that the lock object was -destroyed at the proper time to prevent both memory leaks and core -dumps. The finaly product may be a little bit intimidating at first -but it's really quite simple once you understand the motivation. -<P> -SHAR_EOF - $shar_touch -am 03191459100 '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' -325565f3f72961b842b612caeb93b36a page04.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pst'`" - test 704 -eq "$shar_count" || - $echo 'page04.pst:' 'original size' '704,' 'current size' "$shar_count!" - fi -fi -# ============= page06.pst ============== -if test -f 'page06.pst' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page06.pst' '(file already exists)' -else - $echo 'x -' extracting 'page06.pst' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page06.pst' && -<HR WIDTH="100%"> -<P> -So you see... it wasn't really that much more complicated. We really -just have to remember to pass to <i>next_</i> when we finish working -on the data. If your Unit_Of_Work derivative is going to implement a -state machine be sure that you also implement a fini() method -<em>or</em> ensure that your chain of subtasks is large enough for all -possible states. -<P> -SHAR_EOF - $shar_touch -am 03191459100 'page06.pst' && - chmod 0664 'page06.pst' || - $echo 'restore of' 'page06.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 'page06.pst:' 'MD5 check failed' -65a1b8bc21034187e0885cc07fa7734f page06.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page06.pst'`" - test 385 -eq "$shar_count" || - $echo 'page06.pst:' 'original size' '385,' 'current size' "$shar_count!" - fi -fi -# ============= page07.pst ============== -if test -f 'page07.pst' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page07.pst' '(file already exists)' -else - $echo 'x -' extracting 'page07.pst' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page07.pst' && -<HR> -<P> -And that is that. For a more complex machine that may want to "jump -states" you would have to set some "state information" (sorry, bad -choice of terminology again) so that process() could decide what to do -at each call. You might also modify Task::svc() so that it will -respect the return value of process() and do something useful with the -information. -<P> -SHAR_EOF - $shar_touch -am 03191459100 'page07.pst' && - chmod 0664 'page07.pst' || - $echo 'restore of' 'page07.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 'page07.pst:' 'MD5 check failed' -21f1bb3615bd4ba5efe5ec25bb895c0e page07.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page07.pst'`" - test 369 -eq "$shar_count" || - $echo 'page07.pst:' 'original size' '369,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh32654 -exit 0 diff --git a/docs/tutorials/013/message_queue.cpp b/docs/tutorials/013/message_queue.cpp deleted file mode 100644 index 17d1afd3d9d..00000000000 --- a/docs/tutorials/013/message_queue.cpp +++ /dev/null @@ -1,88 +0,0 @@ - -// $Id$ - -#include "mld.h" -#include "task.h" -#include "work.h" -#include "block.h" - -int run_test (int iterations, int threads, int subtasks) -{ - // Create a task with some subtasks. Each Task is a thread - // pool of 'threads' size. If a task has a subtask, it will - // forward the unit of work to the subtask when finished. See - // task.{h|cpp} for more details. - Task *task = new Task (subtasks); - - if (task->start (threads) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "start"), -1); - } - - // Give the threads a chance to get ready. - ACE_OS::sleep (ACE_Time_Value (1)); - - for (int i = 0; i < iterations; ++i) - { - // Create a custom message block that can contain our Work object - Message_Block *message = new Message_Block (new Work (i)); - - // Put the "unit of work" into the message queue - if (task->putq (message) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "putq"), -1); - } - } - - // The default constructor of our custom message block will - // insert a message telling our task to shutdown. - Message_Block *message = new Message_Block (); - - // Put the shutdown request into the thread pool - if (task->putq (message) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "putq"), -1); - } - - // Wait for the task to shut down. Any subtasks will also be - // waited for. - task->wait (); - - // Delete our Task to prevent a memory leak - delete task; - - // Ask our memory leak detector if things are OK - if (MLD_COUNTER != 0) - { - ACE_DEBUG ((LM_DEBUG, "(%P|%t) Memory Leak! (counter = %d)\n",MLD_COUNTER)); - } - - return (0); -} - -int main (int argc, char *argv[]) -{ - // Number of Work objects to put into the Task pool - int iterations = argc > 1 ? ACE_OS::atoi (argv[1]) : 4; - // Number of threads for each Task - int threads = argc > 2 ? ACE_OS::atoi (argv[2]) : 2; - // Number of tasks to chain after the primary task - int subtasks = argc > 3 ? ACE_OS::atoi (argv[3]) : 1; - - (void) run_test (iterations, threads, subtasks); - - ACE_DEBUG ((LM_DEBUG, "(%P|%t) Application exiting\n")); - - return (0); -} -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Guard < ACE_Mutex >; -template class ACE_Lock_Adapter < ACE_Mutex >; -template class ACE_Atomic_Op < ACE_Mutex, int >; -#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate ACE_Guard<ACE_Mutex> -#pragma instantiate ACE_Lock_Adapter<ACE_Mutex> -#pragma instantiate ACE_Atomic_Op<ACE_Mutex, int> -#endif /* - ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION - */ diff --git a/docs/tutorials/013/mld.cpp b/docs/tutorials/013/mld.cpp deleted file mode 100644 index ca12d9eb514..00000000000 --- a/docs/tutorials/013/mld.cpp +++ /dev/null @@ -1,23 +0,0 @@ - -// $Id$ - -#include "mld.h" - -ACE_Atomic_Op < ACE_Mutex, int >mld::counter_ (0); - -// Increment the counter when a new mld is created... -mld::mld (void) -{ - ++counter_; -} - -// and decrement it when the object is destructed. -mld::~mld (void) -{ - --counter_; -} - -int mld::value (void) -{ - return counter_.value (); -} diff --git a/docs/tutorials/013/mld.h b/docs/tutorials/013/mld.h deleted file mode 100644 index 2f43562bb4b..00000000000 --- a/docs/tutorials/013/mld.h +++ /dev/null @@ -1,50 +0,0 @@ - -// $Id$ - -#ifndef MLD_H -#define MLD_H - -#include "ace/Synch.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "ace/Singleton.h" -#include "ace/Atomic_Op.h" - -/* - This is a cheap memory leak detector. Each class I want to watch over - contains an mld object. The mld object's ctor increments a global counter - while the dtor decrements it. If the counter is non-zero when the program - is ready to exit then there may be a leak. - */ - -class mld -{ -public: - mld (void); - ~mld (void); - - static int value (void); - -protected: - static ACE_Atomic_Op < ACE_Mutex, int >counter_; -}; - -// ================================================ - -/* - Just drop 'MLD' anywhere in your class definition to get cheap memory leak - detection for your class. - */ -#define MLD mld mld_ - -/* - Use 'MLD_COUNTER' in main() to see if things are OK. - */ -#define MLD_COUNTER mld::value() - -// ================================================ - -#endif diff --git a/docs/tutorials/013/page01.html b/docs/tutorials/013/page01.html deleted file mode 100644 index 2f5c50afaf9..00000000000 --- a/docs/tutorials/013/page01.html +++ /dev/null @@ -1,65 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 013</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 013</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Multiple thread pools</FONT></B></CENTER> -<P> -<HR WIDTH="100%"> -<P> -My intent with this tutorial was to derive from ACE_Data_Block instead -of ACE_Message_Block so that we could leverage the reference counting -nature of that object. -<P> -Along the way, I sort of got distracted... What I ended up with is a -poor excuse for ACE_Stream that implements a simple state machine. -<P> -The application is built around a thread pool where the pool's svc() -method takes work units from the message queue for processing. As -each unit is taken from the queue, the process() method is invoked to -do some work. The twist is that after processing the message, we -enqueue it into another thread pool to do more work. This continues -through a chain of thread pools until the last where the unit's fini() -method is called for finishing up any outstanding work. -<P> -The chain of thread pools is uni-directional using a singly-linked -list of Task derivatives. Each pool has the same number of tasks in -order to keep things simple. -<P> -Kirthika's abstract: -<UL> -In this tutorial, a singly linked list of thread-pools, each of which is -a subtask and which acts as the finite state machine node, is used to -simulate a finite state machine. -<P> -A task is created with a number of subtasks. Once the message block is -obtained from the queue, it is verified to see whether a task has a -subtask. If so, it is forwarded to the subtask. Thus the mesage -traverses over the whole list. As a safety measure for destroying the -block after it goes through the whole list, an effective and simple -Memory Leak Detector has been implemented. It is a counter which -increments when the object where it resides is created and decrements on -its deletion. -<P> -Another optimisation from the previous tutorials on Message Queues, is -the bundling of the Data block within the Message Block. The Data block -provides reference counting, so duplication of data is avoided. It is -deleted only when its reference count drops to zero. Now updating -this count between threads call for synchronisation and in comes the -ACE_Mutex, a lock which takes care that the counting is thread-safe. -<P> -Although the example isn't a full-fledged Finite State Machine, -i.e. it has to be tweaked to be able to jump states on different inputs, -it definitely proves to be a great lesson and introduces us to quite a -few new ACE classes and the ways they can be mixed and matched to -produce the end-system desired. -</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/013/page02.html b/docs/tutorials/013/page02.html deleted file mode 100644 index d8b037fc70f..00000000000 --- a/docs/tutorials/013/page02.html +++ /dev/null @@ -1,124 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 013</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 013</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Multiple thread pools</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -<P> -We'll go back to our tradition of looking at main() first. The only -change here from our "normal" thread pool is the ability to specify -the number of subtasks for the pool. (Each subtask is another thread -pool in the chain. I suppose I should have named that better...) -I've still got the custom Message_Block so that, at this level, we -don't even know about custom Data_Blocks. -<P> -<HR WIDTH="100%"> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>mld.h</font>" -<font color=blue>#include</font> "<font color=green>task.h</font>" -<font color=blue>#include</font> "<font color=green>work.h</font>" -<font color=blue>#include</font> "<font color=green>block.h</font>" - -int run_test (int iterations, int threads, int subtasks) -{ - <font color=red>// Create a task with some subtasks. Each Task is a thread</font> - <font color=red>// pool of 'threads' size. If a task has a subtask, it will</font> - <font color=red>// forward the unit of work to the subtask when finished. See</font> - <font color=red>// task.{h|cpp} for more details.</font> - Task *task = new Task (subtasks); - - if (task->start (threads) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>start</font>"), -1); - } - - <font color=red>// Give the threads a chance to get ready.</font> - <font color=#008888>ACE_OS::sleep</font> (ACE_Time_Value (1)); - - for (int i = 0; i < iterations; ++i) - { - <font color=red>// Create a custom message block that can contain our Work object</font> - Message_Block *message = new Message_Block (new Work (i)); - - <font color=red>// Put the "<font color=green>unit of work</font>" into the message queue</font> - if (task->putq (message) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>putq</font>"), -1); - } - } - - <font color=red>// The default constructor of our custom message block will</font> - <font color=red>// insert a message telling our task to shutdown.</font> - Message_Block *message = new Message_Block (); - - <font color=red>// Put the shutdown request into the thread pool</font> - if (task->putq (message) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>putq</font>"), -1); - } - - <font color=red>// Wait for the task to shut down. Any subtasks will also be</font> - <font color=red>// waited for.</font> - task->wait (); - - <font color=red>// Delete our Task to prevent a memory leak</font> - delete task; - - <font color=red>// Ask our memory leak detector if things are OK</font> - if (MLD_COUNTER != 0) - { - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Memory Leak! (counter = %d)\n</font>",MLD_COUNTER)); - } - - return (0); -} - -int main (int argc, char *argv[]) -{ - <font color=red>// Number of Work objects to put into the Task pool</font> - int iterations = argc > 1 ? atoi (argv[1]) : 4; - <font color=red>// Number of threads for each Task</font> - int threads = argc > 2 ? atoi (argv[2]) : 2; - <font color=red>// Number of tasks to chain after the primary task</font> - int subtasks = argc > 3 ? atoi (argv[3]) : 1; - - (void) run_test (iterations, threads, subtasks); - - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Application exiting\n</font>")); - - return (0); -} -<font color=blue>#if defined</font> (<font color=purple>ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION</font>) -template class ACE_Guard < ACE_Mutex >; -template class ACE_Lock_Adapter < ACE_Mutex >; -template class ACE_Atomic_Op < ACE_Mutex, int >; -<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_Guard<ACE_Mutex>; -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Lock_Adapter<ACE_Mutex>; -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Atomic_Op<ACE_Mutex, int>; -<font color=blue>#endif</font> <font color=red>/* - ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION - */</font> -</PRE> -<HR WIDTH="100%"> -<P> -Nothing really surprising here... Just remember that your total -number of threads is ( ( 1 + subtasks ) * threads ). You probably -don't want to get too carried away with that! -<P> -<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/013/page03.html b/docs/tutorials/013/page03.html deleted file mode 100644 index c113cd0cf23..00000000000 --- a/docs/tutorials/013/page03.html +++ /dev/null @@ -1,127 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 013</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 013</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Multiple thread pools</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -<P> -I did eventually create that ACE_Data_Block derivative that I wanted. -My purpose in doing so was to use the reference-counting -that is provided by ACE_Data_Block and ACE_Message_Block interactions. - When you're working with an object in a single -thread, it's generally not so difficult to manage it's lifetime. -That is, it doesn't tend to go out of scope or get destroyed unless -you do it on purpose. -<P> -On the other hand, if you're passing data between several threads, it -is easy to loose track of who "owns" the data at any one time. All -too frequently, data will be deleted by one thread while another is -still using it. Reference counting can prevent that. The rule of -thumb is that you increment the reference count of the object when you -hand it off to a new thread. You then decrement the count when you're -done with the object and let the object delete itself when there are -no more references. -<P> -To prove that all of that works correctly in the tutorial, I've -created a cheap Memory Leak Detector object. All mld instances -reference a thread-safe counter that is incremented when the mld is -constructed and decremented when destructed. I then insert an mld -into each of my dynamically created objects. If I get to the end of -main() and the counter isn't zero then I either didn't delete enough -or I deleted too many times. -<P> -Simple, cheap, effective. -<P> -<HR WIDTH="100%"> -<HR width=50%><P><center>mld.h</center><HR width=50%> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>MLD_H</font> -<font color=blue>#define</font> <font color=purple>MLD_H</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Synch.h">ace/Synch.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Singleton.h">ace/Singleton.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/Atomic_Op.h">ace/Atomic_Op.h</A>" - -<font color=red>/* - This is a cheap memory leak detector. Each class I want to watch over - contains an mld object. The mld object's ctor increments a global counter - while the dtor decrements it. If the counter is non-zero when the program - is ready to exit then there may be a leak. - */</font> - -class mld -{ -public: - mld (void); - ~mld (void); - - static int value (void); - -protected: - static ACE_Atomic_Op < ACE_Mutex, int >counter_; -}; - -<font color=red>// ================================================</font> - -<font color=red>/* - Just drop 'MLD' anywhere in your class definition to get cheap memory leak - detection for your class. - */</font> -<font color=blue>#define</font> <font color=purple>MLD</font> mld mld_ - -<font color=red>/* - Use 'MLD_COUNTER' in main() to see if things are OK. - */</font> -<font color=blue>#define</font> <font color=purple>MLD_COUNTER</font> <font color=#008888>mld::value</font>() - -<font color=red>// ================================================</font> - -<font color=blue>#endif</font> -</PRE> -<HR width=50%><P><center>mld.cpp</center><HR width=50%> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>mld.h</font>" - -ACE_Atomic_Op < ACE_Mutex, int ><font color=#008888>mld::counter_</font> (0); - -<font color=red>// Increment the counter when a new mld is created...</font> -<font color=#008888>mld::mld</font> (void) -{ - ++counter_; -} - -<font color=red>// and decrement it when the object is destructed.</font> -<font color=#008888>mld::~mld</font> (void) -{ - --counter_; -} - -int <font color=#008888>mld::value</font> (void) -{ - return counter_.value (); -} -</PRE> -<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/013/page04.html b/docs/tutorials/013/page04.html deleted file mode 100644 index af1410396a2..00000000000 --- a/docs/tutorials/013/page04.html +++ /dev/null @@ -1,141 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 013</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 013</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Multiple thread pools</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -<P> -Let's look now at the changes to our ACE_Message_Block derivative and -the new ACE_Data_Block derivative. -<P> -The important thing to remember is that the data block (not the -message block) is reference counted. When you instantiate a new -ACE_Message_Block, it will create one or more ACE_Data_Block objects -to contain the data you need. Optionally, you can provide it with a -pointer to a data block. -<P> -When you finish with a message block, you should use the release() -method to make it go away. Do not ever <em>delete</em> an instance of -a message block! When you invoke release(), the message block will -invoke release() on the data block(s) it contains. If the block's -reference count goes to zero as a result then the block will <em>delete</em> -itself. -<P> -To increment the reference count of a data block, use the -duplicate() method of the message block (or blocks) to get a new -message block referencing the same data block. This is very efficient -since the actual data is not copied. -<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> "<A HREF="../../../ace/Message_Block.h">ace/Message_Block.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Synch.h">ace/Synch.h</A>" -<font color=blue>#include</font> "<font color=green>mld.h</font>" -<font color=blue>#include</font> "<font color=green>work.h</font>" - -<font color=red>/* - In this Tutorial, we derive from ACE_Data_Block for our special data. With - the possiblilty that our Task object may forward the unit of work on to - another thread pool, we have to make sure that the data object doesn't go - out of scope unexpectedly. An ACE_Message_Block will be deleted as soon as - it's release() method is called but the ACE_Data_Blocks it uses are - reference counted and only delete when the last reference release()es the - block. We use that trait to simplify our object memory management. - */</font> -class Data_Block : public ACE_Data_Block -{ -public: - typedef ACE_Data_Block inherited; - - <font color=red>// Create a data block with a unit of work to be done</font> - Data_Block (Unit_Of_Work * _data); - - ~Data_Block (void); - - <font color=red>// Returns the work pointer</font> - Unit_Of_Work *data (void); - -protected: - Unit_Of_Work * data_; - MLD; <font color=red>// Our memory leak detector</font> - - <font color=red>// The ACE_Data_Block allows us to choose a locking strategy</font> - <font color=red>// for making the reference counting thread-safe. The</font> - <font color=red>// ACE_Lock_Adaptor<> template adapts the interface of a</font> - <font color=red>// number of lock objects so that the ACE_Message_Block will</font> - <font color=red>// have an interface it can use.</font> - class Lock : public ACE_Lock_Adapter < ACE_Mutex > - { - public: - typedef ACE_Lock_Adapter < ACE_Mutex > inherited; - - Lock (void); - ~Lock (void); - - <font color=red>// destroy() will be called to explicitly delete the</font> - <font color=red>// lock when we no longer need it. The method will then</font> - <font color=red>// cleanup to prevent any memory leaks.</font> - int destroy (void); - - protected: - MLD; - }; -}; - -<font color=red>/* - This simple derivative of ACE_Message_Block will construct our Data_Block - object to contain a unit of work. - */</font> -class Message_Block : public ACE_Message_Block -{ -public: - typedef ACE_Message_Block inherited; - - Message_Block (void); - Message_Block (Unit_Of_Work * _data); - - ~Message_Block (void); - -protected: - MLD; -}; - -<font color=blue>#endif</font> -</PRE> -<HR WIDTH="100%"> -<P> -One of the most difficult parts of this to get right was the Lock -object. I didn't even have it in the beginning but I soon realized -that the reference counts were getting weird. A little careful -reading of the comments and the source informed me that some sort of -locking is necessary to keep the counter sane. The simplest thing at -that point was to use the ACE_Lock_Adaptor<> to adapt ACE_Mutex -appropriately. The next trick was to ensure that the lock object was -destroyed at the proper time to prevent both memory leaks and core -dumps. The finaly product may be a little bit intimidating at first -but it's really quite simple once you understand the motivation. -<P> -<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/013/page05.html b/docs/tutorials/013/page05.html deleted file mode 100644 index df9e7cd7c00..00000000000 --- a/docs/tutorials/013/page05.html +++ /dev/null @@ -1,109 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 013</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 013</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Multiple thread pools</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -<P> -On this page we have the code for the Data_Block and Message_Block -objects. As you probably suspect from the header on the previous -page, the complicated part is in the construction and destruction of -the Data_Block. -<P> -<HR WIDTH="100%"> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>block.h</font>" - -<font color=red>/* - Construct a Dat_Block to contain a unit of work. Note the careful - construction of the baseclass to set the block type and the locking - strategy. - */</font> -<font color=#008888>Data_Block::Data_Block</font> (Unit_Of_Work * _data) - : ACE_Data_Block (0, <font color=#008888>ACE_Message_Block::MB_DATA</font>, 0, 0, new Lock (), 0, 0) - ,data_ (_data) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x Data_Block ctor for 0x%x\n</font>", (void *) this, (void *) data_)); -} - -<font color=red>/* - The Lock object created in the constructor is stored in the baseclass and - available through the locking_strategy() method. We can cast it's value to - our Lock object and invoke the destroy() to indicate that we want it to go - away when the lock is released. - */</font> -<font color=#008888>Data_Block::~Data_Block</font> (void) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x Data_Block dtor for 0x%x\n</font>", (void *) this, (void *) data_)); - ((Lock *) locking_strategy ())->destroy (); - delete data_; -} - -<font color=red>/* - Return the data - */</font> -Unit_Of_Work *<font color=#008888>Data_Block::data</font> (void) -{ - return this->data_; -} - -Data_Block:: <font color=#008888>Lock::Lock</font> (void) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x Lock ctor\n</font>", (void *) this)); -} - -Data_Block:: <font color=#008888>Lock::~Lock</font> (void) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x Lock dtor\n</font>", (void *) this)); -} - -<font color=red>/* - Delete ourselves to prevent any memory leak - */</font> -int <font color=#008888>Data_Block::Lock</font>::destroy (void) -{ - delete this; - return (0); -} - -<font color=red>/* - Create an baseclass unit of work when we instantiate a hangup message. - */</font> -<font color=#008888>Message_Block::Message_Block</font> (void) - :ACE_Message_Block (new Data_Block (new Unit_Of_Work ())) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x Message_Block ctor for shutdown\n</font>", (void *) this)); - this->msg_type (MB_HANGUP); -} - -<font color=red>/* - Store the unit of work in a Data_Block and initialize the baseclass with - that data. - */</font> -<font color=#008888>Message_Block::Message_Block</font> (Unit_Of_Work * _data) - :ACE_Message_Block (new Data_Block (_data)) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x Message_Block ctor for 0x%x\n</font>", (void *) this, (void *) _data)); -} - -<font color=#008888>Message_Block::~Message_Block</font> (void) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x Message_Block dtor\n</font>", (void *) this)); -} -</PRE> -<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/013/page06.html b/docs/tutorials/013/page06.html deleted file mode 100644 index 33fa7aba2c9..00000000000 --- a/docs/tutorials/013/page06.html +++ /dev/null @@ -1,304 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 013</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 013</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Multiple thread pools</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -<P> -Let's take a look now at the new Task object. This will obviously be -different from the Tasks we've created before but I think you'll be -surprised at how relatively simple it actually is. -<P> -Remember that the goal of this tutorial was to use the reference -counting abilities of the ACE_Data_Block. The only way to show that -effectively is to have a data block passed between different threads. -A thread pool isn't really going to do that so, instead, our new Task -can be part of a chain of tasks. In that way, each Task can pass the -data on to another and satisfy our need for moving the ACE_Data_Block -around. -If we've done the reference counting correctly then none of our tasks -will be trying to work with deleted data and we won't have any memory -leaks at the end. -<P> -There's not much to the header, so I've included it and the cpp file -on this one page. -<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> "<A HREF="../../../ace/Task.h">ace/Task.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=blue>#include</font> "<font color=green>mld.h</font>" - -<font color=red>/* - This is much like the Task we've used in the past for implementing a thread - pool. This time, however, I've made the Task an element in a singly-linked - list. As the svc() method finishes the process() on a unit of work, it - will enqueue that unit of work to the next_ Task if there is one. If the - Task does not have a next_ Task, it will invoke the unit of work object's - fini() method after invoking process(). - */</font> -class Task : public ACE_Task < ACE_MT_SYNCH > -{ -public: - - typedef ACE_Task < ACE_MT_SYNCH > inherited; - - <font color=red>// Construct ourselves and an optional number of subtasks</font> - <font color=red>// chained beyond us.</font> - Task (int sub_tasks = 0); - ~Task (void); - - <font color=red>/* - I really wanted this to be called open() but that was already - claimed by the Task framework. start() will kick off our thread - pool for us. - */</font> - int start (int threads = 1); - - <font color=red>// Take Unit_Of_Work objects from the thread pool and invoke</font> - <font color=red>// their process() and/or fini() as appropriate.</font> - int svc (void); - - <font color=red>// Shut down the thread pool and it's associated subtasks</font> - int close (u_long flags = 0); - - <font color=red>// Wait for the pool and subtasks to close</font> - int wait (void); - -protected: - ACE_Barrier * barrier_; - Task *next_; - MLD; -}; - -<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>work.h</font>" - -<font color=red>/* - Construct the Task with zero or more subtasks. If subtasks are requested, - we assign our next_ pointer to the first of those and let it worry about - any remaining subtasks. - */</font> -<font color=#008888>Task::Task</font> (int sub_tasks) - : barrier_ (0) - ,next_ (0) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Task ctor 0x%x\n</font>", (void *) this)); - if (sub_tasks) - { - next_ = new Task (--sub_tasks); - } -} - -<font color=red>/* - Delete our barrier object and any subtasks we may have. - */</font> -<font color=#008888>Task::~Task</font> (void) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Task dtor 0x%x\n</font>", (void *) this)); - - delete barrier_; - delete next_; -} - -<font color=red>/* - Open our thread pool with the requested number of threads. If subtasks are - enabled, they inherit the thread-pool size. Make sure that the subtasks can - be opened before we open our own threadpool. - */</font> -int <font color=#008888>Task::start</font> (int threads) -{ - if (next_) - { - if (next_->start (threads) == -1) - { - return -1; - } - } - - barrier_ = new ACE_Barrier (threads); - return this->activate (THR_NEW_LWP, threads); -} - -<font color=red>/* - Close ourselves and any subtasks. This just prints a message so that we can - assure ourselves things are cleaned up correctly. - */</font> -int <font color=#008888>Task::close</font> (u_long flags) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Task close 0x%x\n</font>", (void *) this)); - if (next_) - { - next_->close (flags); - } - - return (0); -} - -<font color=red>/* - Wait for all of the threads in our pool to exit and then wait for any - subtasks. When called from the front of the task chain, this won't return - until all thread pools in the chain have exited. - */</font> -int <font color=#008888>Task::wait</font> (void) -{ - <font color=#008888>inherited::wait</font> (); - if (next_) - { - next_->wait (); - } - return (0); -} - -<font color=red>/* - Like the thread-pools before, this is where all of the work is done. - */</font> -int <font color=#008888>Task::svc</font> (void) -{ - <font color=red>// Wait for all threads to get this far before continuing.</font> - this->barrier_->wait (); - - 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> ())); - - <font color=red>// getq() wants an ACE_Message_Block so we'll start out with one</font> - <font color=red>// of those. We could do some casting (or even auto-casting) to</font> - <font color=red>// avoid the extra variable but I prefer to be clear about our actions.</font> - ACE_Message_Block *message; - - <font color=red>// What we really put into the queue was our Message_Block.</font> - <font color=red>// After we get the message from the queue, we'll cast it to this</font> - <font color=red>// so that we know how to work on it.</font> - Message_Block *message_block; - - <font color=red>// And, of course, our Message_Block contains our Data_Block</font> - <font color=red>// instead of the typical ACE_Data_Block</font> - Data_Block *data_block; - - <font color=red>// Even though we put Work objects into the queue, we take them</font> - <font color=red>// out using the baseclass pointer. This allows us to create new</font> - <font color=red>// derivatives without having to change this svc() method.</font> - Unit_Of_Work *work; - - while (1) - { - <font color=red>// Get the ACE_Message_Block</font> - if (this->getq (message) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>getq</font>"), -1); - } - - <font color=red>// "<font color=green>Convert</font>" it to our Message_Block</font> - message_block = (Message_Block *) message; - - <font color=red>// Get the ACE_Data_Block and "<font color=green>convert</font>" to Data_Block in one step.</font> - data_block = (Data_Block *) (message_block->data_block ()); - - <font color=red>// Get the unit of work from the data block</font> - work = data_block->data (); - - <font color=red>// Show the object's instance value and "<font color=green>type name</font>"</font> - work->who_am_i (); - work->what_am_i (); - - <font color=red>// If there is a hangup we need to tell our pool-peers as</font> - <font color=red>// well as any subtasks.</font> - if (message_block->msg_type () == <font color=#008888>ACE_Message_Block::MB_HANGUP</font>) - { - <font color=red>// duplicate()ing the message block will increment the</font> - <font color=red>// reference counts on the data blocks. This allows us</font> - <font color=red>// to safely release() the message block. The rule of</font> - <font color=red>// thumb is that if you pass a message block to a new</font> - <font color=red>// owner, duplicate() it. Then you can release() when</font> - <font color=red>// you're done and not worry about memory leaks.</font> - if (this->putq (message_block->duplicate ()) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>putq</font>"), -1); - } - - <font color=red>// If we have a subtask, duplicate() the message block</font> - <font color=red>// again and pass it to that task's queue</font> - if (next_ && next_->putq (message_block->duplicate ()) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>putq</font>"), -1); - } - - <font color=red>// We're now done with our copy of the block, so we can</font> - <font color=red>// release it. Our peers/subtasks have their own message</font> - <font color=red>// block to access the shared data blocks.</font> - message_block->release (); - - break; - } - - <font color=red>// If this isn't a hangup/shutdown message then we tell the</font> - <font color=red>// unit of work to process() for a while.</font> - work->process (); - - if (next_) - { - <font color=red>// If we have subtasks, we pass the block on to them. Notice</font> - <font color=red>// that I don't bother to duplicate() the block since I won't</font> - <font color=red>// release it in this case. I could have invoked</font> - <font color=red>// duplicate() in the puq() and then release()</font> - <font color=red>// afterwards. Either is acceptable.</font> - if (next_->putq (message_block) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>putq</font>"), -1); - } - else - { - <font color=red>// If we don't have subtasks then invoke fini() to tell</font> - <font color=red>// the unit of work that we won't be invoking process()</font> - <font color=red>// any more. Then release() the block. This release()</font> - <font color=red>// would not change if we duplicate()ed in the above conditional</font> - work->fini (); - message_block->release (); - } - - <font color=red>// Pretend that the work takes some time...</font> - <font color=#008888>ACE_OS::sleep</font> (ACE_Time_Value (0, 250)); - } - - return (0); -} -</PRE> -<HR WIDTH="100%"> -<P> -So you see... it wasn't really that much more complicated. We really -just have to remember to pass to <i>next_</i> when we finish working -on the data. If your Unit_Of_Work derivative is going to implement a -state machine be sure that you also implement a fini() method -<em>or</em> ensure that your chain of subtasks is large enough for all -possible states. -<P> -<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/013/page07.html b/docs/tutorials/013/page07.html deleted file mode 100644 index c4c5ab5936b..00000000000 --- a/docs/tutorials/013/page07.html +++ /dev/null @@ -1,258 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 013</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 013</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Multiple thread pools</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -<P> -I've been trying to justify the chain of tasks by talking about a -Work object that implements a state machine. The idea is that your -Work object has to perform a series of discrete steps to complete it's -function. Traditionally, all of those steps would take place in one -thread of execution. That thread would probably be one from a Task -thread pool. -<P> -Suppose, however, that some of those steps spend a lot of time waiting -for disk IO. You could find that all of your thread-pool threads -are just sitting there waiting for the disk. You might then be -tempted to increase the thread pool size to get more work through. -However, if some of the stages are memory intensive, you could run out -of memory if all of the workers get to that state at the same time. -<P> -One solution might be to have different thread pools for each state. -Each pool could have it's size tuned appropriately for the work that -would be done there. That's where the chain of Tasks comes in. - In this tutorial's implementation I've taken the -easy route and set all of the thread pools to the same size but a more -realistic solution would be to set each thread pool in the chain to a -specific size as needed by that state of operation. -<P> -There's not much to this header either so I've combined it with the -cpp file as with task. -<P> -<HR WIDTH="100%"> -<HR width=50%><P><center>work.h</center><HR width=50%> -<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> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Synch.h">ace/Synch.h</A>" -<font color=blue>#include</font> "<font color=green>mld.h</font>" - -<font color=red>/* - Our specilized message queue and thread pool will know how to do "<font color=green>work</font>" on - our Unit_Of_Work baseclass. - */</font> -class Unit_Of_Work -{ -public: - Unit_Of_Work (void); - - virtual ~ Unit_Of_Work (void); - - <font color=red>// Display the object instance value</font> - void who_am_i (void); - - <font color=red>// The baseclass can override this to show it's "<font color=green>type name</font>"</font> - virtual void what_am_i (void); - - <font color=red>// This is where you do application level logic. It will be</font> - <font color=red>// called once for each thread pool it passes through. It</font> - <font color=red>// would typically implement a state machine and execute a</font> - <font color=red>// different state on each call.</font> - virtual int process (void); - - <font color=red>// This is called by the last Task in the series (see task.h)</font> - <font color=red>// in case our process() didn't get through all of it's states.</font> - virtual int fini (void); - -protected: - ACE_Atomic_Op < ACE_Mutex, int >state_; - MLD; -}; - -<font color=red>/* - A fairly trivial work derivative that implements an equally trivial state - machine in process() - */</font> -class Work : public Unit_Of_Work -{ -public: - Work (void); - - Work (int message); - - virtual ~ Work (void); - - void what_am_i (void); - - int process (void); - - int fini (void); - -protected: - int message_; - MLD; -}; - -<font color=blue>#endif</font> -</PRE> -<HR width=50%><P><center>work.cpp</center><HR width=50%> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>work.h</font>" - -<font color=red>/* - Initialize the state to zero - */</font> -<font color=#008888>Unit_Of_Work::Unit_Of_Work</font> (void) - : state_ (0) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x Unit_Of_Work ctor\n</font>", (void *) this)); -} - -<font color=#008888>Unit_Of_Work::~Unit_Of_Work</font> (void) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x Unit_Of_Work dtor\n</font>", (void *) this)); -} - -<font color=red>/* - Display our instance value - */</font> -void <font color=#008888>Unit_Of_Work::who_am_i</font> (void) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x Unit_Of_Work instance\n</font>", (void *) this)); -} - -<font color=red>/* - Dispay our type name - */</font> -void <font color=#008888>Unit_Of_Work::what_am_i</font> (void) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x I am a Unit_Of_Work object\n</font>", (void *) this)); -} - -<font color=red>/* - Return failure. You should always derive from Unit_Of_Work... - */</font> -int <font color=#008888>Unit_Of_Work::process</font> (void) -{ - return -1; -} - -<font color=red>/* - ditto - */</font> -int <font color=#008888>Unit_Of_Work::fini</font> (void) -{ - return -1; -} - -<font color=red>/* - Default constructor has no "<font color=green>message number</font>" - */</font> -<font color=#008888>Work::Work</font> (void) - :message_ (-1) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x Work ctor\n</font>", (void *) this)); -} - -<font color=red>/* - The useful constructor remembers which message it is and will tell you if - you ask. - */</font> -<font color=#008888>Work::Work</font> (int message) - : message_ (message) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x Work ctor for message %d\n</font>", (void *) this, message_)); -} - -<font color=#008888>Work::~Work</font> (void) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x Work dtor\n</font>", (void *) this)); -} - -<font color=red>/* - This objects type name is different from the baseclass - */</font> -void <font color=#008888>Work::what_am_i</font> (void) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x I am a Work object for message %d\n</font>", (void *) this, message_)); -} - -<font color=red>/* - A very simple state machine that just walks through three stages. If it is - called more than that, it will tell you not to bother. - */</font> -int <font color=#008888>Work::process</font> (void) -{ - switch (++state_) - { - case 1: - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x Stage One\n</font>", (void *) this)); - break; - case 2: - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x Stage Two\n</font>", (void *) this)); - break; - case 3: - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x Stage Three\n</font>", (void *) this)); - break; - default: - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x No work to do in state %d\n</font>", - (void *) this, state_.value ())); - break; - } - return (0); -} - -<font color=red>/* - If you don't have enough subtasks in the chain then the state machine won't - progress to the end. The fini() hook will allow us to recover from that by - executing the remaining states in the final task of the chain. - */</font> -int <font color=#008888>Work::fini</font> (void) -{ - while (state_.value () < 3) - { - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) 0x%x <font color=#008888>Work::fini</font>() state %d\n</font>", (void *) this,state_.value())); - if (this->process () == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>process</font>"), -1); - } - } - return (0); -} -</PRE> -<HR> -<P> -And that is that. For a more complex machine that may want to "jump -states" you would have to set some "state information" (sorry, bad -choice of terminology again) so that process() could decide what to do -at each call. You might also modify Task::svc() so that it will -respect the return value of process() and do something useful with the -information. -<P> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page08.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/013/page08.html b/docs/tutorials/013/page08.html deleted file mode 100644 index e3a46b43638..00000000000 --- a/docs/tutorials/013/page08.html +++ /dev/null @@ -1,43 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 013</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 013</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Multiple thread pools</FONT></B></CENTER> - - -<P> -<HR WIDTH="100%"> -<P> -And that's the end of another tutorial. This one is probably the most -complicated so far because I've introduced or expanded upon -a number of different -concepts. Namely: state machines, reference counting and task -chaining. I hope I didn't complicate things to the point where the -lesson got lost in the noise. As always, feel free to drop a note to -the ACE-Users mailing list if you feel that some of this could use a -little more explaination. - -<P> -<UL> -<LI><A HREF="Makefile">Makefile</A> -<LI><A HREF="block.cpp">block.cpp</A> -<LI><A HREF="block.h">block.h</A> -<LI><A HREF="message_queue.cpp">message_queue.cpp</A> -<LI><A HREF="mld.cpp">mld.cpp</A> -<LI><A HREF="mld.h">mld.h</A> -<LI><A HREF="task.cpp">task.cpp</A> -<LI><A HREF="task.h">task.h</A> -<LI><A HREF="work.cpp">work.cpp</A> -<LI><A HREF="work.h">work.h</A> -</UL> -<P> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/013/task.cpp b/docs/tutorials/013/task.cpp deleted file mode 100644 index 37af6f8072f..00000000000 --- a/docs/tutorials/013/task.cpp +++ /dev/null @@ -1,193 +0,0 @@ - -// $Id$ - -#include "task.h" -#include "block.h" -#include "work.h" - -/* - Construct the Task with zero or more subtasks. If subtasks are requested, - we assign our next_ pointer to the first of those and let it worry about - any remaining subtasks. - */ -Task::Task (int sub_tasks) - : barrier_ (0) - ,next_ (0) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task ctor 0x%x\n", (void *) this)); - if (sub_tasks) - { - next_ = new Task (--sub_tasks); - } -} - -/* - Delete our barrier object and any subtasks we may have. - */ -Task::~Task (void) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task dtor 0x%x\n", (void *) this)); - - delete barrier_; - delete next_; -} - -/* - Open our thread pool with the requested number of threads. If subtasks are - enabled, they inherit the thread-pool size. Make sure that the subtasks can - be opened before we open our own threadpool. - */ -int Task::start (int threads) -{ - if (next_) - { - if (next_->start (threads) == -1) - { - return -1; - } - } - - barrier_ = new ACE_Barrier (threads); - return this->activate (THR_NEW_LWP, threads); -} - -/* - Close ourselves and any subtasks. This just prints a message so that we can - assure ourselves things are cleaned up correctly. - */ -int Task::close (u_long flags) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task close 0x%x\n", (void *) this)); - if (next_) - { - next_->close (flags); - } - - return (0); -} - -/* - Wait for all of the threads in our pool to exit and then wait for any - subtasks. When called from the front of the task chain, this won't return - until all thread pools in the chain have exited. - */ -int Task::wait (void) -{ - inherited::wait (); - if (next_) - { - next_->wait (); - } - return (0); -} - -/* - Like the thread-pools before, this is where all of the work is done. - */ -int Task::svc (void) -{ - // Wait for all threads to get this far before continuing. - this->barrier_->wait (); - - ACE_DEBUG ((LM_DEBUG, "(%P|%t) Task 0x%x starts in thread %u\n", (void *) this, ACE_Thread::self ())); - - // getq() wants an ACE_Message_Block so we'll start out with one - // of those. We could do some casting (or even auto-casting) to - // avoid the extra variable but I prefer to be clear about our actions. - ACE_Message_Block *message; - - // What we really put into the queue was our Message_Block. - // After we get the message from the queue, we'll cast it to this - // so that we know how to work on it. - Message_Block *message_block; - - // And, of course, our Message_Block contains our Data_Block - // instead of the typical ACE_Data_Block - Data_Block *data_block; - - // Even though we put Work objects into the queue, we take them - // out using the baseclass pointer. This allows us to create new - // derivatives without having to change this svc() method. - Unit_Of_Work *work; - - while (1) - { - // Get the ACE_Message_Block - if (this->getq (message) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "getq"), -1); - } - - // "Convert" it to our Message_Block - message_block = (Message_Block *) message; - - // Get the ACE_Data_Block and "convert" to Data_Block in one step. - data_block = (Data_Block *) (message_block->data_block ()); - - // Get the unit of work from the data block - work = data_block->data (); - - // Show the object's instance value and "type name" - work->who_am_i (); - work->what_am_i (); - - // If there is a hangup we need to tell our pool-peers as - // well as any subtasks. - if (message_block->msg_type () == ACE_Message_Block::MB_HANGUP) - { - // duplicate()ing the message block will increment the - // reference counts on the data blocks. This allows us - // to safely release() the message block. The rule of - // thumb is that if you pass a message block to a new - // owner, duplicate() it. Then you can release() when - // you're done and not worry about memory leaks. - if (this->putq (message_block->duplicate ()) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "putq"), -1); - } - - // If we have a subtask, duplicate() the message block - // again and pass it to that task's queue - if (next_ && next_->putq (message_block->duplicate ()) == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "putq"), -1); - } - - // We're now done with our copy of the block, so we can - // release it. Our peers/subtasks have their own message - // block to access the shared data blocks. - message_block->release (); - - break; - } - - // If this isn't a hangup/shutdown message then we tell the - // unit of work to process() for a while. - work->process (); - - if (next_) - { - // If we have subtasks, we pass the block on to them. Notice - // that I don't bother to duplicate() the block since I won't - // release it in this case. I could have invoked - // duplicate() in the puq() and then release() - // afterwards. Either is acceptable. - if (next_->putq (message_block) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "putq"), -1); - } - else - { - // If we don't have subtasks then invoke fini() to tell - // the unit of work that we won't be invoking process() - // any more. Then release() the block. This release() - // would not change if we duplicate()ed in the above conditional - work->fini (); - message_block->release (); - } - - // Pretend that the work takes some time... - ACE_OS::sleep (ACE_Time_Value (0, 250)); - } - - return (0); -} diff --git a/docs/tutorials/013/task.h b/docs/tutorials/013/task.h deleted file mode 100644 index c111333b022..00000000000 --- a/docs/tutorials/013/task.h +++ /dev/null @@ -1,57 +0,0 @@ - -// $Id$ - -#ifndef TASK_H -#define TASK_H - -#include "ace/Task.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "mld.h" - -/* - This is much like the Task we've used in the past for implementing a thread - pool. This time, however, I've made the Task an element in a singly-linked - list. As the svc() method finishes the process() on a unit of work, it - will enqueue that unit of work to the next_ Task if there is one. If the - Task does not have a next_ Task, it will invoke the unit of work object's - fini() method after invoking process(). - */ -class Task : public ACE_Task < ACE_MT_SYNCH > -{ -public: - - typedef ACE_Task < ACE_MT_SYNCH > inherited; - - // Construct ourselves and an optional number of subtasks - // chained beyond us. - Task (int sub_tasks = 0); - ~Task (void); - - /* - I really wanted this to be called open() but that was already - claimed by the Task framework. start() will kick off our thread - pool for us. - */ - int start (int threads = 1); - - // Take Unit_Of_Work objects from the thread pool and invoke - // their process() and/or fini() as appropriate. - int svc (void); - - // Shut down the thread pool and it's associated subtasks - int close (u_long flags = 0); - - // Wait for the pool and subtasks to close - int wait (void); - -protected: - ACE_Barrier * barrier_; - Task *next_; - MLD; -}; - -#endif diff --git a/docs/tutorials/013/work.cpp b/docs/tutorials/013/work.cpp deleted file mode 100644 index ac2920fec90..00000000000 --- a/docs/tutorials/013/work.cpp +++ /dev/null @@ -1,125 +0,0 @@ - -// $Id$ - -#include "work.h" - -/* - Initialize the state to zero - */ -Unit_Of_Work::Unit_Of_Work (void) - : state_ (0) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x Unit_Of_Work ctor\n", (void *) this)); -} - -Unit_Of_Work::~Unit_Of_Work (void) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x Unit_Of_Work dtor\n", (void *) this)); -} - -/* - Display our instance value - */ -void Unit_Of_Work::who_am_i (void) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x Unit_Of_Work instance\n", (void *) this)); -} - -/* - Dispay our type name - */ -void Unit_Of_Work::what_am_i (void) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x I am a Unit_Of_Work object\n", (void *) this)); -} - -/* - Return failure. You should always derive from Unit_Of_Work... - */ -int Unit_Of_Work::process (void) -{ - return -1; -} - -/* - ditto - */ -int Unit_Of_Work::fini (void) -{ - return -1; -} - -/* - Default constructor has no "message number" - */ -Work::Work (void) - :message_ (-1) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x Work ctor\n", (void *) this)); -} - -/* - The useful constructor remembers which message it is and will tell you if - you ask. - */ -Work::Work (int message) - : message_ (message) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x Work ctor for message %d\n", (void *) this, message_)); -} - -Work::~Work (void) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x Work dtor\n", (void *) this)); -} - -/* - This objects type name is different from the baseclass - */ -void Work::what_am_i (void) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x I am a Work object for message %d\n", (void *) this, message_)); -} - -/* - A very simple state machine that just walks through three stages. If it is - called more than that, it will tell you not to bother. - */ -int Work::process (void) -{ - switch (++state_) - { - case 1: - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x Stage One\n", (void *) this)); - break; - case 2: - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x Stage Two\n", (void *) this)); - break; - case 3: - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x Stage Three\n", (void *) this)); - break; - default: - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x No work to do in state %d\n", - (void *) this, state_.value ())); - break; - } - return (0); -} - -/* - If you don't have enough subtasks in the chain then the state machine won't - progress to the end. The fini() hook will allow us to recover from that by - executing the remaining states in the final task of the chain. - */ -int Work::fini (void) -{ - while (state_.value () < 3) - { - ACE_DEBUG ((LM_DEBUG, "(%P|%t) 0x%x Work::fini() state %d\n", (void *) this,state_.value())); - if (this->process () == -1) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "process"), -1); - } - } - return (0); -} diff --git a/docs/tutorials/013/work.h b/docs/tutorials/013/work.h deleted file mode 100644 index bdd0835e098..00000000000 --- a/docs/tutorials/013/work.h +++ /dev/null @@ -1,72 +0,0 @@ - -// $Id$ - -#ifndef WORK_H -#define WORK_H - -#include "ace/Log_Msg.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "ace/Synch.h" -#include "mld.h" - -/* - Our specilized message queue and thread pool will know how to do "work" on - our Unit_Of_Work baseclass. - */ -class Unit_Of_Work -{ -public: - Unit_Of_Work (void); - - virtual ~ Unit_Of_Work (void); - - // Display the object instance value - void who_am_i (void); - - // The baseclass can override this to show it's "type name" - virtual void what_am_i (void); - - // This is where you do application level logic. It will be - // called once for each thread pool it passes through. It - // would typically implement a state machine and execute a - // different state on each call. - virtual int process (void); - - // This is called by the last Task in the series (see task.h) - // in case our process() didn't get through all of it's states. - virtual int fini (void); - -protected: - ACE_Atomic_Op < ACE_Mutex, int >state_; - MLD; -}; - -/* - A fairly trivial work derivative that implements an equally trivial state - machine in process() - */ -class Work : public Unit_Of_Work -{ -public: - Work (void); - - Work (int message); - - virtual ~ Work (void); - - void what_am_i (void); - - int process (void); - - int fini (void); - -protected: - int message_; - MLD; -}; - -#endif diff --git a/docs/tutorials/014/014.dsp b/docs/tutorials/014/014.dsp deleted file mode 100644 index 0801d52285f..00000000000 --- a/docs/tutorials/014/014.dsp +++ /dev/null @@ -1,112 +0,0 @@ -# Microsoft Developer Studio Project File - Name="014" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=014 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "014.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "014.mak" CFG="014 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "014 - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "014 - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "014 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "014 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"stream.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "014 - Win32 Release"
-# Name "014 - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\stream.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\Task.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\EndTask.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Task.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/014/EndTask.h b/docs/tutorials/014/EndTask.h deleted file mode 100644 index 3ee76f1672c..00000000000 --- a/docs/tutorials/014/EndTask.h +++ /dev/null @@ -1,84 +0,0 @@ -// $Id$ - -// Tutorial regarding a way to use ACE_Stream. -// -// written by bob mcwhirter (bob@netwrench.com) - -#ifndef ENDTASK_H -#define ENDTASK_H - -#include "Task.h" - -// When you setup a Stream and push your modules on, -// there are two additional modules that go unseen -// by the user. -// -// The Stream pushes on a Stream_Head in front of -// your first module, and a Stream_Tail behind your -// last module. -// -// If your put () a message to the Stream Tail, it -// assumes you did so in error. This simple EndTask -// class allows you to push a message to it and just -// have it safely Go Away. -// -// All this Task does is release the Message_Block -// and return 0. It's a suitable black-hole. - -class EndTask : public Task -{ -public: - typedef Task inherited; - - EndTask (const char *nameOfTask): inherited (nameOfTask, 0) - { - // when we get open ()'d, it with 0 threads since there is actually - // no processing to do. - - ACE_DEBUG ((LM_INFO, - " (%P|%t) Line: %d, File: %s\n", - __LINE__, - __FILE__)); - } - - virtual int open (void *) - { - ACE_DEBUG ((LM_INFO, - " (%P|%t) Line: %d, File: %s\n", - __LINE__, - __FILE__)); - return 0; - } - - virtual int open (void) - { - ACE_DEBUG ((LM_INFO, - " (%P|%t) Line: %d, File: %s\n", - __LINE__, - __FILE__)); - return 0; - } - - virtual ~EndTask (void) - { - } - - virtual int put (ACE_Message_Block *message, - ACE_Time_Value *timeout) - { - ACE_DEBUG ((LM_INFO, - " (%P|%t) Line: %d, File: %s\n", - __LINE__, - __FILE__)); - ACE_UNUSED_ARG (timeout); - - // we don't have anything to do, so release () the message. - ACE_DEBUG ((LM_DEBUG, - " (%P|%t) %s EndTask::put () -- releasing Message_Block\n", - this->nameOfTask ())); - message->release (); - return 0; - } -}; - -#endif /* ENDTASK_H */ diff --git a/docs/tutorials/014/Makefile b/docs/tutorials/014/Makefile deleted file mode 100644 index 9ccd4e53357..00000000000 --- a/docs/tutorials/014/Makefile +++ /dev/null @@ -1,77 +0,0 @@ - -# $Id$ - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = stream - -FILES = Task - -BUILD = $(VBIN) - -SRC = $(addsuffix .cpp,$(BIN)) -SRC += $(addsuffix .cpp,$(FILES)) - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -rename : # - for i in *.cxx ; do \ - n=`expr "$$i" : "\(.*\).cxx"` ;\ - mv $$i $$n.cpp ;\ - done - -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb -ts2 -bl -bli0 < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - -e 's/ / /g' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - -Depend : depend - perl ../fix.Makefile - -.depend : # - touch .depend - -HTML : # - [ -f hdr ] || $(MAKE) UNSHAR - perl ../combine *.pre - -SHAR : # - [ ! -f combine.shar ] || exit 1 - shar -T hdr bodies *.pre > combine.shar && $(RM) hdr bodies *.pre - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - -include .depend diff --git a/docs/tutorials/014/Task.cpp b/docs/tutorials/014/Task.cpp deleted file mode 100644 index 6732bfa622b..00000000000 --- a/docs/tutorials/014/Task.cpp +++ /dev/null @@ -1,207 +0,0 @@ -// $Id$ - -// Tutorial regarding a way to use ACE_Stream. -// -// written by bob mcwhirter (bob@netwrench.com) - -#include <ace/Message_Block.h> - -#include "Task.h" - -Task::Task (const char * nameOfTask, - int numberOfThreads) - : d_numberOfThreads (numberOfThreads), - d_barrier (numberOfThreads) -{ - // Just initialize our name, number of threads, and barrier. - - ACE_OS::strcpy (d_nameOfTask, nameOfTask); -} - -Task::~Task (void) -{ - ACE_DEBUG ((LM_DEBUG, " (%P|%t) %s Task::~Task () -- once per Task\n", d_nameOfTask)); -} - -int Task::open (void *arg) -{ - ACE_UNUSED_ARG (arg); - - ACE_DEBUG ((LM_DEBUG, " (%P|%t) %s Task::open () -- once per Task\n", d_nameOfTask)); - - // call ACE_Task::activate () to spawn the threads using - // our Task::svc () as the function to be run. - - // No need to use THR_DETACHED here, we're going to wait () - // for the threads to exit later. No leaks. - - return this->activate (THR_NEW_LWP, d_numberOfThreads); -} - -int Task::put (ACE_Message_Block *message, - ACE_Time_Value *timeout) -{ - // ACE_Stream uses the put () method of Tasks to send messages. - // This defaultly does nothing. Here we link our put () method - // directly to our putq () method, so that Messages put () to us - // will appear in the Message_Queue that is checked by the - // service threads. - - return this->putq (message, timeout); -} - -int Task::close (u_long flags) -{ - // When the Stream closes the Module, the Module then close ()'s the Task - // and passing a value of (1) as the flag. - - // When a service thread exits, it calls close () with a value that is not - // (1). - - // We use this fact to tell the difference between closing a service thread, - // and closing the main Task itself. - - if (flags == 1) { - // The Module has asked to close the main Task. - - ACE_DEBUG ((LM_DEBUG, " (%P|%t) %s Task::close () -- flags == 1 -- once per Task\n", d_nameOfTask)); - - // We create a Message_Block of type MB_HANGUP. - - ACE_Message_Block *hangupBlock; - - // Note the use of the lock_adapter () to ensure proper serialization. - ACE_NEW_RETURN (hangupBlock, - ACE_Message_Block (0, - ACE_Message_Block::MB_HANGUP, - 0, - 0, - 0, - Task::lock_adapter ()), - -1); - - // We then send this Block into the Message_Queue to be seen by the - // service threads. - - // Once again we duplicate () the Block as send it off... - - if (this->putq (hangupBlock->duplicate ()) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Task::close () putq"), -1); - } - - // ..and we're free to release () our copy of it. - - hangupBlock->release (); - - // Now, all we have to do is wait () for the service threads to all - // exit. This is where using THR_DETACHED in the activate () method - // will come back to haunt you. - - // The Stream waits until this returns before attempting to remove - // the next Module/Task group in the Stream. This allows for an - // orderly shutting down of the Stream. - - return this->wait (); - } else { - ACE_DEBUG ((LM_DEBUG, " (%P|%t) %s Task::close () -- flags != 1 -- once per servicing thread\n", d_nameOfTask)); - - // This is where we can clean up any mess left over by each service thread. - // In this Task, there is nothing to do. - } - return 0; -} - -int Task::svc (void) -{ - // This is the function that our service threads run once they are spawned. - - ACE_DEBUG ((LM_DEBUG, " (%P|%t) %s Task::svc () -- once per servicing thread\n", d_nameOfTask)); - - // First, we wait until all of our peer service threads have arrived - // at this point also. - - d_barrier.wait (); - - ACE_Message_Block *messageBlock; - - while (1) { - // And now we loop almost infinitely. - - // getq () will block until a Message_Block is available to be read, - // or an error occurs. - - if ( this->getq (messageBlock, 0) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Task::svc () getq"), -1); - } - - if (messageBlock->msg_type () == ACE_Message_Block::MB_HANGUP) { - - // If the Message_Block is of type MB_HANGUP, then we're being asked - // to shut down nicely. - - ACE_DEBUG ((LM_DEBUG, " (%P|%t) %s Task::svc () -- HANGUP block received\n", d_nameOfTask)); - - // So, we duplicate the Block, and put it back into the Message_Queue, - // in case there are some more peer service threads still running. - - if (this->putq (messageBlock->duplicate ()) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Task::svc () putq"), -1); - } - - // We release our copy of the Block. - messageBlock->release (); - - // And we break out of the nearly infinitely loop, and - // head towards close () ourselves. - break; - } - - // If we're here, then we've received a Message_Block that was - // not informing us to quit, so we're assuming it's a valid - // meaningful Block. - - ACE_DEBUG ((LM_DEBUG, " (%P|%t) %s Task::svc () -- Normal block received\n", d_nameOfTask)); - - // We grab the read-pointer from the Block, and display it through a DEBUG statement. - - ACE_DEBUG ((LM_DEBUG, " (%P|%t) %s Task::svc () -- %s\n", d_nameOfTask, messageBlock->rd_ptr () )); - - // We pretend that this takes to time to process the Block. - // If you're on a fast machine, you might have to raise this - // value to actually witness different threads handling - // blocks for each Task. - - ACE_OS::sleep (ACE_Time_Value (0, 250)); - - // Since we're part of a Stream, we duplicate the Block, and - // send it on to the next Task. - - if (put_next (messageBlock->duplicate ()) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Task::svc () put_next"), -1); - } - - // And then we release our copy of it. - - messageBlock->release (); - } - return 0; -} - -const char *Task::nameOfTask (void) const -{ - return d_nameOfTask; -} - -ACE_Lock_Adapter<ACE_SYNCH_MUTEX> *Task::lock_adapter (void) -{ - return &lock_adapter_; -} - -// Static definition. -ACE_Lock_Adapter<ACE_SYNCH_MUTEX> Task::lock_adapter_; - -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Lock_Adapter <ACE_SYNCH_MUTEX>; -#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate ACE_Lock_Adapter <ACE_SYNCH_MUTEX>; -#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/docs/tutorials/014/Task.h b/docs/tutorials/014/Task.h deleted file mode 100644 index 765496598e5..00000000000 --- a/docs/tutorials/014/Task.h +++ /dev/null @@ -1,66 +0,0 @@ -// $Id$ - -// Task.h -// -// Tutorial regarding a way to use ACE_Stream. -// -// written by bob mcwhirter (bob@netwrench.com) - -#ifndef TASK_H -#define TASK_H - -#include <ace/Task.h> -#include <ace/Synch.h> - -// Always typedef when possible. - -typedef ACE_Task<ACE_MT_SYNCH> Task_Base; - -class Task : public Task_Base -{ -public: - typedef Task_Base inherited; - // This is just good form. - - Task (const char *nameOfTask, - int numberOfThreads); - // Initialize our Task with a name, and number of threads to spawn. - - virtual ~Task (void); - - virtual int open (void *arg); - // This is provided to prevent compiler complaints about hidden - // virtual functions. - - virtual int close (u_long flags); - // This closes down the Task and all service threads. - - virtual int put (ACE_Message_Block *message, - ACE_Time_Value *timeout); - // This is the interface that ACE_Stream uses to communicate with - // our Task. - - virtual int svc (void); - // This is the actual service loop each of the service threads - // iterates through. - - const char *nameOfTask (void) const; - // Returns the name of this Task. - - static ACE_Lock_Adapter<ACE_SYNCH_MUTEX> *lock_adapter (void); - // Returns a pointer to the lock adapter. - -private: - int d_numberOfThreads; - char d_nameOfTask[64]; - - ACE_Barrier d_barrier; - // Simple Barrier to make sure all of our service threads have - // entered their loop before accepting any messages. - - static ACE_Lock_Adapter<ACE_SYNCH_MUTEX> lock_adapter_; - // This Lock_Adapter is used to synchronize operations - // on the ACE_Message_Block objects -}; - -#endif /* TASK_H */ diff --git a/docs/tutorials/014/combine.shar b/docs/tutorials/014/combine.shar deleted file mode 100644 index a9183adebeb..00000000000 --- a/docs/tutorials/014/combine.shar +++ /dev/null @@ -1,357 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/014'. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 414 -rw-r--r-- hdr -# 44 -rw-r--r-- bodies -# 2605 -rw-r--r-- page01.pre -# 233 -rw-r--r-- page02.pre -# 657 -rw-r--r-- page03.pre -# 443 -rw-r--r-- page04.pre -# 1091 -rw-r--r-- page05.pre -# -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 _sh32692; 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="Bob McWhirter"> -X <TITLE>ACE Tutorial 014</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> -X -<CENTER><B><FONT SIZE=+2>ACE Tutorial 014</FONT></B></CENTER> -X -<CENTER><B><FONT SIZE=+2>ACE_Stream Tutorial, Of Sorts</FONT></B></CENTER> -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 'hdr' && - chmod 0644 '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' -25304aa689283dcbed9531b68e7ae2b9 hdr -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`" - test 414 -eq "$shar_count" || - $echo 'hdr:' 'original size' '414,' '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 -Task.h -Task.cpp -EndTask.h -stream.cpp -SHAR_EOF - $shar_touch -am 1020193698 'bodies' && - chmod 0644 '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' -43305b4b15975a1e4cbd99b6d3592c12 bodies -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`" - test 44 -eq "$shar_count" || - $echo 'bodies:' 'original size' '44,' '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><b>ACE_Stream</b> is handy when you have several <b>ACE_Task</b> objects -that you would like to link together. -X -<p>An intermediate class you we will deal with is the <b>ACE_Module</b>. -X -<p>The basic plan is to wrap your <b>Task</b> into a <b>Module</b>, push -the <b>Module</b> onto the <b>Stream</b>. Do this for each <b>Task</b>, -X and then inject <b>Message_Block</b>s into the <b>Stream</b>. -X -<p>Each <b>Task</b> then processes the <b>Message_Block</b>, and forwards -it on to the next <b>Task</b> in the <b>Stream</b>. -X -<p>If you are not already familiar with <b>Message_Block</b>s and <b>Message_Queue</b>s, -I highly suggest that you check out <A HREF="../#MQ">Tutorials 10-13</A>. -X -<p>Streams can be used for both downstream and upstream movement of messages. Used -this way mirrors closely the way System V STREAMS work. But you don't have to use them -bidirectionally. In this tutorial, we only use one direction of the Stream. Down. -X -<p>This tutorial is contributed by Bob McWhirter (bob@netwrench.com) -X -<P> -Kirthika's abstract: -<ul> -In this tutorial, an ACE_Stream has been implemented which has modules -flowing through it.(literally ;). -The chain of modules in the Stream include the Head and Tail Modules. A -Module is simply a reader-writer pair of ACE_Tasks with the writing side -acting as downstream and the reading side as upstream. Here we are only -concerned with going downstream so we install a Task into the write-side -of the module. -<P> -The task implementation makes use of flags to decide on whether to close -the main task or the service thread. The svc () method follows the -golden rule of copying message blocks before putting them on the queue -until it comes across a hang-up message. It then puts the message back -on the queue for its peers to obtain it and exits. -<P> -Any message put onto the Tail module is an error. So a customised -derivative of the Task class is created, which collects all the garbage -messages put onto the Tail. This End_Task is put into the Stream at the -start itself such that no modules whould ever follow it! -<P> -Then the other modules are pushed from the Tail-end into the Stream. -This is because we are interested in writing and not reading. -(Picture this to be a FIFO (queue) with head and tail nodes such -that the nodes are removed from the front and put into the queue from -the back) -<P> -Each module then opens up the task which spawns threads and begins to -shove messgaes down the stream. Once we have got all the messages into -the stream, our job is completed and we shut down the Stream. -<P> -A simple way to wade down the stream...;) -</ul> -SHAR_EOF - $shar_touch -am 03191459100 'page01.pre' && - chmod 0644 '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' -b0f801c8c6ba2ddcdf8caf89cb672698 page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 2605 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '2605,' '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> -You find pretty soon that anytime you work with ACE_Task<> you -X have to create a derivative. The Task.h header simply provides -X that derivative with the overrides we'll need in our application. -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 'page02.pre' && - chmod 0644 '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' -af6ee3bfc7543c3b536d5c0ff4b70dd5 page02.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`" - test 233 -eq "$shar_count" || - $echo 'page02.pre:' 'original size' '233,' '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> -Before we get to main() let's take a look at the Task implementation. -X While we've overridden several methods, the real work is done in -X the close() and svc() methods. -<P> -Notice how close() figures out if it is being called by the shutdown -X of the ACE_Stream or by the exit of svc(). The magic here is -X provided by the <i>flags</i> parameter. By handling the stream -X shutdown in this way, we don't have to do anything strange in -X svc(). We also don't end up with extra hangup messages in the -X queue when the dust all settles down. -<P> -Like our other tutorials, svc() looks for a hangup and processes data. -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 'page03.pre' && - chmod 0644 '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' -3403e1bdb202945fc7da5ee1197b4771 page03.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`" - test 657 -eq "$shar_count" || - $echo 'page03.pre:' 'original size' '657,' '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> -As stated in the comments below, the default action of the task at the -X stream tail is to treat any received data as an error. In our -X implementation it will often happen that data gets through to -X the tail. How, then, do we handle this without creating an -X error condition? Simple: Create a custom Task for use as the -X stream tail that doesn't consider it an error to receive data. -<P> -Read on... -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 'page04.pre' && - chmod 0644 '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' -6a3e4f0f1c99fe05cfd1b36b1a1030ed page04.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`" - test 443 -eq "$shar_count" || - $echo 'page04.pre:' 'original size' '443,' '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> -Now we come to main(). In the previous task-chain tutorial -X every thread pool had to have the same number of threads. This -X time around, we leverage the construction method of ACE_Stream -X and ACE_Module to customize the thread-pool size in each -X ACE_Task of the stream. -<P> -Remember EndTask from the previous page? We create one here and push -X it into the stream to take care of cleaning up the messages. -X Technically, we could have replaced the default Tail task -X created by the ACE framework but it seems to make more sense to -X just push our "tail" onto the stream like the other tasks. The -X caveat to this method is that you must be sure you don't push() -X any other Modules behind the EndTask! -<P> -Once the stream of modules containing tasks is all setup then we can -X put() some data into the stream for processing. The clever use -X of Task::close() makes shutting downt the stream easier than -X ever. No messing with hangup messages at the application level, -X just close() when you're done! What could be simpler? -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 'page05.pre' && - chmod 0644 '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' -737e85703d52fe5eefbed872ef22ed7f page05.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`" - test 1091 -eq "$shar_count" || - $echo 'page05.pre:' 'original size' '1091,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh32692 -exit 0 diff --git a/docs/tutorials/014/page01.html b/docs/tutorials/014/page01.html deleted file mode 100644 index cf6972a1156..00000000000 --- a/docs/tutorials/014/page01.html +++ /dev/null @@ -1,74 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Bob McWhirter"> - <TITLE>ACE Tutorial 014</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 014</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>ACE_Stream Tutorial, Of Sorts</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> - -<p><b>ACE_Stream</b> is handy when you have several <b>ACE_Task</b> objects -that you would like to link together. - -<p>An intermediate class you we will deal with is the <b>ACE_Module</b>. - -<p>The basic plan is to wrap your <b>Task</b> into a <b>Module</b>, push -the <b>Module</b> onto the <b>Stream</b>. Do this for each <b>Task</b>, - and then inject <b>Message_Block</b>s into the <b>Stream</b>. - -<p>Each <b>Task</b> then processes the <b>Message_Block</b>, and forwards -it on to the next <b>Task</b> in the <b>Stream</b>. - -<p>If you are not already familiar with <b>Message_Block</b>s and <b>Message_Queue</b>s, -I highly suggest that you check out <A HREF="../#MQ">Tutorials 10-13</A>. - -<p>Streams can be used for both downstream and upstream movement of messages. Used -this way mirrors closely the way System V STREAMS work. But you don't have to use them -bidirectionally. In this tutorial, we only use one direction of the Stream. Down. - -<p>This tutorial is contributed by Bob McWhirter (bob@netwrench.com) - -<P> -Kirthika's abstract: -<ul> -In this tutorial, an ACE_Stream has been implemented which has modules -flowing through it.(literally ;). -The chain of modules in the Stream include the Head and Tail Modules. A -Module is simply a reader-writer pair of ACE_Tasks with the writing side -acting as downstream and the reading side as upstream. Here we are only -concerned with going downstream so we install a Task into the write-side -of the module. -<P> -The task implementation makes use of flags to decide on whether to close -the main task or the service thread. The svc () method follows the -golden rule of copying message blocks before putting them on the queue -until it comes across a hang-up message. It then puts the message back -on the queue for its peers to obtain it and exits. -<P> -Any message put onto the Tail module is an error. So a customised -derivative of the Task class is created, which collects all the garbage -messages put onto the Tail. This End_Task is put into the Stream at the -start itself such that no modules whould ever follow it! -<P> -Then the other modules are pushed from the Tail-end into the Stream. -This is because we are interested in writing and not reading. -(Picture this to be a FIFO (queue) with head and tail nodes such -that the nodes are removed from the front and put into the queue from -the back) -<P> -Each module then opens up the task which spawns threads and begins to -shove messgaes down the stream. Once we have got all the messages into -the stream, our job is completed and we shut down the Stream. -<P> -A simple way to wade down the stream...;) -</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/014/page02.html b/docs/tutorials/014/page02.html deleted file mode 100644 index 47126503170..00000000000 --- a/docs/tutorials/014/page02.html +++ /dev/null @@ -1,92 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Bob McWhirter"> - <TITLE>ACE Tutorial 014</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 014</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>ACE_Stream Tutorial, Of Sorts</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -<P> -You find pretty soon that anytime you work with ACE_Task<> you - have to create a derivative. The Task.h header simply provides - that derivative with the overrides we'll need in our application. -<P> -<HR WIDTH="100%"> -<PRE> -<font color=red>// $Id$</font> - -<font color=red>// Task.h</font> -<font color=red>//</font> -<font color=red>// Tutorial regarding a way to use ACE_Stream.</font> -<font color=red>//</font> -<font color=red>// written by bob mcwhirter (bob@netwrench.com)</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> <ace/Task.h> -<font color=blue>#include</font> <ace/Synch.h> - -<font color=red>// Always typedef when possible.</font> - -typedef ACE_Task<ACE_MT_SYNCH> Task_Base; - -class Task : public Task_Base -{ -public: - typedef Task_Base inherited; - <font color=red>// This is just good form.</font> - - Task (const char *nameOfTask, - int numberOfThreads); - <font color=red>// Initialize our Task with a name, and number of threads to spawn.</font> - - virtual ~Task (void); - - virtual int open (void *arg); - <font color=red>// This is provided to prevent compiler complaints about hidden</font> - <font color=red>// virtual functions.</font> - - virtual int close (u_long flags); - <font color=red>// This closes down the Task and all service threads.</font> - - virtual int put (ACE_Message_Block *message, - ACE_Time_Value *timeout); - <font color=red>// This is the interface that ACE_Stream uses to communicate with</font> - <font color=red>// our Task.</font> - - virtual int svc (void); - <font color=red>// This is the actual service loop each of the service threads</font> - <font color=red>// iterates through.</font> - - const char *nameOfTask (void) const; - <font color=red>// Returns the name of this Task.</font> - - static ACE_Lock_Adapter<ACE_SYNCH_MUTEX> *lock_adapter (void); - <font color=red>// Returns a pointer to the lock adapter.</font> - -private: - int d_numberOfThreads; - char d_nameOfTask[64]; - - ACE_Barrier d_barrier; - <font color=red>// Simple Barrier to make sure all of our service threads have</font> - <font color=red>// entered their loop before accepting any messages.</font> - - static ACE_Lock_Adapter<ACE_SYNCH_MUTEX> lock_adapter_; - <font color=red>// This Lock_Adapter is used to synchronize operations</font> - <font color=red>// on the ACE_Message_Block objects</font> -}; - -<font color=blue>#endif</font> <font color=red>/* TASK_H */</font> -</PRE> -<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/014/page03.html b/docs/tutorials/014/page03.html deleted file mode 100644 index 03d5a41fe14..00000000000 --- a/docs/tutorials/014/page03.html +++ /dev/null @@ -1,262 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Bob McWhirter"> - <TITLE>ACE Tutorial 014</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 014</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>ACE_Stream Tutorial, Of Sorts</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -<P> -Before we get to main () let's take a look at the Task implementation. - While we've overridden several methods, the real work is done in - the close () and svc () methods. -<P> -Notice how close () figures out if it is being called by the shutdown - of the ACE_Stream or by the exit of svc (). The magic here is - provided by the <i>flags</i> parameter. By handling the stream - shutdown in this way, we don't have to do anything strange in - svc (). We also don't end up with extra hangup messages in the - queue when the dust all settles down. -<P> -Like our other tutorials, svc () looks for a hangup and processes data. -<P> -<HR WIDTH="100%"> -<PRE> - -<font color=red>// $Id$</font> - -<font color=red>// Task.cxx</font> -<font color=red>//</font> -<font color=red>// Tutorial regarding a way to use ACE_Stream.</font> -<font color=red>//</font> -<font color=red>// written by bob mcwhirter (bob@netwrench.com)</font> -<font color=red>//</font> -<font color=red>//</font> - -<font color=blue>#include</font> <ace/Message_Block.h> - -<font color=blue>#include</font> "<font color=green>Task.h</font>" - -<font color=#008888>Task::Task</font> (const char * nameOfTask, - int numberOfThreads) - : d_numberOfThreads (numberOfThreads), - d_barrier (numberOfThreads) -{ - <font color=red>// Just initialize our name, number of threads, and barrier.</font> - - <font color=#008888>ACE_OS::strcpy</font> (d_nameOfTask, nameOfTask); -} - -<font color=#008888>Task::~Task</font> (void) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green> (%P|%t) %s <font -color=#008888>Task::~Task</font> () -- once per Task\n</font>", d_nameOfTask)); -} - -int <font color=#008888>Task::open</font> (void *arg) -{ - ACE_UNUSED_ARG (arg); - - ACE_DEBUG ((LM_DEBUG, "<font color=green> (%P|%t) %s <font -color=#008888>Task::open</font> () -- once per Task\n</font>", d_nameOfTask)); - - <font color=red>// call <font color=#008888>ACE_Task::activate</font> () to spawn the threads using</font> - <font color=red>// our <font color=#008888>Task::svc</font> () as the function to be run.</font> - - <font color=red>// No need to use THR_DETACHED here, we're going to wait ()</font> - <font color=red>// for the threads to exit later. No leaks.</font> - - return this->activate (THR_NEW_LWP, d_numberOfThreads); -} - -int <font color=#008888>Task::put</font> (ACE_Message_Block *message, - ACE_Time_Value *timeout) -{ - <font color=red>// ACE_Stream uses the put () method of Tasks to send messages.</font> - <font color=red>// This defaultly does nothing. Here we link our put () method</font> - <font color=red>// directly to our putq () method, so that Messages put () to us</font> - <font color=red>// will appear in the Message_Queue that is checked by the</font> - <font color=red>// service threads.</font> - - return this->putq (message, timeout); -} - -int <font color=#008888>Task::close</font> (u_long flags) -{ - - <font color=red>// When the Stream closes the Module, the Module then close ()'s the Task</font> - <font color=red>// and passing a value of (1) as the flag.</font> - - <font color=red>// When a service thread exits, it calls close () with a value that is not</font> - <font color=red>// (1).</font> - - <font color=red>// We use this fact to tell the difference between closing a service thread,</font> - <font color=red>// and closing the main Task itself.</font> - - if (flags == 1) { - - <font color=red>// The Module has asked to close the main Task.</font> - - ACE_DEBUG ((LM_DEBUG, "<font color=green> (%P|%t) %s <font -color=#008888>Task::close</font> () -- flags == 1 -- once per Task\n</font>", d_nameOfTask)); - - <font color=red>// We create a Message_Block of type MB_HANGUP.</font> - - ACE_Message_Block *hangupBlock; - - <font color=red>// Note the use of the lock_adapter () to ensure proper serialization.</font> - ACE_NEW_RETURN (hangupBlock, - ACE_Message_Block (0, - ACE_Message_Block::MB_HANGUP, - 0, - 0, - 0, - Task::lock_adapter ()), - -1); - - <font color=red>// We then send this Block into the Message_Queue to be seen by the</font> - <font color=red>// service threads.</font> - - <font color=red>// Once again we duplicate () the Block as send it off...</font> - - if (this->putq (hangupBlock->duplicate ()) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>","<font color=green><font color=#008888>Task::close</font> () putq</font>"), -1); - } - - <font color=red>// ..and we're free to release () our copy of it.</font> - - hangupBlock->release (); - - <font color=red>// Now, all we have to do is wait () for the service threads to all</font> - <font color=red>// exit. This is where using THR_DETACHED in the activate () method</font> - <font color=red>// will come back to haunt you.</font> - - <font color=red>// The Stream waits until this returns before attempting to remove</font> - <font color=red>// the next Module/Task group in the Stream. This allows for an</font> - <font color=red>// orderly shutting down of the Stream.</font> - - return this->wait (); - - - } else { - - ACE_DEBUG ((LM_DEBUG, "<font color=green> (%P|%t) %s <font -color=#008888>Task::close</font> () -- flags != 1 -- once per servicing thread\n</font>", d_nameOfTask)); - - <font color=red>// This is where we can clean up any mess left over by each service thread.</font> - <font color=red>// In this Task, there is nothing to do.</font> - - } - - return 0; - -} - -int <font color=#008888>Task::svc</font> (void) -{ - - <font color=red>// This is the function that our service threads run once they are spawned.</font> - - ACE_DEBUG ((LM_DEBUG, "<font color=green> (%P|%t) %s <font -color=#008888>Task::svc</font> () -- once per servicing thread\n</font>", d_nameOfTask)); - - <font color=red>// First, we wait until all of our peer service threads have arrived</font> - <font color=red>// at this point also.</font> - - d_barrier.wait (); - - ACE_Message_Block *messageBlock; - - while (1) { - - <font color=red>// And now we loop almost infinitely.</font> - - <font color=red>// getq () will block until a Message_Block is available to be read,</font> - <font color=red>// or an error occurs.</font> - - if ( this->getq (messageBlock, 0) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>","<font color=green><font color=#008888>Task::svc</font> () getq</font>"), -1); - } - - if (messageBlock->msg_type () == <font color=#008888>ACE_Message_Block::MB_HANGUP</font>) { - - <font color=red>// If the Message_Block is of type MB_HANGUP, then we're being asked</font> - <font color=red>// to shut down nicely.</font> - - ACE_DEBUG ((LM_DEBUG, "<font color=green> (%P|%t) %s <font -color=#008888>Task::svc</font> () -- HANGUP block received\n</font>", d_nameOfTask)); - - <font color=red>// So, we duplicate the Block, and put it back into the Message_Queue,</font> - <font color=red>// in case there are some more peer service threads still running.</font> - - if (this->putq (messageBlock->duplicate ()) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>","<font color=green><font color=#008888>Task::svc</font> () putq</font>"), -1); - } - - <font color=red>// We release our copy of the Block.</font> - messageBlock->release (); - - <font color=red>// And we break out of the nearly infinitely loop, and</font> - <font color=red>// head towards close () ourselves.</font> - break; - } - - <font color=red>// If we're here, then we've received a Message_Block that was</font> - <font color=red>// not informing us to quit, so we're assuming it's a valid</font> - <font color=red>// meaningful Block.</font> - - ACE_DEBUG ((LM_DEBUG, "<font color=green> (%P|%t) %s <font color=#008888>Task::svc</font> () -- Normal block received\n</font>", d_nameOfTask)); - - <font color=red>// We grab the read-pointer from the Block, and display it through a DEBUG statement.</font> - - ACE_DEBUG ((LM_DEBUG, "<font color=green> (%P|%t) %s <font color=#008888>Task::svc</font> () -- %s\n</font>", d_nameOfTask, messageBlock->rd_ptr () )); - - <font color=red>// We pretend that this takes to time to process the Block.</font> - <font color=red>// If you're on a fast machine, you might have to raise this</font> - <font color=red>// value to actually witness different threads handling</font> - <font color=red>// blocks for each Task.</font> - - <font color=#008888>ACE_OS::sleep</font> (ACE_Time_Value (0, 250)); - - <font color=red>// Since we're part of a Stream, we duplicate the Block, and</font> - <font color=red>// send it on to the next Task.</font> - - if (put_next (messageBlock->duplicate ()) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>","<font color=green><font color=#008888>Task::svc</font> () put_next</font>"), -1); - } - - <font color=red>// And then we release our copy of it.</font> - - messageBlock->release (); - - } - - return 0; - -} - -const char * <font color=#008888>Task::nameOfTask</font> (void) const -{ - return d_nameOfTask; -} - -ACE_Lock_Adapter<ACE_SYNCH_MUTEX> *<font -color=#008888>Task::lock_adapter</font> (void) -{ - return &lock_adapter_; -} - -<font color=red>// Static definition.</font> -ACE_Lock_Adapter<ACE_SYNCH_MUTEX> Task::lock_adapter_; - -</PRE> -<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/014/page04.html b/docs/tutorials/014/page04.html deleted file mode 100644 index 5b06801de81..00000000000 --- a/docs/tutorials/014/page04.html +++ /dev/null @@ -1,121 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Bob McWhirter"> - <TITLE>ACE Tutorial 014</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 014</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>ACE_Stream Tutorial, Of Sorts</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -<P> -As stated in the comments below, the default action of the task at the - stream tail is to treat any received data as an error. In our - implementation it will often happen that data gets through to - the tail. How, then, do we handle this without creating an - error condition? Simple: Create a custom Task for use as the - stream tail that doesn't consider it an error to receive data. -<P> -Read on... -<P> -<HR WIDTH="100%"> -<PRE> -<font color=red>// $Id$</font> - -<font color=red>// EndTask.h</font> -<font color=red>//</font> -<font color=red>// Tutorial regarding a way to use ACE_Stream.</font> -<font color=red>//</font> -<font color=red>// written by bob mcwhirter (bob@netwrench.com)</font> -<font color=red>//</font> -<font color=red>//</font> - -<font color=blue>#ifndef</font> <font color=purple>ENDTASK_H</font> -<font color=blue>#define</font> <font color=purple>ENDTASK_H</font> - -<font color=blue>#include</font> "<font color=green>Task.h</font>" - -<font color=red>// When you setup a Stream and push your modules on,</font> -<font color=red>// there are two additional modules that go unseen</font> -<font color=red>// by the user.</font> -<font color=red>//</font> -<font color=red>// The Stream pushes on a Stream_Head in front of</font> -<font color=red>// your first module, and a Stream_Tail behind your</font> -<font color=red>// last module.</font> -<font color=red>//</font> -<font color=red>// If your put () a message to the Stream Tail, it</font> -<font color=red>// assumes you did so in error. This simple EndTask</font> -<font color=red>// class allows you to push a message to it and just</font> -<font color=red>// have it safely Go Away.</font> -<font color=red>//</font> -<font color=red>// All this Task does is release the Message_Block</font> -<font color=red>// and return 0. It's a suitable black-hole.</font> - -class EndTask : public Task -{ -public: - typedef Task inherited; - - EndTask (const char *nameOfTask): inherited (nameOfTask, 0) - { - <font color=red>// when we get open ()'d, it with 0 threads since there is actually</font> - <font color=red>// no processing to do.</font> - - ACE_DEBUG ((LM_INFO, - "<font color=green> (%P|%t) Line: %d, File: %s\n</font>", - __LINE__, - __FILE__)); - } - - virtual int open (void *) - { - ACE_DEBUG ((LM_INFO, - "<font color=green> (%P|%t) Line: %d, File: %s\n</font>", - __LINE__, - __FILE__)); - return 0; - } - - virtual int open (void) - { - ACE_DEBUG ((LM_INFO, - "<font color=green> (%P|%t) Line: %d, File: %s\n</font>", - __LINE__, - __FILE__)); - return 0; - } - - virtual ~EndTask (void) - { - } - - virtual int put (ACE_Message_Block *message, - ACE_Time_Value *timeout) - { - ACE_DEBUG ((LM_INFO, - "<font color=green> (%P|%t) Line: %d, File: %s\n</font>", - __LINE__, - __FILE__)); - ACE_UNUSED_ARG (timeout); - - <font color=red>// we don't have anything to do, so release () the message.</font> - ACE_DEBUG ((LM_DEBUG, - "<font color=green> (%P|%t) %s <font -color=#008888>EndTask::put</font> () -- releasing Message_Block\n</font>", - this->nameOfTask ())); - message->release (); - return 0; - } - -}; - -<font color=blue>#endif</font> <font color=red>/* ENDTASK_H */</font> -</PRE> -<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/014/page05.html b/docs/tutorials/014/page05.html deleted file mode 100644 index 011cebcdd97..00000000000 --- a/docs/tutorials/014/page05.html +++ /dev/null @@ -1,218 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Bob McWhirter"> - <TITLE>ACE Tutorial 014</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 014</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>ACE_Stream Tutorial, Of Sorts</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -<P> -Now we come to main (). In the previous task-chain tutorial - every thread pool had to have the same number of threads. This - time around, we leverage the construction method of ACE_Stream - and ACE_Module to customize the thread-pool size in each - ACE_Task of the stream. -<P> -Remember EndTask from the previous page? We create one here and push - it into the stream to take care of cleaning up the messages. - Technically, we could have replaced the default Tail task - created by the ACE framework but it seems to make more sense to - just push our "tail" onto the stream like the other tasks. The - caveat to this method is that you must be sure you don't push () - any other Modules behind the EndTask! -<P> -Once the stream of modules containing tasks is all setup then we can - put () some data into the stream for processing. The clever use - of Task::close () makes shutting downt the stream easier than - ever. No messing with hangup messages at the application level, - just close () when you're done! What could be simpler? -<P> -<HR WIDTH="100%"> -<PRE> - -<font color=red>// $Id$</font> - -<font color=red>// stream.cxx</font> -<font color=red>//</font> -<font color=red>// Tutorial regarding a way to use ACE_Stream.</font> -<font color=red>//</font> -<font color=red>// written by bob mcwhirter (bob@netwrench.com)</font> -<font color=red>//</font> -<font color=red>//</font> - -<font color=blue>#include</font> "<font color=green>Task.h</font>" -<font color=blue>#include</font> "<font color=green>EndTask.h</font>" -<font color=red>// This is our specialized ACE_Task.</font> - -<font color=blue>#include</font> <ace/Module.h> -<font color=blue>#include</font> <ace/Stream.h> -<font color=blue>#include</font> <ace/streams.h> -<font color=red>// These are the neccessary ACE headers.</font> - - -typedef ACE_Module<ACE_MT_SYNCH> Module; -typedef ACE_Stream<ACE_MT_SYNCH> Stream; -<font color=red>// Just to avoid a lot of typing, typedefs</font> -<font color=red>// are generally a good idea.</font> - -int main (int argc, char *argv[]) -{ - int numberOfMessages = argc > 1 ? <font -color=#008888>ACE_OS::atoi</font> (argv[1]) : 3; - <font color=red>// unless otherwise specified, just send three messages</font> - <font color=red>// down the stream.</font> - - Stream theStream; - <font color=red>// the ACE_Stream itself.</font> - - <font color=red>// Now, we instantiate 4 different Tasks. These do not</font> - <font color=red>// need to be all the same class, but they do need to</font> - <font color=red>// all derrive from the same flavor of ACE_Task.</font> - <font color=red>//</font> - <font color=red>// Also, we instantiate a fifth end-cap Task to clean</font> - <font color=red>// up Message_Blocks as they reach the end.</font> - - Task *taskOne; - Task *taskTwo; - Task *taskThree; - Task *taskFour; - Task *taskEnd; - - <font color=red>// Out Task's take two arguments: a name, and the number</font> - <font color=red>// of threads to dedicate to the task.</font> - - taskOne = new Task ("<font color=green>Task No. 1</font>", 1); - taskTwo = new Task ("<font color=green>Task No. 2</font>", 3); - taskThree = new Task ("<font color=green>Task No. 3</font>", 7); - taskFour = new Task ("<font color=green>Task No. 4</font>", 1); - - <font color=red>// Our EndTask only takes 1 argument, as it actually</font> - <font color=red>// doesn't spawn any threads for processing.</font> - - taskEnd = new EndTask ("<font color=green>End Task</font>"); - - Module *moduleOne; - Module *moduleTwo; - Module *moduleThree; - Module *moduleFour; - Module *moduleEnd; - - <font color=red>// ACE_Stream accepts ACE_Modules, which are simply a pair of</font> - <font color=red>// ACE_Tasks. One is dedicated for writing, while the other</font> - <font color=red>// is dedicated to reading. Think of the writing side as</font> - <font color=red>// downstream, and the reading side as upstream.</font> - <font color=red>//</font> - <font color=red>// We're only working with a unidirection Stream today,</font> - <font color=red>// so we'll only actually install a Task into the write</font> - <font color=red>// side of the module, effectively downstream.</font> - - moduleOne = new Module ("<font color=green>Module No. 1</font>", taskOne); - moduleTwo = new Module ("<font color=green>Module No. 2</font>", taskTwo); - moduleThree = new Module ("<font color=green>Module No. 3</font>", taskThree); - moduleFour = new Module ("<font color=green>Module No. 4</font>", taskFour); - moduleEnd = new Module ("<font color=green>Module End</font>", taskEnd); - - <font color=red>// Now we push the Modules onto the Stream.</font> - <font color=red>// Pushing adds the module to the head, or</font> - <font color=red>// otherwise prepends it to whatever modules</font> - <font color=red>// are already installed.</font> - - <font color=red>// So, you need to push () the modules on -backwards-</font> - <font color=red>// from our viewpoint.</font> - - if (theStream.push (moduleEnd) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>push</font>"), -1); - } - - if (theStream.push (moduleFour) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>push</font>"), -1); - } - - <font color=red>// As we push a Module onto the Stream, it gets opened.</font> - <font color=red>// When a Module open ()s, it opens the Tasks that it contains.</font> - <font color=red>//</font> - <font color=red>// Since we cannot provide an argument to this embedded</font> - <font color=red>// call to open (), we supplied specified the number of</font> - <font color=red>// threads in the constructor of our Tasks.</font> - - if (theStream.push (moduleThree) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>push</font>"), -1); - } - - if (theStream.push (moduleTwo) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>push</font>"), -1); - } - - if (theStream.push (moduleOne) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>push</font>"), -1); - } - - <font color=red>// Now that the Modules are open, the Tasks threads should</font> - <font color=red>// be launching and entering their svc () loop, so we send</font> - <font color=red>// some messages down the Stream.</font> - - int sent = 1; - - ACE_Message_Block *message; - - while (sent <= numberOfMessages) { - - <font color=red>// First, create ourselves a Message_Block. See Tutorials 10-13</font> - <font color=red>// for more information about Message_Blocks and Message_Queues.</font> - <font color=red>// Note the use of the lock_adapter () to ensure proper</font> - <font color=red>// serialization.</font> - ACE_NEW_RETURN (message, - ACE_Message_Block (128, - ACE_Message_Block::MB_DATA, - 0, - 0, - 0, - Task::lock_adapter ()), - -1); - - <font color=red>// Now, we grab the write-pointer from the Block,</font> - <font color=red>// and sprintf () our text into it.</font> - - <font color=#008888>ACE_OS::sprintf</font> (message->wr_ptr (), "<font color=green>Message No. %d</font>", sent); - - <font color=red>// All we have to do now is drop the Message_Block</font> - <font color=red>// into the Stream.</font> - - <font color=red>// It is always a good idea to duplicate () a Message_Block</font> - <font color=red>// when you put it into any Message_Queue, as then</font> - <font color=red>// you can always be allowed to release () your copy</font> - <font color=red>// without worry.</font> - - if (theStream.put (message->duplicate (), 0) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>put</font>"), -1); - } - - message->release (); - ++sent; - } - - <font color=red>// Now that we've sent our Message_Blocks, close down</font> - <font color=red>// the Stream.</font> - <font color=red>//</font> - <font color=red>// The Stream will automagically delete the Modules and</font> - <font color=red>// the contained Tasks. We don't have to do that.</font> - <font color=red>//</font> - <font color=red>// This call will block (due to the way we've written our</font> - <font color=red>// Task class) until all Message_Blocks have cleared the</font> - <font color=red>// entire Stream, and all associated threads have exited.</font> - - theStream.close (); - - return 0; -} -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/014/stream.cpp b/docs/tutorials/014/stream.cpp deleted file mode 100644 index 86505604822..00000000000 --- a/docs/tutorials/014/stream.cpp +++ /dev/null @@ -1,169 +0,0 @@ -// $Id$ - -// Tutorial regarding a way to use ACE_Stream. -// -// written by bob mcwhirter (bob@netwrench.com) - -#include "Task.h" -#include "EndTask.h" -// This is our specialized ACE_Task. - -#include <ace/Module.h> -#include <ace/Stream.h> -#include <ace/streams.h> -// These are the neccessary ACE headers. - -typedef ACE_Module<ACE_MT_SYNCH> Module; -typedef ACE_Stream<ACE_MT_SYNCH> Stream; -// Just to avoid a lot of typing, typedefs -// are generally a good idea. - -int main (int argc, char *argv[]) -{ - int numberOfMessages = argc > 1 ? ACE_OS::atoi (argv[1]) : 3; - // unless otherwise specified, just send three messages - // down the stream. - - Stream theStream; - // the ACE_Stream itself. - - // Now, we instantiate 4 different Tasks. These do not - // need to be all the same class, but they do need to - // all derrive from the same flavor of ACE_Task. - // - // Also, we instantiate a fifth end-cap Task to clean - // up Message_Blocks as they reach the end. - - Task *taskOne; - Task *taskTwo; - Task *taskThree; - Task *taskFour; - Task *taskEnd; - - // Out Task's take two arguments: a name, and the number - // of threads to dedicate to the task. - - taskOne = new Task ("Task No. 1", 1); - taskTwo = new Task ("Task No. 2", 3); - taskThree = new Task ("Task No. 3", 7); - taskFour = new Task ("Task No. 4", 1); - - // Our EndTask only takes 1 argument, as it actually - // doesn't spawn any threads for processing. - - taskEnd = new EndTask ("End Task"); - - Module *moduleOne; - Module *moduleTwo; - Module *moduleThree; - Module *moduleFour; - Module *moduleEnd; - - // ACE_Stream accepts ACE_Modules, which are simply a pair of - // ACE_Tasks. One is dedicated for writing, while the other - // is dedicated to reading. Think of the writing side as - // downstream, and the reading side as upstream. - // - // We're only working with a unidirection Stream today, - // so we'll only actually install a Task into the write - // side of the module, effectively downstream. - - moduleOne = new Module ("Module No. 1", taskOne); - moduleTwo = new Module ("Module No. 2", taskTwo); - moduleThree = new Module ("Module No. 3", taskThree); - moduleFour = new Module ("Module No. 4", taskFour); - moduleEnd = new Module ("Module End", taskEnd); - - // Now we push the Modules onto the Stream. - // Pushing adds the module to the head, or - // otherwise prepends it to whatever modules - // are already installed. - - // So, you need to push () the modules on -backwards- - // from our viewpoint. - - if (theStream.push (moduleEnd) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "push"), -1); - } - - if (theStream.push (moduleFour) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "push"), -1); - } - - // As we push a Module onto the Stream, it gets opened. - // When a Module open ()s, it opens the Tasks that it contains. - // - // Since we cannot provide an argument to this embedded - // call to open (), we supplied specified the number of - // threads in the constructor of our Tasks. - - if (theStream.push (moduleThree) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "push"), -1); - } - - if (theStream.push (moduleTwo) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "push"), -1); - } - - if (theStream.push (moduleOne) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "push"), -1); - } - - // Now that the Modules are open, the Tasks threads should - // be launching and entering their svc () loop, so we send - // some messages down the Stream. - - int sent = 1; - - ACE_Message_Block *message; - - while (sent <= numberOfMessages) { - - // First, create ourselves a Message_Block. See Tutorials 10-13 - // for more information about Message_Blocks and Message_Queues. - // Note the use of the lock_adapter () to ensure proper - // serialization. - ACE_NEW_RETURN (message, - ACE_Message_Block (128, - ACE_Message_Block::MB_DATA, - 0, - 0, - 0, - Task::lock_adapter ()), - -1); - - // Now, we grab the write-pointer from the Block, - // and sprintf () our text into it. - - ACE_OS::sprintf (message->wr_ptr (), "Message No. %d", sent); - - // All we have to do now is drop the Message_Block - // into the Stream. - - // It is always a good idea to duplicate () a Message_Block - // when you put it into any Message_Queue, as then - // you can always be allowed to release () your copy - // without worry. - - if (theStream.put (message->duplicate (), 0) == -1) { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "put"), -1); - } - - message->release (); - ++sent; - } - - // Now that we've sent our Message_Blocks, close down - // the Stream. - // - // The Stream will automagically delete the Modules and - // the contained Tasks. We don't have to do that. - // - // This call will block (due to the way we've written our - // Task class) until all Message_Blocks have cleared the - // entire Stream, and all associated threads have exited. - - theStream.close (); - - return 0; -} diff --git a/docs/tutorials/015/015-client.dsp b/docs/tutorials/015/015-client.dsp deleted file mode 100644 index 5152df92235..00000000000 --- a/docs/tutorials/015/015-client.dsp +++ /dev/null @@ -1,138 +0,0 @@ -# Microsoft Developer Studio Project File - Name="015 client" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=015 client - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "015-client.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "015-client.mak" CFG="015 client - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "015 client - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "015 client - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "015 client - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "015 client - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"../client.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "015 client - Win32 Release"
-# Name "015 client - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=client.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Client_i.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Compressor.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Crypt.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Protocol_Stream.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Protocol_Task.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Recv.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Xmit.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=Client_i.h
-# End Source File
-# Begin Source File
-
-SOURCE=Protocol_Stream.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/015/015-server.dsp b/docs/tutorials/015/015-server.dsp deleted file mode 100644 index d9f45886fe9..00000000000 --- a/docs/tutorials/015/015-server.dsp +++ /dev/null @@ -1,166 +0,0 @@ -# Microsoft Developer Studio Project File - Name="015 server" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=015 server - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "015-server.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "015-server.mak" CFG="015 server - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "015 server - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "015 server - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "015 server - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "015 server - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"../server.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "015 server - Win32 Release"
-# Name "015 server - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=Compressor.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Crypt.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Handler.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Protocol_Stream.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Protocol_Task.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Recv.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=server.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Server_i.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=Xmit.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=Compressor.h
-# End Source File
-# Begin Source File
-
-SOURCE=Crypt.h
-# End Source File
-# Begin Source File
-
-SOURCE=Handler.h
-# End Source File
-# Begin Source File
-
-SOURCE=Protocol_Stream.h
-# End Source File
-# Begin Source File
-
-SOURCE=Protocol_Task.h
-# End Source File
-# Begin Source File
-
-SOURCE=Recv.h
-# End Source File
-# Begin Source File
-
-SOURCE=Server_i.h
-# End Source File
-# Begin Source File
-
-SOURCE=Xmit.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/015/Client_i.cpp b/docs/tutorials/015/Client_i.cpp deleted file mode 100644 index 6415fed1966..00000000000 --- a/docs/tutorials/015/Client_i.cpp +++ /dev/null @@ -1,60 +0,0 @@ - -// $Id$ - -#include "Client_i.h" -#include "ace/Message_Block.h" -#include "ace/INET_Addr.h" -#include "ace/SOCK_Connector.h" - -// Simple constructor just remembers the endpoint information for use by open. -Client::Client( u_short _port, const char * _server) - : port_(_port), server_(_server) -{ - ; -} - -/* Do nothing. This should probably call close() if we can make sure - that it's OK to close() multiple times. -*/ -Client::~Client(void) -{ - ; -} - -/* Open the connection to the server. This is traditional ACE. We - simply construct an endpoint and use a connector to establish the - link. -*/ -int Client::open( void ) -{ - ACE_INET_Addr addr(port_,server_); - ACE_SOCK_Connector con; - - if( con.connect(peer(),addr) == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_SOCK_Connector::connect()"), -1); - } - - // Something new here... We have to use the protocol stream - // to ensure that our data is in the correct format when - // received by the server. Thus, we open the stream and - // transfer ownership of the peer. - return stream().open( peer() ); -} - -// The remainder of the functions just delegate to the stream. - -int Client::close( void ) -{ - return stream().close(); -} - -int Client::put( ACE_Message_Block * _message ) -{ - return stream().put(_message,0); -} - -int Client::get( ACE_Message_Block * & _response ) -{ - return stream().get(_response); -} diff --git a/docs/tutorials/015/Client_i.h b/docs/tutorials/015/Client_i.h deleted file mode 100644 index 32eaac8dd48..00000000000 --- a/docs/tutorials/015/Client_i.h +++ /dev/null @@ -1,73 +0,0 @@ -// $Id$ - -#ifndef CLIENT_H -#define CLIENT_H - -#include "ace/SOCK_Stream.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "Protocol_Stream.h" - -class ACE_Message_Block; - -/* Hide the details of connection and protocol-conformance from the - application-level logic. -*/ -class Client -{ -public: - // Provide the server information when constructing the - // object. This could (and probably should) be moved to the - // open() method. - Client (u_short port, - const char *server); - - // Cleanup... - ~Client (void); - - // Open the connection to the server. - int open (void); - - // Close the connection to the server. Be sure to do this - // before you let the Client go out of scope. - int close (void); - - // Put a message to the server. The Client assumes ownership of - // <message> at that point and will release() it when done. Do not - // use <message> after passing it to put(). - int put (ACE_Message_Block *message); - - // Get a response from the server. The caller becomes the owner of - // <response> after this call and is responsible for invoking - // release() when done. - int get (ACE_Message_Block *&response); - -private: - // Protocol_Stream hides the protocol conformance details from us. - Protocol_Stream stream_; - - // We create a connection on the peer_ and then pass ownership of it - // to the protocol stream. - ACE_SOCK_Stream peer_; - - // Endpoing information saved by the constructor for use by open(). - u_short port_; - const char *server_; - - // Accessors for the complex member variables. - - Protocol_Stream &stream (void) - { - return this->stream_; - } - - ACE_SOCK_Stream &peer (void) - { - return this->peer_; - } -}; - -#endif /* CLIENT_H */ diff --git a/docs/tutorials/015/Compressor.cpp b/docs/tutorials/015/Compressor.cpp deleted file mode 100644 index bbe76eb1a69..00000000000 --- a/docs/tutorials/015/Compressor.cpp +++ /dev/null @@ -1,101 +0,0 @@ - -// $Id$ - -#include "Compressor.h" -#include "ace/SOCK_Stream.h" - -Compressor::Compressor( void ) - : Protocol_Task() -{ - ; -} - -Compressor::~Compressor(void) -{ - ; -} - -/* This is where you insert your compression code. Most compressors - want to work on a block of data instead of a byte-stream. - Fortunately the message block has a block that can be compressed. - Take a look at libz for a quick way to add compression to your - apps - */ -int Compressor::send(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - ACE_UNUSED_ARG(message); - ACE_UNUSED_ARG(timeout); - - ACE_DEBUG ((LM_INFO, "(%P|%t) Compressor::send() compressing (%s)\n", message->rd_ptr() )); - - // Create a block to hold the compressed data. I belive libz - // recommends a buffer about 10-20% larger than the source. - // Other libraries/algorithms may have their own quirks. - ACE_Message_Block * compressed = new ACE_Message_Block( - message->size() +16 ); - - // Perform a bogus compression algorithm. 'CD' just tells me - // that this is compressed data and when we "decompress" we'll - // look for this signature to validate the data received. - ACE_OS::sprintf( compressed->wr_ptr(), "CD:%s", message->rd_ptr() ); - compressed->wr_ptr( strlen(compressed->wr_ptr())+1 ); - - // Send the compressed data down the stream to the next module - this->put_next( compressed ); - - // We're done here. - message->release(); - - return( 0 ); -} - -/* And here's the decompression side. We've written Xmit/Recv so that - we're guaranteed to get an entire block of compressed data. If - we'd used recv() in the Recv object then we might have gotten a - partial block and that may not decompress very nicely. - */ -int Compressor::recv(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - ACE_UNUSED_ARG(message); - ACE_UNUSED_ARG(timeout); - - ACE_DEBUG ((LM_INFO, "(%P|%t) Compress::recv() decompressing (%s)\n", message->rd_ptr() )); - - // Room for the decompressed data. In the real world you - // would probably want to send the original (uncompressed) - // data size in the message. You can predict the maximum - // possible decompression size but it's cheap and easy just to - // send that along. Look again at how I do exacly that - // between Xmit and Recv. - ACE_Message_Block * decompressed = new ACE_Message_Block( - message->size() + 16 ); - - // Check for our signature. Even when you use a real - // compression algorithm you may want to include your own - // signature so that you can verify the block. It pays to be - // paranoid! - if( ACE_OS::strncmp( message->rd_ptr(), "CD:", 3 ) ) - { - ACE_DEBUG ((LM_INFO, "(%P|%t) Improperly encompressed data.\n" )); - message->release(); - return(-1); - } - - // Skip past the signature before going any further. - message->rd_ptr( 3 ); - - // Perform a bogus decompression algorithm. This is where you - // would feed to libz or your favorite decompressor. (It's - // costly but you could invoke popen() on gzip!) - ACE_OS::sprintf( decompressed->wr_ptr(), "%s", message->rd_ptr() ); - decompressed->wr_ptr( strlen(decompressed->wr_ptr())+1 ); - - // Recv the decompressed data down the stream to the next module - this->put_next( decompressed ); - - // We're done here. - message->release(); - - return( 0 ); -} - diff --git a/docs/tutorials/015/Compressor.h b/docs/tutorials/015/Compressor.h deleted file mode 100644 index cb4c7248cce..00000000000 --- a/docs/tutorials/015/Compressor.h +++ /dev/null @@ -1,35 +0,0 @@ -// $Id$ - -#ifndef COMPRESSOR_H -#define COMPRESSOR_h - -#include "Protocol_Task.h" - -/* A reallly dumb compression object. (It actually adds 3 bytes to - every message block.) -*/ -class Compressor : public Protocol_Task -{ -public: - - typedef Protocol_Task inherited; - - Compressor (void); - - ~Compressor (void); - -protected: - - // This is called when the compressor is on the downstream side. - // We'll take the message, compress it and move it along to the next - // module. - int send (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - // This one is called on the upstream side. No surprise: we - // decompress the data and send it on up the stream. - int recv (ACE_Message_Block *message, - ACE_Time_Value *timeout); -}; - -#endif /* COMPRESSOR_H */ diff --git a/docs/tutorials/015/Crypt.cpp b/docs/tutorials/015/Crypt.cpp deleted file mode 100644 index 2eb1d60d128..00000000000 --- a/docs/tutorials/015/Crypt.cpp +++ /dev/null @@ -1,83 +0,0 @@ - -// $Id$ - -#include "Crypt.h" -#include "ace/SOCK_Stream.h" - -/* The expected constructor... - */ -Crypt::Crypt( void ) - : Protocol_Task() -{ -} - -Crypt::~Crypt(void) -{ -} - -/* To send the data we'll apply a signature and encryption. - */ -int Crypt::send(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - ACE_UNUSED_ARG(timeout); - - ACE_DEBUG ((LM_INFO, "(%P|%t) Crypt::send() encrypting (%s)\n", message->rd_ptr() )); - - // I suspect that some encryptors might change the data size. - // It probably isn't safe to create a same-size destination buffer. - ACE_Message_Block * encrypted = new ACE_Message_Block( - message->size() +16 ); - - // Perform a bogus encryption algorithm and add our safety - // signature. Adding the original data size is also probably - // a good idea that I haven't encorporated here. - ACE_OS::sprintf( encrypted->wr_ptr(), "ED:%s", message->rd_ptr() ); - encrypted->wr_ptr( strlen(encrypted->wr_ptr())+1 ); - - // Send the encrypted data down the stream to the next module - this->put_next( encrypted ); - - // We're done here. - message->release(); - - return( 0 ); -} - -/* The upstream movement requires that we decrypt what the peer has - given us. -*/ -int Crypt::recv(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - ACE_UNUSED_ARG(timeout); - - ACE_DEBUG ((LM_INFO, "(%P|%t) Crypt::recv() decrypting (%s)\n", message->rd_ptr() )); - - // Create a destination for the decrypted data. The same - // block size caveat exists of course. - ACE_Message_Block * decrypted = new ACE_Message_Block( - message->size() +16 ); - - // Check the signature as expected. - if( ACE_OS::strncmp( message->rd_ptr(), "ED:", 3 ) ) - { - ACE_DEBUG ((LM_INFO, "(%P|%t) Improperly encrypted data.\n" )); - message->release(); - return(-1); - } - - // Don't forget to skip past the signature before decrypting - // or things will be quite exciting! - message->rd_ptr( 3 ); - - // Perform a bogus decryption algorithm - ACE_OS::sprintf( decrypted->wr_ptr(), "%s", message->rd_ptr() ); - decrypted->wr_ptr( strlen(decrypted->wr_ptr())+1 ); - - // Send the decrypted data down the stream to the next module - this->put_next( decrypted ); - - // We're done here. - message->release(); - - return( 0 ); -} diff --git a/docs/tutorials/015/Crypt.h b/docs/tutorials/015/Crypt.h deleted file mode 100644 index 6de997fa4a9..00000000000 --- a/docs/tutorials/015/Crypt.h +++ /dev/null @@ -1,32 +0,0 @@ -// $Id$ - -#ifndef CRYPT_H -#define CRYPT_h - -#include "Protocol_Task.h" - -/* An interface (adaptor) between your favorite encryption method and - an ACE_Stream. -*/ -class Crypt : public Protocol_Task -{ -public: - - typedef Protocol_Task inherited; - - Crypt (void); - - ~Crypt (void); - -protected: - - // Moving downstream will encrypt the data - int send (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - // And moving upstream will decrypt it. - int recv (ACE_Message_Block *message, - ACE_Time_Value *timeout); -}; - -#endif /* CRYPT_H */ diff --git a/docs/tutorials/015/Handler.cpp b/docs/tutorials/015/Handler.cpp deleted file mode 100644 index e940a8a8ce7..00000000000 --- a/docs/tutorials/015/Handler.cpp +++ /dev/null @@ -1,179 +0,0 @@ - -// $Id$ - -#include "Handler.h" -#include "Protocol_Task.h" - -/* The Protocol_Stream gives us the option to insert a Protocol_Task - to process data received by the stream. We'll get into the details - more when we talk about the stream in detail. For now it's enough - to know that Handler_Task::recv() will be invoked by the stream - after data from the client has been received and processed (eg -- - decrypted, uncompressed, and whatever else the protocol requires.) -*/ -class Handler_Task : public Protocol_Task -{ -public: - - // Typical... - typedef Protocol_Task inherited; - - // Simple... - Handler_Task(void); - ~Handler_Task(void); - -protected: - - // recv() is invoked after received data has been fully - // processed by the protocol rules. Data processing typically - // done in handle_input() can then be done here. - int recv(ACE_Message_Block * message, - ACE_Time_Value *timeout = 0); -}; - -Handler::Handler(void) -{ - ; -} - -Handler::~Handler(void) -{ - ; -} - -/* The Acceptor will open() us once the peer() connection is - established. There are a couple of things we have to do here - before we're ready to receive data from the client. -*/ -int Handler::open (void *) -{ - ACE_INET_Addr addr; - - // Make sure that we can get the peer's address. If we can't - // then there may be a network error or something else that - // will prevent communicating with the client. This is - // something you'll want to do in every event handler you create. - if (this->peer ().get_remote_addr (addr) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) Cannot get remote addr\n"), -1); - - // Announce the client - ACE_DEBUG ((LM_DEBUG, "(%P|%t) connected with %s\n", addr.get_host_name() )); - - // Here's the first new twist to the old event handler. - // Before we can use the Protocol_Stream to communicate with - // the peer, we must open() it. We provide the stream with - // the peer() so that it will have a valid socket on which to - // read client requests and send our responses. We also - // provide a Handler_Task instance that will ultimately be - // responsible for processing any client data we receive. - int rval = stream().open( this->peer(), new Handler_Task() ); - - // Of course, we have to account for the chance that the - // stream's open() may fail. - if( rval == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) Cannot open the protocol stream.\n"), -1); - } - - // Now that we know the client is valid and that the stream is - // ready for business we can register with the gloabl reactor - // instance. Here again is an opportunity for improvement if - // we expect to have mulitple Server object instances. - if (ACE_Reactor::instance()->register_handler (this, ACE_Event_Handler::READ_MASK) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) Cannot register with reactor\n"), -1); - - return rval; -} - -/* This is a fairly typical destroy() method that can be shared by - both close() and handle_close(). -*/ -void Handler::destroy (void) -{ - ACE_Reactor::instance()->remove_handler(this,ACE_Event_Handler::READ_MASK|ACE_Event_Handler::DONT_CALL); - - this->peer ().close (); - - delete this; -} - -/* In this simple application we just forward the close() and - handle_close() requests right on to the destroy() method. -*/ - -int Handler::close (u_long) -{ - this->destroy (); - return 0; -} - -int Handler::handle_close(ACE_HANDLE, ACE_Reactor_Mask) -{ - this->destroy(); - return 0; -} - -/* Unlike a "traditional" handle_input() ours is very simple. Because - of the use of the protocol stream, we delegate the read function to - the stream's get() and rely on our Handler_Task to do the real work. -*/ -int Handler::handle_input (ACE_HANDLE) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) Activity from client\n" )); - - // This will cause a blocking read from the peer(). The data - // will then be pushed through the protocol stream. - if( stream().get( ) == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) Cannot get data from protocol stream\n"), -1); - } - - return 0; -} - -/* A Protocol_Task is derived from ACE_Task and has the option of - running in one or more threads. I've chosen here to construct the - baseclass with no threads but it should work just fine with one or - more if you need. Unless you're sharing the Handler_Task with - several peers, however, you're probably just wasting a thread to - activate it. On the other hand, if your reactor is running in a - single thread (as in this example) then you can easily implement - thread-per-connection concurrency by giving the baseclass one thread. -*/ -Handler_Task::Handler_Task(void) - : inherited() -{ - ; -} - -Handler_Task::~Handler_Task(void) -{ - ; -} - -/* When installed into the protocol stream, the Handler_Task's recv() - method will be called when data is ready for processing. - */ -int Handler_Task::recv(ACE_Message_Block * message, - ACE_Time_Value *timeout ) -{ - // Announce the request we got from the client - ACE_DEBUG ((LM_INFO, "(%P|%t) Handler_Task::recv() got (%s)\n", message->rd_ptr() )); - - // Create a response message to send to the client - ACE_Message_Block * response = new ACE_Message_Block( 128 ); - - // Nothing very original about this I'm afraid... - ACE_OS::sprintf( response->wr_ptr(), "You Said: (%s)", message->rd_ptr() ); - response->wr_ptr( strlen(response->wr_ptr())+1 ); - - // Release the original message block now that we're through - // "processing" it. - message->release(); - - // Turn the message around and send it back down the Stream. - // In other words, we invoke the put() method on the - // Protocol_Stream without having to have a direct reference - // to the stream object. - return this->reply( response, timeout ); -} diff --git a/docs/tutorials/015/Handler.h b/docs/tutorials/015/Handler.h deleted file mode 100644 index 1a0f1a69e46..00000000000 --- a/docs/tutorials/015/Handler.h +++ /dev/null @@ -1,61 +0,0 @@ -// $Id$ - -#ifndef HANDLER_H -#define HANDLER_H - -#include "ace/Svc_Handler.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "ace/SOCK_Stream.h" -#include "Protocol_Stream.h" - -/* Just your basic event handler. We use ACE_Svc_Handler<> as a - baseclass so that it can maintain the peer() and other details for - us. We're not going to activate() this object, so we can get away - with the NULL synch choice. */ -class Handler : public ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> -{ -public: - Handler (void); - ~Handler (void); - - // Called by the acceptor when we're created in response to a client - // connection. - int open (void *); - - // Called when it's time for us to be deleted. We take care of - // removing ourselves from the reactor and shutting down the peer() - // connectin. - void destroy (void); - - // Called when it's time for us to go away. There are subtle - // differences between destroy() and close() so don't try to use - // either for all cases. - int close (u_long); - -protected: - // Respond to peer() activity. - int handle_input (ACE_HANDLE); - - // This will be called when handle_input() returns a failure code. - // That's our signal that it's time to begin the shutdown process. - int handle_close (ACE_HANDLE, - ACE_Reactor_Mask mask); -private: - - // Like the Client, we have to abide by the protocol requirements. - // We use a local Protocol_Stream object to take care of those - // details. For us, I/O then just becomes a matter of interacting - // with the stream. - Protocol_Stream stream_; - - Protocol_Stream &stream (void) - { - return this->stream_; - } -}; - -#endif /* HANDLER_H */ diff --git a/docs/tutorials/015/Makefile b/docs/tutorials/015/Makefile deleted file mode 100644 index 5975764d91d..00000000000 --- a/docs/tutorials/015/Makefile +++ /dev/null @@ -1,33 +0,0 @@ - -# $Id$ - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = client server - -all clean realclean : # - $(MAKE) -f Makefile.client $@ - $(MAKE) -f Makefile.server $@ - -client server : # - $(MAKE) -f Makefile.$@ all - -Depend : # - $(MAKE) -f Makefile.client $@ - -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) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend* diff --git a/docs/tutorials/015/Makefile.client b/docs/tutorials/015/Makefile.client deleted file mode 100644 index 20680aea15b..00000000000 --- a/docs/tutorials/015/Makefile.client +++ /dev/null @@ -1,79 +0,0 @@ - -# $Id$ - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = client - -FILES += Protocol_Stream -FILES += Protocol_Task -FILES += Xmit -FILES += Recv -FILES += Compressor -FILES += Crypt -FILES += Client_i - -BUILD = $(VBIN) - -SRC = $(addsuffix .cpp,$(BIN)) -SRC += $(addsuffix .cpp,$(FILES)) - -HDR = *.h - -MAKEFILE = Makefile.client -DEPEND = .depend.client - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.lib.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -HTML : # - perl ../combine *.html - -rename : # - for i in *.cxx ; do \ - n=`expr "$$i" : "\(.*\).cxx"` ;\ - mv $$i $$n.cpp ;\ - done - -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb -ts2 -bl -bli0 < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - -e 's/ / /g' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - -Depend : depend - perl ../fix.Makefile -f $(MAKEFILE) -o $(DEPEND) - -$(DEPEND) : - touch $(DEPEND) - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - -include $(DEPEND) -include .depend.client diff --git a/docs/tutorials/015/Makefile.server b/docs/tutorials/015/Makefile.server deleted file mode 100644 index 109cecc8e90..00000000000 --- a/docs/tutorials/015/Makefile.server +++ /dev/null @@ -1,81 +0,0 @@ - -# $Id$ - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = server - -FILES += Protocol_Stream -FILES += Protocol_Task -FILES += Xmit -FILES += Recv -FILES += Compressor -FILES += Crypt - -FILES += Handler -FILES += Server_i - -BUILD = $(VBIN) - -SRC = $(addsuffix .cpp,$(BIN)) -SRC += $(addsuffix .cpp,$(FILES)) - -HDR = *.h - -MAKEFILE = Makefile.server -DEPEND = .depend.server - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.lib.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -HTML : # - perl ../combine *.html - -rename : # - for i in *.cxx ; do \ - n=`expr "$$i" : "\(.*\).cxx"` ;\ - mv $$i $$n.cpp ;\ - done - -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb -ts2 -bl -bli0 < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - -e 's/ / /g' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - -Depend : depend - perl ../fix.Makefile -f $(MAKEFILE) -o $(DEPEND) - -$(DEPEND) : - touch $(DEPEND) - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - -include $(DEPEND) -include .depend.server diff --git a/docs/tutorials/015/Protocol_Stream.cpp b/docs/tutorials/015/Protocol_Stream.cpp deleted file mode 100644 index e1c210ec119..00000000000 --- a/docs/tutorials/015/Protocol_Stream.cpp +++ /dev/null @@ -1,195 +0,0 @@ -// $Id$ - -#include "Protocol_Stream.h" -#include "Protocol_Task.h" - -#include "Xmit.h" -#include "Recv.h" - -#include "Compressor.h" -#include "Crypt.h" - -#include "ace/Stream_Modules.h" - -/* You can choose at compile time to include/exclude the protocol - pieces. -*/ -#define ENABLE_COMPRESSION -#define ENABLE_ENCRYPTION - -// The usual typedefs to make things easier to type. -typedef ACE_Module<ACE_MT_SYNCH> Module; -typedef ACE_Thru_Task<ACE_MT_SYNCH> Thru_Task; - -/* An ACE_Stream is a collection of ACE_Modules. You can think of it - as a doubly-linked list if you like. Each Module contains two - ACE_Task derivatives. One of these tasks is used when sending data - "upstream", the other is used for "downstream" operation. In some - cases, you'll only need to move data in one direction. To provide - a placeholder for the other direction, ACE_Thru_Task can be used. - ACE_Thru_Task responds to the put() by simply invoking put_next() - to send the data to the next module. - */ - -/* Do-nothing constructor and destructor - */ - -Protocol_Stream::Protocol_Stream (void) -{ -} - -Protocol_Stream::~Protocol_Stream (void) -{ -} - -/* Even opening the stream is rather simple. The important thing to - remember is that the modules you push onto the stream first will be - at the tail (eg -- most downstream) end of things when you're - done. - */ -int -Protocol_Stream::open (ACE_SOCK_Stream &peer, - Protocol_Task *reader) -{ - // Initialize our peer() to read/write the socket we're given - peer_.set_handle (peer.get_handle ()); - - // Construct (and remember) the Recv object so that we can read from - // the peer(). - ACE_NEW_RETURN (recv_, - Recv ( this->peer ()), - -1); - - // Add the transmit and receive tasks to the head of the stream. As - // we add more modules these will get pushed downstream and end up - // nearest the tail by the time we're done. - if (stream ().push (new Module ("Xmit/Recv", - new Xmit ( this->peer ()), - recv_)) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "stream().push(xmit/recv)"), - -1); - - // Add any other protocol tasks to the stream. Each one is added at - // the head. The net result is that Xmit/Recv are at the tail. - if (this->open () == -1) - return -1; - - // If a reader task was provided then push that in as the upstream - // side of the next-to-head module. Any data read from the peer() - // will be sent through here last. Server applications will - // typically use this task to do the actual processing of data. - // Note the use of Thru_Task. Since a module must always have a - // pair of tasks we use this on the writer side as a no-op. - if (reader) - { - if (stream ().push (new Module ("Reader", - new Thru_Task (), - reader)) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "stream().push(reader)"), - -1); - } - - return 0; -} - -/* Add the necessary protocol objects to the stream. The way we're - pushing things on we will compress the data before encrypting it. -*/ -int -Protocol_Stream::open (void) -{ -#if defined (ENABLE_ENCRYPTION) - if (stream ().push (new Module ("crypt", - new Crypt (), - new Crypt ())) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "stream().push(crypt)"), - -1); -#endif /* ENABLE_ENCRYPTION */ - -#if defined (ENABLE_COMPRESSION) - if (stream ().push (new Module ("compress", - new Compressor (), - new Compressor ())) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "stream().push(comprssor)"), - -1); -#endif /* ENABLE_COMPRESSION */ - return 0; -} - -// Closing the Protocol_Stream is as simple as closing the ACE_Stream. -int -Protocol_Stream::close (void) -{ - return stream ().close (); -} - -// Simply pass the data directly to the ACE_Stream. -int -Protocol_Stream::put (ACE_Message_Block *&message, - ACE_Time_Value *timeout) -{ - return stream ().put (message, - timeout); -} - -/* Tell the Recv module to read some data from the peer and pass it - upstream. Servers will typically use this method in a - handle_input() method to tell the stream to get a client's request. */ - -int -Protocol_Stream::get(void) -{ - // If there is no Recv module, we're in big trouble! - if (recv_ == 0) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) No Recv object!\n"), - -1); - - // This tells the Recv module to go to it's peer() and read some - // data. Once read, that data will be pushed upstream. If there is - // a reader object then it will have a chance to process the data. - // If not, the received data will be available in the message queue - // of the stream head's reader object (eg -- - // stream().head()->reader()->msg_queue()) and can be read with our - // other get() method below. - if (recv_->get () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) Cannot queue read request\n"), - -1); - - // For flexibility I've added an error() method to tell us if - // something bad has happened to the Recv object. - if (recv_->error ()) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) Recv object error!\n"), - -1); - - return 0; -} - -/* Take a message block off of the stream head reader's message queue. - If the queue is empty, use get() to read from the peer. This is - most often used by client applications. Servers will generaly - insert a reader that will prevent the data from getting all the way - upstream to the head. */ -int -Protocol_Stream::get (ACE_Message_Block *&response, - ACE_Time_Value *timeout ) -{ - if (stream ().head ()->reader ()->msg_queue ()->is_empty () - && this->get () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) Cannot get data into the stream.\n"), - -1); - - return stream ().head ()->reader ()->getq (response, - timeout); -} diff --git a/docs/tutorials/015/Protocol_Stream.h b/docs/tutorials/015/Protocol_Stream.h deleted file mode 100644 index 5209ed68907..00000000000 --- a/docs/tutorials/015/Protocol_Stream.h +++ /dev/null @@ -1,86 +0,0 @@ -// $Id$ - -#ifndef PROTOCOL_STREAM_H -#define PROTOCOL_STREAM_H - -#include "ace/SOCK_Stream.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "ace/Stream.h" - -// Shorthand for the stream. -typedef ACE_Stream<ACE_MT_SYNCH> Stream; - -// Forward references to cut down on the number of #includes -class ACE_Message_Block; -class Recv; -class Protocol_Task; - -/* The Protocol_Stream provides a tidy interface to an ACE_Stream - setup to process a data block through a series of protocol stages. -*/ -class Protocol_Stream -{ -public: - Protocol_Stream (void); - ~Protocol_Stream (void); - - // Provide the stream with an ACE_SOCK_Stream on which it can - // communicate. If _reader is non-null, it will be added as the - // reader task just below the stream head so that it can process - // data read from the peer. - int open (ACE_SOCK_Stream &peer, - Protocol_Task *reader = 0); - - // Close the stream. All of the tasks & modules will also be - // closed. - int close (void); - - // putting data onto the stream will pass it through all protocol - // levels and send it to the peer. - int put (ACE_Message_Block *&message, - ACE_Time_Value *timeout = 0); - - // get will cause the Recv task (at the tail of the stream) to read - // some data from the peer and pass it upstream. The message block - // is then taken from the stream reader task's message queue. - int get (ACE_Message_Block *&response, - ACE_Time_Value *timeout = 0); - - // Tell the Recv task to read some data and send it upstream. The - // data will pass through the protocol tasks and be queued into the - // stream head reader task's message queue. If you've installed a - // _reader in open() then that task's recv() method will see the - // message and may consume it instead of passing it to the stream - // head for queueing. - int get (void); - - ACE_SOCK_Stream &peer (void) - { - return this->peer_; - } - -private: - // Our peer connection - ACE_SOCK_Stream peer_; - - // The stream managing the various protocol tasks - Stream stream_; - - // A task which is capable of receiving data on a socket. - // Note that this is only useful by server-side applications. - Recv *recv_; - - Stream &stream (void) - { - return this->stream_; - } - - // Install the protocol tasks into the stream. - int open (void); -}; - -#endif /* PROTOCOL_STREAM_H */ diff --git a/docs/tutorials/015/Protocol_Task.cpp b/docs/tutorials/015/Protocol_Task.cpp deleted file mode 100644 index 6060fb1ddfa..00000000000 --- a/docs/tutorials/015/Protocol_Task.cpp +++ /dev/null @@ -1,79 +0,0 @@ - -// $Id$ - -#include "Protocol_Task.h" -#include "ace/ACE.h" - -// Construct the object and remember the thread count. -Protocol_Task::Protocol_Task(void) -{ - ; -} - -Protocol_Task::~Protocol_Task(void) -{ - ; -} - -int Protocol_Task::open(void *arg) -{ - ACE_UNUSED_ARG(arg); - - return(0); -} - -int Protocol_Task::close(u_long flags) -{ - ACE_UNUSED_ARG(flags); - return 0; -} - -/* When a message is put() onto the task, it's time to process() some data. -*/ -int Protocol_Task::put(ACE_Message_Block *message,ACE_Time_Value *timeout) -{ - return this->process(message,timeout); -} - -/* Return an error since we don't want the task to ever be activated. - */ -int Protocol_Task::svc(void) -{ - return -1; -} - -/* There's nothing really magic about process(). We just decide if - we're moving data upstream or downstream and invoke the appropriate - virtual function to handle it. -*/ -int Protocol_Task::process(ACE_Message_Block * message, ACE_Time_Value *timeout) -{ - if( this->is_writer() ) - { - return this->send(message,timeout); - } - - return this->recv(message,timeout); -} - -/* We must insist that derivatives provide a meaningful overload for - these methods. It's fairly common for ACE object methods to return - an error when an overload is expected but the method cannot be - safely made pure virtual. - */ - -int Protocol_Task::send(ACE_Message_Block *message, - ACE_Time_Value *timeout) -{ - ACE_UNUSED_ARG(message); - ACE_UNUSED_ARG(timeout); - return -1; -} - -int Protocol_Task::recv(ACE_Message_Block * message, - ACE_Time_Value *timeout) -{ - ACE_UNUSED_ARG(message); - ACE_UNUSED_ARG(timeout); - return -1; -} diff --git a/docs/tutorials/015/Protocol_Task.h b/docs/tutorials/015/Protocol_Task.h deleted file mode 100644 index 2ea7d339eb8..00000000000 --- a/docs/tutorials/015/Protocol_Task.h +++ /dev/null @@ -1,60 +0,0 @@ -// $Id$ - -#ifndef PROTOCOL_TASK_H -#define PROTOCOL_TASK_H - -#include "ace/Task.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -/* A typical ACE_Task<> derivative that adds a few things appropriate - to protocol stacks. To keep things a little simpler, we prevent - activation of the task and just borrow the thread of control from - the calling method in all cases. -*/ -class Protocol_Task : public ACE_Task<ACE_MT_SYNCH> -{ -public: - typedef ACE_Task<ACE_MT_SYNCH> inherited; - - Protocol_Task (void); - - ~Protocol_Task (void); - - // open() is invoked when the task is inserted into the stream. - virtual int open (void *arg); - - // close() is invoked when the stream is closed (flags will be set - // to '1') and when the svc() method exits (flags will be '0'). - virtual int close (u_long flags); - - // As data travels through the stream, the put() method of each task - // is invoked to keep the data moving along. - virtual int put (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - // We're obligated to provide this signature even though we won't be - // allowing this object to be activated. - virtual int svc (void); - -protected: - - // Called by put() or svc() as necessary to process a block of data. - int process (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - // Tasks on the writer (downstream) side of the stream are called - // upon to send() data that will ultimately go to the peer. - virtual int send (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - // Tasks on the reader (upstream) side will be receiving data that - // came from the peer. - virtual int recv (ACE_Message_Block *message, - ACE_Time_Value *timeout); - -}; - -#endif /* PROTOCOL_TASK_H */ diff --git a/docs/tutorials/015/Recv.cpp b/docs/tutorials/015/Recv.cpp deleted file mode 100644 index 0cf739e7d25..00000000000 --- a/docs/tutorials/015/Recv.cpp +++ /dev/null @@ -1,93 +0,0 @@ - -// $Id$ - -#include "Recv.h" -#include "ace/SOCK_Stream.h" - -/* Construct the object with the peer reference and other appropriate - initializations. -*/ -Recv::Recv( ACE_SOCK_Stream & _peer ) - : Protocol_Task(), peer_(_peer), error_(0) -{ - // Create the tickler that get() will use to trigger recv() - // through the baseclass. Since we're single-threaded this is - // probably overkill but it makes multi-threading easier if we - // choose to do that. - tickler_ = new ACE_Message_Block(1); -} - -/* Be sure we manage the lifetime of the tickler to prevent a memory - leak. -*/ -Recv::~Recv(void) -{ - tickler_->release(); -} - -/* By putting the tickler to ourselves we cause things to happen in - the baseclass that will invoke recv(). If we know we're single - threaded we could directly call recv() and be done with it but then - we'd have to do something else if we're multi-threaded. Just let - the baseclass worry about those things! -*/ -int Recv::get(void) -{ - return this->put( tickler_, 0 ); -} - -int Recv::recv(ACE_Message_Block * message, ACE_Time_Value *timeout) -{ - int rval; - - /* Xmit will send us the message length in clear-text. I - assume that will be less than 32-bytes! - */ - char msize[32]; - int b = 0; - - /* Read from the socket one byte at a time until we see then - end-of-string NULL character. Since the OS layers (at least - in Unix) will provide some buffering this isn't as bad as - it may seem at first. - - The byte-at-a-time recv breaks horribly on Win32 where the - WFMO_Reactor is used. This is because the socket has been - placed into non-blocking mode and only the recv() of the - first byte will block. The solution is to use - ACE_Select_Reactor which doesn't change the socket - characteristics. We did that back in main(), so we should - be in good shape now. - */ - do - { - rval = this->peer().recv( &msize[b], 1, timeout ); - if( rval == -1 ) - { - error_ = 1; - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Recv::recv() Failed to get message size."), -1); - } - } - while( msize[b++] != 0 ); - - int size = ACE_OS::atoi(msize); - - // Make a block big enough to contain the data we'll read - message = new ACE_Message_Block( size ); - - // Read the actual message data into our new message block - rval = this->peer().recv_n( message->wr_ptr(), size, 0, timeout ); - - // If we got the data correctly then send it on upstream. - if( rval > 0 ) - { - message->wr_ptr( rval ); - return( this->put_next( message ) ); - } - - // Something bad happend on the recv_n(). Set an error flag - // and return error. - error_ = 1; - - return( -1 ); -} diff --git a/docs/tutorials/015/Recv.h b/docs/tutorials/015/Recv.h deleted file mode 100644 index 3e65b3ecb1e..00000000000 --- a/docs/tutorials/015/Recv.h +++ /dev/null @@ -1,58 +0,0 @@ -// $Id$ - -#ifndef RECV_H -#define RECV_h - -#include "Protocol_Task.h" - -class ACE_SOCK_Stream; - -/* Get some data from the peer and send it upstream for - de-protocol-ization. -*/ -class Recv : public Protocol_Task -{ -public: - typedef Protocol_Task inherited; - - // Give it someone to talk to... - Recv (ACE_SOCK_Stream &peer); - ~Recv (void); - - // Trigger a read from the socket - int get (void); - - // In some cases it might be easier to check the "state" of the Recv - // object than to rely on return codes filtering back to you. - int error (void) - { - return this->error_; - } - -protected: - - ACE_SOCK_Stream &peer (void) - { - return this->peer_; - } - - // The baseclass will trigger this when our get() method is called. - // A message block of the appropriate size is created, filled and - // passed up the stream. - int recv (ACE_Message_Block *message, - ACE_Time_Value *timeout = 0); - -private: - // Our endpoint - ACE_SOCK_Stream &peer_; - - // get() uses a bogus message block to cause the baseclass to invoke - // recv(). To avoid memory thrashing, we create that bogus message - // once and reuse it for the life of Recv. - ACE_Message_Block *tickler_; - - // Our error flag (duh) - int error_; -}; - -#endif /* RECV_H */ diff --git a/docs/tutorials/015/Server_i.cpp b/docs/tutorials/015/Server_i.cpp deleted file mode 100644 index 5de37d07e85..00000000000 --- a/docs/tutorials/015/Server_i.cpp +++ /dev/null @@ -1,75 +0,0 @@ - -// $Id$ - -#include "Server_i.h" - -/* We have to allocate space for our static finished_ flag. We also - initialize it to 'false' so that we don't exit immediately. -*/ -sig_atomic_t Server::finished_ = 0; - -/* The simple constructor and destructor don't do anything but give us - a place to expand in the future if we want. -*/ -Server::Server(void) -{ - ; -} - -Server::~Server(void) -{ - ; -} - -/* Opening the server is as simple as opening the acceptor with the - default ACE_Reactor instance. If we want to allow multiple - instances of Server objects then we should have an ACE_Reactor - member variable that we can register with. -*/ -int Server::open(void) -{ - if (acceptor_.open (ACE_INET_Addr (ACE_DEFAULT_SERVER_PORT), ACE_Reactor::instance()) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), -1); - - return(0); -} - -/* Running the server just means that we execute the basic event - loop for the reactor. Again, if we had a private reactor then we - could have multiple server's in their run() method. -*/ -int Server::run(void) -{ - ACE_DEBUG ((LM_DEBUG, "(%P|%t) starting up server daemon\n")); - - // Here's the basic event loop. I have a 2-second timeout on - // the handle_events() so that we don't have to wait too long - // when we set the finished_ flag. - while (!finished_) - { - // Some (all?) platforms return the "remaining time" in the - // timeout parameter. If we don't reset it each time, we - // will end up with a 100% CPU spin loop! - ACE_Time_Value timeout(2); - - ACE_Reactor::instance()->handle_events (&timeout); - } - - // Close the acceptor when we're done. This may be handled by - // the framework but it's good practice to be explicit about things. - acceptor_.close(); - - ACE_DEBUG ((LM_DEBUG, "(%P|%t) shutting down server daemon\n")); - - return 0; -} - -/* The close() method simply sets the finished_ flag so that run() - will leave the event loop and exit. -*/ -int Server::close(void) -{ - finished_ = 1; - ACE_Reactor::instance()->notify(); - return(0); -} diff --git a/docs/tutorials/015/Server_i.h b/docs/tutorials/015/Server_i.h deleted file mode 100644 index 2a77c611565..00000000000 --- a/docs/tutorials/015/Server_i.h +++ /dev/null @@ -1,50 +0,0 @@ -// $Id$ - -#ifndef SERVER_H -#define SERVER_H - -#include "ace/Acceptor.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "ace/SOCK_Acceptor.h" -#include "Handler.h" - -/* Anytime I have templates I try to remember to create a typedef for - the parameterized object. It makes for much less typing later! -*/ -typedef ACE_Acceptor <Handler, ACE_SOCK_ACCEPTOR> Acceptor; - -class Server -{ -public: - // Our simple constructor takes no parameters. To make the - // server a bit more useful, you may want to pass in the - // TCP/IP port to be used by the acceptor. - Server (void); - ~Server (void); - - // Open the server for business - int open (void); - - // Close all server instances by setting the finished_ flag. - // Actually, the way this class is written, you can only have - // one instance. - static int close (void); - - // Run the server's main loop. The use of the gloabl ACE_Reactor by - // this method is what limits us to one Server instance. - int run (void); - -private: - // This will accept client connection requests and instantiate a - // Handler object for each new connection. - Acceptor acceptor_; - - // Our shutdown flag - static sig_atomic_t finished_; -}; - -#endif /* SERVER_H */ diff --git a/docs/tutorials/015/Xmit.cpp b/docs/tutorials/015/Xmit.cpp deleted file mode 100644 index 28be01b1d25..00000000000 --- a/docs/tutorials/015/Xmit.cpp +++ /dev/null @@ -1,84 +0,0 @@ - -// $Id$ - -#include "Xmit.h" -#include "ace/SOCK_Stream.h" - -/* Construct the object with the peer connection and choose not to - activate ourselves into a dedicated thread. You might get some - performance gain by activating but if you really want a - multi-threaded apprroach you should handle that as a separate - issue. Attempting to force threading at this level will likely - cause more trouble than you want to deal with. -*/ -Xmit::Xmit( ACE_SOCK_Stream & _peer ) - : Protocol_Task(), peer_(_peer) -{ -} - -Xmit::~Xmit(void) -{ -} - -/* Check to see if we're being closed by the stream (flags != 0) or if - we're responding to the exit of our svc() method. -*/ -int Xmit::close(u_long flags) -{ - // Take care of the baseclass closure. - int rval = inherited::close(flags); - - // Only if we're being called at the stream shutdown do we close - // the peer connection. If, for some reason, we were activated - // into one or more threads we wouldn't want to close the pipe - // before all threads had a chance to flush their data. - if( flags ) - { - peer().close(); - } - - return( rval ); -} - -/* Our overload of send() will take care of sending the data to the - peer. -*/ -int Xmit::send(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - int rval; - - ACE_DEBUG ((LM_INFO, "(%P|%t) Xmit::send() sending (%s)(%d)\n", message->rd_ptr(), message->length() )); - - /* Since we're going to be sending data that may have been - compressed and encrypted it's probably important for the - receiver to get an entire "block" instead of having a - partial read. - - For that reason, we'll send the length of the message block - (in clear-text) to the peer so that it can then recv_n() - the entire block contents in one read operation. - */ - char msize[32]; - sprintf(msize,"%d",message->length()); - - // Be sure we send the end-of-string NULL so that Recv will - // know when to stop assembling the length. - rval = this->peer().send_n( msize, strlen(msize)+1, 0, timeout ); - - if( rval == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Xmit::send() Failed to send message size."), -1); - } - - /* Now we send the actual data. If you're worried about - network efficiency then you may choose to create one buffer - containing msize and the message data and send it all at - once. - */ - rval = this->peer().send_n( message->rd_ptr(), message->length(), 0, timeout ); - - // Release the message block since we're done with it. - message->release(); - - return( rval ); -} diff --git a/docs/tutorials/015/Xmit.h b/docs/tutorials/015/Xmit.h deleted file mode 100644 index 356bacf25b9..00000000000 --- a/docs/tutorials/015/Xmit.h +++ /dev/null @@ -1,46 +0,0 @@ -// $Id$ - -#ifndef XMIT_H -#define XMIT_h - -#include "Protocol_Task.h" - -// Forward reference reduces #include dependencies -class ACE_SOCK_Stream; - -/* A class suitable for sending data to a peer from within an - ACE_Stream. - */ -class Xmit : public Protocol_Task -{ -public: - typedef Protocol_Task inherited; - - // We must be given a valid peer when constructed. Without that we - // don't know who to send data to. - Xmit (ACE_SOCK_Stream &peer); - ~Xmit (void); - - // As you know, close() will be called in a couple of ways by the - // ACE framework. We use that opportunity to terminate the - // connection to the peer. - int close (u_long flags); - -protected: - - ACE_SOCK_Stream &peer (void) - { - return this->peer_; - } - - // Send the data to the peer. By now it will have been completely - // protocol-ized by other tasks in the stream. - int send (ACE_Message_Block *message, - ACE_Time_Value *timeout); - -private: - // A representation of the peer we're talking to. - ACE_SOCK_Stream &peer_; -}; - -#endif /* XMIT_H */ diff --git a/docs/tutorials/015/client.cpp b/docs/tutorials/015/client.cpp deleted file mode 100644 index 93041dcdfdd..00000000000 --- a/docs/tutorials/015/client.cpp +++ /dev/null @@ -1,70 +0,0 @@ - -// $Id$ - -/* The Client object will implement the nasty details of connecting to - communicating with the server -*/ -#include "Client_i.h" - -int main(int argc, char *argv[]) -{ - // How many messages will we send? - int mcount = argc > 1 ? ACE_OS::atoi(argv[1]) : 3; - - // Construct a Client with our desired endpoint. - Client client(ACE_DEFAULT_SERVER_PORT,ACE_DEFAULT_SERVER_HOST); - - // Attempt to open the connection to the server. - if( client.open() == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Client::open()"), -1); - } - - // Send a few messages to the server and get some responses... - for( int i = 0 ; i < mcount ; ++i ) - { - // Since we'll be using a Protocol Stream (even though we - // don't know that at this level) we require the use of - // ACE_Message_Block objects to send/receive data. - ACE_Message_Block * message = new ACE_Message_Block( 128 ); - - // Construct a silly message to send to the server. - // Notice that we're careful to add one to the strlen() so - // that we also send the end-of-string NULL character. - ACE_OS::sprintf (message->wr_ptr (), "This is message %d.", i); - message->wr_ptr (strlen (message->rd_ptr ())+1); - - // client will take ownership of the message block so that - // we don't have to remember to release(). We *do* have - // to remember not to use it after put() since it may be - // released almost immediately. - client.put( message ); - - ACE_Message_Block * response; - - // get() takes an ACE_Message_Block pointer reference. We then - // assume ownership of it and must release() when we're done. - if( client.get( response ) == -1 ) - { - ACE_DEBUG ((LM_INFO, "(%P|%t) Failed to get response from server\n" )); - break; - } - - ACE_DEBUG ((LM_INFO, "(%P|%t) The server's response: (%s)\n", - response->rd_ptr())); - - // Now that we're through with the response we have to - // release() it to avoid memory leaks. - response->release(); - } - - ACE_DEBUG ((LM_INFO, "(%P|%t) Shutting down the stream\n" )); - - // Before we exit, it's a good idea to properly close() the connection. - if( client.close() == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Client::close()"), -1); - } - - return(0); -} diff --git a/docs/tutorials/015/combine.shar b/docs/tutorials/015/combine.shar deleted file mode 100644 index 3116b69e7d6..00000000000 --- a/docs/tutorials/015/combine.shar +++ /dev/null @@ -1,1063 +0,0 @@ -#!/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 2000-04-09 01:31 EDT by <jcej@chiroptera.tragus.org>. -# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/015'. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 414 -rw-rw-r-- hdr -# 419 -rw-rw-r-- bodies -# 4225 -rw-rw-r-- page01.pre -# 194 -rw-rw-r-- page02.pre -# 318 -rw-rw-r-- page03.pre -# 178 -rw-rw-r-- page04.pre -# 302 -rw-rw-r-- page05.pre -# 415 -rw-rw-r-- page06.pre -# 321 -rw-rw-r-- page07.pre -# 500 -rw-rw-r-- page08.pre -# 638 -rw-rw-r-- page09.pre -# 976 -rw-rw-r-- page10.pre -# 334 -rw-rw-r-- page11.pre -# 49 -rw-rw-r-- page12.pre -# 325 -rw-rw-r-- page13.pre -# 539 -rw-rw-r-- page14.pre -# 769 -rw-rw-r-- page15.pre -# 659 -rw-rw-r-- page16.pre -# 213 -rw-rw-r-- page17.pre -# 372 -rw-rw-r-- page18.pre -# 281 -rw-rw-r-- page19.pre -# 355 -rw-rw-r-- page20.pre -# 151 -rw-rw-r-- page21.pre -# 2563 -rw-rw-r-- page22.pre -# 406 -rw-rw-r-- page04.pst -# 616 -rw-rw-r-- page09.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 _sh16810; 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 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> -X -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> -X -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 04090120100 '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' -41322d388f7bb6c8eba031c4a6ab53ce hdr -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`" - test 414 -eq "$shar_count" || - $echo 'hdr:' 'original size' '414,' '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' && -# -# The client application specific files -# -PAGE=2 -client.cpp -Client_i.h -Client_i.cpp -# -# The server application specific files -# -server.cpp -Server_i.h -Server_i.cpp -Handler.h -Handler.cpp -# -# The basic protocol stream -# -Protocol_Stream.h -Protocol_Stream.cpp -Protocol_Task.h -Protocol_Task.cpp -# -# Send/Receive objects -# -XXmit.h -XXmit.cpp -Recv.h -Recv.cpp -# -# Protocol objects -# -Compressor.h -Compressor.cpp -Crypt.h -Crypt.cpp -SHAR_EOF - $shar_touch -am 1022205498 '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' -a6c99d6567b0640ad524b196dc43647e bodies -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`" - test 419 -eq "$shar_count" || - $echo 'bodies:' 'original size' '419,' '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 -In a typical client/server system you will be sending and receiving -X data. That's the whole point after all. -<P> -In the client/server tutorials that we've done so far it was just a -X matter of sending a buffer of data to the peer. This was done -X with the send*() and recv*() methods of the ACE_SOCK* objects. -<P> -In a more robust system, one might want to process the data before -X sending it to a peer and "unprocess" it after reading from a -X peer. These processing steps might include encryption, -X compression, applying checksums or any number of other actions. -<P> -In this tutorial a Protocol_Stream object is created to encrypt and -X compress* data being sent between peers. Both client and server -X applications are presented as well. I present the application -level code first and then go into the details of the protocol stream -and it's helper objects. If the stream stuff in the application logic -is confusing then just read on by and come back to it after the later -discussions. -<P> -Disclaimer: -<br> -<ul> -Several folks have reported problems with this tutorial on Win32. -There are a couple of ways to solve this. I've chosen to solve it by -using the ACE_Select_Reactor on all platforms instead of taking the -OS-default. -</ul> -<P> -Kirthika's abstract: -<UL> -The Protocol Stream model consists of a stream layer which pushes the -data towards the underlying SOCK_Stream thru the stages of encryption -and compression. This data is received at the other end of the -SOCK_Stream and sent up to its Protocol_Stream layer via the stages of -decompression and decryption and an optional Reader task. This is very -similar to the model of the TCP/IP stack (specifically the datalink to -physical layer portion). -<P> -ACE_Message_Blocks are used to communicate between the client and the -server across the Protocol Stream, which abstracts the protocol -conformance details. The underlying SOCK_Stream is used to set up the -connection using the ACE_SOCK_Connector class. Once the connector -completes its job, the SOCK_Stream pointer is passed on to the -Protocol Stream which now takes over. The Client has put() and get() -methods to send and receive data from the server. -<P> -The server is implemented using the ACE_Acceptor to listen at the port -for connections and a reactor for delegating events to the appropriate -event handler. The handle_input () method of the handler simply allows -the stream to receive the data and hand it over to the Handler_Task (a -derivative of the ACE_Task) which will then process it. -<P> -The implementation of this Protocol Stream model is done using the -ACE_Module class. The module for Xmit/Recv is shoved in first -into the stream, followed by the encryption and compression modules. The -optional Reader if defined is bundled with a dummy task -(ACE_Thru_Task class) into a module. The get() and put() methods do -the job of reading and writing to the Stream. Each module is made up -of a pair of Protocol Tasks. A Protocol Task is a derivative of the -ACE_Task and whose recv() and send() methods need to be filled to -perform the appropriate task. -<P> -The Xmit object derives from the Protocol task and has a send() method -which does the task of transmitting data to the underlying -SOCK_Stream. Keeping the fragmentation and reassembly issues in mind, -block-size is also sent across with the block of data. -The Recv object uses a dummy Message Block to provoke the Protocol -Task object to call the recv() on it. This is done by being -foresighted about the use of mutliple threads instead of a single -thread. -<P> -The compression/decompression is bundled in a single Protocol Task -object with the send () method doing the compression and the recv() -doing the decompression. Similarly, the encrption/decryption is done -using a single Protocol Task object. -<P> -This tutorial provides a glimpse on how to design and implement a -protocol in layers and also revises a lot of what has been learnt until -now from the previous tutorials. -(for instance, Message_Block, Task, Acceptor, Connector, Event_Handler -etc.) -</UL> -<P> -<font size=-1>* Ok, I didn't really implement encryption and -X compression objects. I'll leave that as a thought -X exercise!</font> -SHAR_EOF - $shar_touch -am 04090120100 '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' -693002c5a94ef0d514f8b6c4bf2ea36e page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 4225 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '4225,' '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 take a look first at the client application. As usual, our goal -X is to keep the main() application as simple as possible and -X delegate the tricky stuff to another object. -X -<HR> -SHAR_EOF - $shar_touch -am 04090120100 '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' -6a2e64962c95b349625f418502c95952 page02.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`" - test 194 -eq "$shar_count" || - $echo 'page02.pre:' 'original size' '194,' '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' && -The Client object is designed to hide all of the messy connection -X logic from it's users. It also provides put/get methods for -X sending data to the server and receiving the server's response. -X Note the Protocol_Stream member that will take care of -X converting and sending/receiving the data. -<HR> -SHAR_EOF - $shar_touch -am 04090120100 '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' -95326c064b10bbda428d3c967f285760 page03.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`" - test 318 -eq "$shar_count" || - $echo 'page03.pre:' 'original size' '318,' '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' && -The implementation of the Client object. Only the open() method -X really does any work. The other methods simply delegate their -X function to the Protocol_Stream. -<HR> -SHAR_EOF - $shar_touch -am 04090120100 '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' -2955ca8d3b0fc6840f3d371aea528b8d page04.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`" - test 178 -eq "$shar_count" || - $echo 'page04.pre:' 'original size' '178,' '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' && -Like the client, we want to keep the main() part of our server code as -X simple as possible. This is done by putting most of the work -X into the Handler object that will deal with client connections. -XFrom the looks of the code below, I think we've been successful in our -simplification. -<HR> -X -SHAR_EOF - $shar_touch -am 04090120100 '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' -7413a66059d2bd31c99b6414cfa9faef page05.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`" - test 302 -eq "$shar_count" || - $echo 'page05.pre:' 'original size' '302,' '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' && -The Server object exists in order simplify the -main() application level. To that end, it hides the details of -creating an acceptor and managing the reactor. -<P> -The static close() method available for a signal handler as you saw on -the previous page. Of course the assumption here is that there would -only be one Server instance but since you can't provide a TCP/IP port, -that's probably a valid assumption! -<HR> -SHAR_EOF - $shar_touch -am 04090120100 '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' -af07f1b6fd76a7bd82ca2eb679ebe482 page06.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page06.pre'`" - test 415 -eq "$shar_count" || - $echo 'page06.pre:' 'original size' '415,' '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' && -And now the implementation of Server. This is actually just the -main() code from a previous tutorial broken into appropriate method -calls. It may seem silly to do this rather than keeping the stuff in -main() but you'll find that you have less trouble enhancing an -application when you take this sort of approach. -<HR> -X -SHAR_EOF - $shar_touch -am 04090120100 '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' -7dfb75884939c3c05ee1e1000956e9f4 page07.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page07.pre'`" - test 321 -eq "$shar_count" || - $echo 'page07.pre:' 'original size' '321,' 'current size' "$shar_count!" - fi -fi -# ============= page08.pre ============== -if test -f 'page08.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page08.pre' '(file already exists)' -else - $echo 'x -' extracting 'page08.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page08.pre' && -The Handler object is our event handler. You can use either -ACE_Event_Handler or ACE_Svc_Handler<> for the baseclass. I generally -prefer the latter since it takes care of some housekeeping that I -would otherwise be responsible for. -<P> -The class declaration is taken almost exactly from a previous -tutorial. A good design will have a simple handler object that will -collect data from the peer and pass it along to another object for -processing. Again, keep it simple and delegate authority. -<HR> -SHAR_EOF - $shar_touch -am 04090120100 'page08.pre' && - chmod 0664 'page08.pre' || - $echo 'restore of' 'page08.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 'page08.pre:' 'MD5 check failed' -8e5bd08125af0eb8b2a8ac6fa1cd6773 page08.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page08.pre'`" - test 500 -eq "$shar_count" || - $echo 'page08.pre:' 'original size' '500,' 'current size' "$shar_count!" - fi -fi -# ============= page09.pre ============== -if test -f 'page09.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page09.pre' '(file already exists)' -else - $echo 'x -' extracting 'page09.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page09.pre' && -Like any other event handler, the handle_input() method will be -responsible for getting data from the peer() and doing something with -it. In this case, we have a Protocol_Stream to deal with. We'll use -the stream for the actual I/O but we are ultimately responsible for -processing the data from the peer. To do that, we've created a -Handler_Task that fits within the Protocol_Stream framework to process -data that has been received. Handler::handle_input() will tell the stream that -it's time to read data and that data will eventually show up at -Handler_Task::recv() where we'll process it as required by our -application logic. -<HR> -SHAR_EOF - $shar_touch -am 04090120100 'page09.pre' && - chmod 0664 'page09.pre' || - $echo 'restore of' 'page09.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 'page09.pre:' 'MD5 check failed' -4157b3795510b693de745d3fa9890418 page09.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page09.pre'`" - test 638 -eq "$shar_count" || - $echo 'page09.pre:' 'original size' '638,' 'current size' "$shar_count!" - fi -fi -# ============= page10.pre ============== -if test -f 'page10.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page10.pre' '(file already exists)' -else - $echo 'x -' extracting 'page10.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page10.pre' && -And so finally we come to the Protocol_Stream. That, after all, is -the focus of the entire tutorial but it took us half of the day to get -here! -<P> -The Protocol_Stream uses an ACE_Stream to move an ACE_Message_Block -through a series of tasks. Each task in the stream is responsible for -performing some operation on the data in the message block. That is -the nature of a protocol stream (or "stack" if you prefer). In this -stream, the data is compressed and encrypted* on its way between -peers. We also allow users of the stream to install a reader task to -handle data that percolates up from the peer. As you saw a page or -two ago, this is most useful for a server. -X -<P> -<font size=-1>*Again, I just pretend to do these things. It would -take another day or two to go through any sort of reasonable -encryption or compression!</font> -<P> -Before we get into the code, here's a picture that's shows what's -going on here. -<P><center><img src="stream.gif"></center></p> -<HR> -SHAR_EOF - $shar_touch -am 04090120100 'page10.pre' && - chmod 0664 'page10.pre' || - $echo 'restore of' 'page10.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 'page10.pre:' 'MD5 check failed' -cd2042fe28f3ec83a293de6d795b6804 page10.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page10.pre'`" - test 976 -eq "$shar_count" || - $echo 'page10.pre:' 'original size' '976,' 'current size' "$shar_count!" - fi -fi -# ============= page11.pre ============== -if test -f 'page11.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page11.pre' '(file already exists)' -else - $echo 'x -' extracting 'page11.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page11.pre' && -And now the implementation of the Protocol_Stream. There are more -lines of code here than we've seen so far but it still isn't -complicated. The basic idea is to construct the ACE_Stream with our -set of protocol objects that will manipulate the data. Our primary -concern in this file is to get everything in the correct order! -<HR> -SHAR_EOF - $shar_touch -am 04090120100 'page11.pre' && - chmod 0664 'page11.pre' || - $echo 'restore of' 'page11.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 'page11.pre:' 'MD5 check failed' -b0e968102fb417b12710e99465f4e387 page11.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page11.pre'`" - test 334 -eq "$shar_count" || - $echo 'page11.pre:' 'original size' '334,' 'current size' "$shar_count!" - fi -fi -# ============= page12.pre ============== -if test -f 'page12.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page12.pre' '(file already exists)' -else - $echo 'x -' extracting 'page12.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page12.pre' && -A quick look at the Protocol_Task header... -<HR> -SHAR_EOF - $shar_touch -am 04090120100 'page12.pre' && - chmod 0664 'page12.pre' || - $echo 'restore of' 'page12.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 'page12.pre:' 'MD5 check failed' -5258df32a7fddcecfe902aec8440f98f page12.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page12.pre'`" - test 49 -eq "$shar_count" || - $echo 'page12.pre:' 'original size' '49,' 'current size' "$shar_count!" - fi -fi -# ============= page13.pre ============== -if test -f 'page13.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page13.pre' '(file already exists)' -else - $echo 'x -' extracting 'page13.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page13.pre' && -The Protocol_Task implementation takes care of the open(), close(), -put() and svc() methods so that derivatives can concentrate on the -send() and recv() methods. After a while you find that most -ACE_Task<> derivatives look very similar in the four basic methods and -only need one or two additional to do any real work. -<HR> -SHAR_EOF - $shar_touch -am 04090120100 'page13.pre' && - chmod 0664 'page13.pre' || - $echo 'restore of' 'page13.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 'page13.pre:' 'MD5 check failed' -3dd6383ba5c5d97e74a7ace5f44b0b33 page13.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page13.pre'`" - test 325 -eq "$shar_count" || - $echo 'page13.pre:' 'original size' '325,' 'current size' "$shar_count!" - fi -fi -# ============= page14.pre ============== -if test -f 'page14.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page14.pre' '(file already exists)' -else - $echo 'x -' extracting 'page14.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page14.pre' && -The Xmit object knows how to send data to the peer. It sits at the -tail of the stream and gets everything that flows down from the head. -In keeping with the spirit of things, this object does only one thing -and doesn't concern itself with anyone else' details. -<P> -The only thing you might want to do is combine it with Recv. Why? -As you'll realize in a page or two, the Xmit and Recv objects must -interact if you're going to ensure a safe transit. By having a single -object it's easier to coordinate and maintain the interaction. -<HR> -SHAR_EOF - $shar_touch -am 04090120100 'page14.pre' && - chmod 0664 'page14.pre' || - $echo 'restore of' 'page14.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 'page14.pre:' 'MD5 check failed' -aa057b88a7c770d1a15721cecbf91032 page14.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page14.pre'`" - test 539 -eq "$shar_count" || - $echo 'page14.pre:' 'original size' '539,' 'current size' "$shar_count!" - fi -fi -# ============= page15.pre ============== -if test -f 'page15.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page15.pre' '(file already exists)' -else - $echo 'x -' extracting 'page15.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page15.pre' && -The implementation of Xmit isn't too complicated. If we choose to -combine it with the Recv task we simply lift the recv() method from -that object and drop it into this one. -<P> -Note that close() must decide if it's being called when the stream is -shutdown or when it's svc() method exits. Since we tell the baseclass -not to use any threads it's a safe bet that flags will always be -non-zero. Still, it's good practice to plan for the future by -checking the value. -<P> -Note also that when we send the data we prefix it with the data size. -This let's our sibling Recv ensure that an entire block is received -together. This can be very important for compression and encryption -processes which typically work better with blocks of data instead of -streams of data. -<HR> -SHAR_EOF - $shar_touch -am 04090120100 'page15.pre' && - chmod 0664 'page15.pre' || - $echo 'restore of' 'page15.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 'page15.pre:' 'MD5 check failed' -adfd8e81c8c9eb43526d58322bbf8acf page15.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page15.pre'`" - test 769 -eq "$shar_count" || - $echo 'page15.pre:' 'original size' '769,' 'current size' "$shar_count!" - fi -fi -# ============= page16.pre ============== -if test -f 'page16.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page16.pre' '(file already exists)' -else - $echo 'x -' extracting 'page16.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page16.pre' && -Recv is the sibling to Xmit. Again, they could be combined into a -single object if you want. -<P> -An ACE_Stream is designed to handle downstream traffic very -well. You put() data into it and it flows along towards the tail. -However, there doesn't seem to be a way to put data in such that it -will travel upstream. To get around that, I've added a get() method -to Recv that will trigger a read on the socket. Recv will then put -the data to the next upstream module and we're on our way. As noted -earlier, that data will eventually show up either in the <i>reader</i> -(if installed on the stream open()) or the stream head reader task's -message queue. -<HR> -SHAR_EOF - $shar_touch -am 04090120100 'page16.pre' && - chmod 0664 'page16.pre' || - $echo 'restore of' 'page16.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 'page16.pre:' 'MD5 check failed' -17e82c6427c779c22ac5c04c5f9c2bff page16.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page16.pre'`" - test 659 -eq "$shar_count" || - $echo 'page16.pre:' 'original size' '659,' 'current size' "$shar_count!" - fi -fi -# ============= page17.pre ============== -if test -f 'page17.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page17.pre' '(file already exists)' -else - $echo 'x -' extracting 'page17.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page17.pre' && -The Recv implementation is nearly as simple as Xmit. There's -opportunity for error when we get the message size and we have to -manage the lifetime of the tickler but other than that it's pretty -basic stuff. -<HR> -SHAR_EOF - $shar_touch -am 04090120100 'page17.pre' && - chmod 0664 'page17.pre' || - $echo 'restore of' 'page17.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 'page17.pre:' 'MD5 check failed' -7db337f2c6ec74d75560534dec550b0e page17.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page17.pre'`" - test 213 -eq "$shar_count" || - $echo 'page17.pre:' 'original size' '213,' 'current size' "$shar_count!" - fi -fi -# ============= page18.pre ============== -if test -f 'page18.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page18.pre' '(file already exists)' -else - $echo 'x -' extracting 'page18.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page18.pre' && -This and the next three pages present the protocol objects that -provide compression and encryption. If you were hoping to learn the -secrets of compression and encryption then I'm going to disappoint -you. There are some really good libraries out there that do this -stuff though and if anyone wants to integrate one of them into the -tutorial I'll be glad to take it! -<HR> -SHAR_EOF - $shar_touch -am 04090120100 'page18.pre' && - chmod 0664 'page18.pre' || - $echo 'restore of' 'page18.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 'page18.pre:' 'MD5 check failed' -dc5f706bd5a27009aed167c0b137648e page18.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page18.pre'`" - test 372 -eq "$shar_count" || - $echo 'page18.pre:' 'original size' '372,' 'current size' "$shar_count!" - fi -fi -# ============= page19.pre ============== -if test -f 'page19.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page19.pre' '(file already exists)' -else - $echo 'x -' extracting 'page19.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page19.pre' && -Here we implement the details of our compression. By having both -compression and decompression in one object it's easier to keep track -of implementation details. Splitting Xmit/Recv like I did will make -things more difficult if something has to change in their interaction. -<HR> -SHAR_EOF - $shar_touch -am 04090120100 'page19.pre' && - chmod 0664 'page19.pre' || - $echo 'restore of' 'page19.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 'page19.pre:' 'MD5 check failed' -4eb5dcd181f180d6c460971903efb288 page19.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page19.pre'`" - test 281 -eq "$shar_count" || - $echo 'page19.pre:' 'original size' '281,' 'current size' "$shar_count!" - fi -fi -# ============= page20.pre ============== -if test -f 'page20.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page20.pre' '(file already exists)' -else - $echo 'x -' extracting 'page20.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page20.pre' && -While I might be able to come up with a competitive compressor, I -don't have a snowball's chance to code up encryption. I'd be better -off piping the data through the standard Unix crypt command. -<P> -So, while I was lazy with Compress, I'm realistic with Crypt. I'll -show you the hooks and entry points and let someone else contribute an -encryptor. -<HR> -SHAR_EOF - $shar_touch -am 04090120100 'page20.pre' && - chmod 0664 'page20.pre' || - $echo 'restore of' 'page20.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 'page20.pre:' 'MD5 check failed' -2e697c01ac1579b409503b14980cadd0 page20.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page20.pre'`" - test 355 -eq "$shar_count" || - $echo 'page20.pre:' 'original size' '355,' 'current size' "$shar_count!" - fi -fi -# ============= page21.pre ============== -if test -f 'page21.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page21.pre' '(file already exists)' -else - $echo 'x -' extracting 'page21.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page21.pre' && -The encryption implementation isn't any smarter than that of the -compressor. Still, the hooks are there for you to insert your -favorite library. -<HR> -SHAR_EOF - $shar_touch -am 04090120100 'page21.pre' && - chmod 0664 'page21.pre' || - $echo 'restore of' 'page21.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 'page21.pre:' 'MD5 check failed' -7f0f64452098cdef38c5496340a4b6c7 page21.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page21.pre'`" - test 151 -eq "$shar_count" || - $echo 'page21.pre:' 'original size' '151,' 'current size' "$shar_count!" - fi -fi -# ============= page22.pre ============== -if test -f 'page22.pre' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page22.pre' '(file already exists)' -else - $echo 'x -' extracting 'page22.pre' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page22.pre' && -Well, this has certainly been one of the more verbose tutorials to -date. I must say "thanks" to everyone who stuck it out this far! -<P> -A quick review of what we've done: -<UL> -X -<LI>Create a simple client application and Client object that uses a -Protocol Stream without really knowing how they work. The app (and -object) rely on the public interface of the Protocol Stream to get the -job done. At this level the protocol details are irrelevant. -<P> -<LI>Next, we create a simple server application and Server object -similar to the client. The Protocol Stream is of course used and we -have to know a little more so that we can insert a <i>reader</i> that -will ultimately process the data from the client. -<P> -<LI>We then go into the details of the Protocol_Stream implementation -and it's Protocol_Task object that forms the basis for the stream -tasks. Each object is kept as small and simple as possible to improve -reusability and future maintenance. -<P> -<LI>Finally, the individual protocol objects are discused. Separate -objects for the peer interface were created as well as the bogus -compressor and encryptor. The protocol can be extended or modified by -creating new such objects and installing them in the Protocol_Stream's -open() method. -X -</UL> -<P> -X -It doesn't sound like much but it certainly took a bunch of files to -get there. It's easy to get lost in the details when there's so much -to cover so you're encouraged to go over things a couple of times. -As always, enhancments of the tutorials is welcome! -<P> -Here's the complete file list: -<UL> -<LI><A HREF="client">Makefile</A> -<P> -<LI><A HREF="Makefile.client">client Makefile</A> -<LI><A HREF="client.cpp">client.cpp</A> -<LI><A HREF="Client_i.h">Client_i.h</A> -<LI><A HREF="Client_i.cpp">Client_i.cpp</A> -<P> -<LI><A HREF="Makefile.server">Server Makefile</A> -<LI><A HREF="server.cpp">server.cpp</A> -<LI><A HREF="Server_i.h">Server_i.h</A> -<LI><A HREF="Server_i.cpp">Server_i.cpp</A> -<LI><A HREF="Handler.h">Handler.h</A> -<LI><A HREF="Handler.cpp">Handler.cpp</A> -<P> -<LI><A HREF="Protocol_Stream.cpp">Protocol_Stream.cpp</A> -<LI><A HREF="Protocol_Stream.h">Protocol_Stream.h</A> -<LI><A HREF="Protocol_Task.cpp">Protocol_Task.cpp</A> -<LI><A HREF="Protocol_Task.h">Protocol_Task.h</A> -<P> -<LI><A HREF="Xmit.cpp">Xmit.cpp</A> -<LI><A HREF="Xmit.h">Xmit.h</A> -<LI><A HREF="Recv.cpp">Recv.cpp</A> -<LI><A HREF="Recv.h">Recv.h</A> -<P> -<LI><A HREF="Compressor.cpp">Compressor.cpp</A> -<LI><A HREF="Compressor.h">Compressor.h</A> -<LI><A HREF="Crypt.cpp">Crypt.cpp</A> -<LI><A HREF="Crypt.h">Crypt.h</A> -</UL> -SHAR_EOF - $shar_touch -am 04090120100 'page22.pre' && - chmod 0664 'page22.pre' || - $echo 'restore of' 'page22.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 'page22.pre:' 'MD5 check failed' -da9603b9f082f453a905e40a8ca8523c page22.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page22.pre'`" - test 2563 -eq "$shar_count" || - $echo 'page22.pre:' 'original size' '2563,' '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> -<P> -Ok, that's it for the client. We've seen a very simple main() -X followed by an equally simple Client object. -<P> -For a quick look back: -<UL> -<LI><A HREF="Makefile.client">client Makefile</A> -<LI><A HREF="client.cpp">client.cpp</A> -<LI><A HREF="Client_i.h">Client_i.h</A> -<LI><A HREF="Client_i.cpp">Client_i.cpp</A> -</UL> -<P> -Now we'll move on and examine the server counter-part of our client. -SHAR_EOF - $shar_touch -am 04090120100 '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' -00419a8ab9a3ddae3261840b62afdc4a page04.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pst'`" - test 406 -eq "$shar_count" || - $echo 'page04.pst:' 'original size' '406,' 'current size' "$shar_count!" - fi -fi -# ============= page09.pst ============== -if test -f 'page09.pst' && test "$first_param" != -c; then - $echo 'x -' SKIPPING 'page09.pst' '(file already exists)' -else - $echo 'x -' extracting 'page09.pst' '(text)' - sed 's/^X//' << 'SHAR_EOF' > 'page09.pst' && -<HR> -<P> -That's it for the server-specific code. I think I've been fairly -successful in keeping it simple and to the point. There are a couple -of places where the as-yet-undescribed Protocol_Stream pops up and may -cause confusion. We're going to discuss that mystery now but before -we do here's the list of server files if you want to review: -X -<UL> -<LI><A HREF="Makefile.server">Server Makefile</A> -<LI><A HREF="server.cpp">server.cpp</A> -<LI><A HREF="Server_i.h">Server_i.h</A> -<LI><A HREF="Server_i.cpp">Server_i.cpp</A> -<LI><A HREF="Handler.h">Handler.h</A> -<LI><A HREF="Handler.cpp">Handler.cpp</A> -</UL> -<P> -SHAR_EOF - $shar_touch -am 04090120100 'page09.pst' && - chmod 0664 'page09.pst' || - $echo 'restore of' 'page09.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 'page09.pst:' 'MD5 check failed' -f88b5e21934f51fc3e14b154e5edd1a9 page09.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page09.pst'`" - test 616 -eq "$shar_count" || - $echo 'page09.pst:' 'original size' '616,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh16810 -exit 0 diff --git a/docs/tutorials/015/page01.html b/docs/tutorials/015/page01.html deleted file mode 100644 index 0709a089c19..00000000000 --- a/docs/tutorials/015/page01.html +++ /dev/null @@ -1,106 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> - -In a typical client/server system you will be sending and receiving - data. That's the whole point after all. -<P> -In the client/server tutorials that we've done so far it was just a - matter of sending a buffer of data to the peer. This was done - with the send*() and recv*() methods of the ACE_SOCK* objects. -<P> -In a more robust system, one might want to process the data before - sending it to a peer and "unprocess" it after reading from a - peer. These processing steps might include encryption, - compression, applying checksums or any number of other actions. -<P> -In this tutorial a Protocol_Stream object is created to encrypt and - compress* data being sent between peers. Both client and server - applications are presented as well. I present the application -level code first and then go into the details of the protocol stream -and it's helper objects. If the stream stuff in the application logic -is confusing then just read on by and come back to it after the later -discussions. -<P> -Disclaimer: -<br> -<ul> -Several folks have reported problems with this tutorial on Win32. -There are a couple of ways to solve this. I've chosen to solve it by -using the ACE_Select_Reactor on all platforms instead of taking the -OS-default. -</ul> -<P> -Kirthika's abstract: -<UL> -The Protocol Stream model consists of a stream layer which pushes the -data towards the underlying SOCK_Stream thru the stages of encryption -and compression. This data is received at the other end of the -SOCK_Stream and sent up to its Protocol_Stream layer via the stages of -decompression and decryption and an optional Reader task. This is very -similar to the model of the TCP/IP stack (specifically the datalink to -physical layer portion). -<P> -ACE_Message_Blocks are used to communicate between the client and the -server across the Protocol Stream, which abstracts the protocol -conformance details. The underlying SOCK_Stream is used to set up the -connection using the ACE_SOCK_Connector class. Once the connector -completes its job, the SOCK_Stream pointer is passed on to the -Protocol Stream which now takes over. The Client has put() and get() -methods to send and receive data from the server. -<P> -The server is implemented using the ACE_Acceptor to listen at the port -for connections and a reactor for delegating events to the appropriate -event handler. The handle_input () method of the handler simply allows -the stream to receive the data and hand it over to the Handler_Task (a -derivative of the ACE_Task) which will then process it. -<P> -The implementation of this Protocol Stream model is done using the -ACE_Module class. The module for Xmit/Recv is shoved in first -into the stream, followed by the encryption and compression modules. The -optional Reader if defined is bundled with a dummy task -(ACE_Thru_Task class) into a module. The get() and put() methods do -the job of reading and writing to the Stream. Each module is made up -of a pair of Protocol Tasks. A Protocol Task is a derivative of the -ACE_Task and whose recv() and send() methods need to be filled to -perform the appropriate task. -<P> -The Xmit object derives from the Protocol task and has a send() method -which does the task of transmitting data to the underlying -SOCK_Stream. Keeping the fragmentation and reassembly issues in mind, -block-size is also sent across with the block of data. -The Recv object uses a dummy Message Block to provoke the Protocol -Task object to call the recv() on it. This is done by being -foresighted about the use of mutliple threads instead of a single -thread. -<P> -The compression/decompression is bundled in a single Protocol Task -object with the send () method doing the compression and the recv() -doing the decompression. Similarly, the encrption/decryption is done -using a single Protocol Task object. -<P> -This tutorial provides a glimpse on how to design and implement a -protocol in layers and also revises a lot of what has been learnt until -now from the previous tutorials. -(for instance, Message_Block, Task, Acceptor, Connector, Event_Handler -etc.) -</UL> -<P> -<font size=-1>* Ok, I didn't really implement encryption and - compression objects. I'll leave that as a thought - exercise!</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/015/page02.html b/docs/tutorials/015/page02.html deleted file mode 100644 index bdf3a3cb44d..00000000000 --- a/docs/tutorials/015/page02.html +++ /dev/null @@ -1,95 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -We'll take a look first at the client application. As usual, our goal - is to keep the main() application as simple as possible and - delegate the tricky stuff to another object. - -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=red>/* The Client object will implement the nasty details of connecting to - communicating with the server -*/</font> -<font color=blue>#include</font> "<font color=green>Client_i.h</font>" - -int main(int argc, char *argv[]) -{ - <font color=red>// How many messages will we send?</font> - int mcount = argc > 1 ? <font color=#008888>ACE_OS::atoi</font>(argv[1]) : 3; - - <font color=red>// Construct a Client with our desired endpoint.</font> - Client client(ACE_DEFAULT_SERVER_PORT,ACE_DEFAULT_SERVER_HOST); - - <font color=red>// Attempt to open the connection to the server.</font> - if( client.open() == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green><font color=#008888>Client::open</font>()</font>"), -1); - } - - <font color=red>// Send a few messages to the server and get some responses...</font> - for( int i = 0 ; i < mcount ; ++i ) - { - <font color=red>// Since we'll be using a Protocol Stream (even though we</font> - <font color=red>// don't know that at this level) we require the use of</font> - <font color=red>// ACE_Message_Block objects to send/receive data.</font> - ACE_Message_Block * message = new ACE_Message_Block( 128 ); - - <font color=red>// Construct a silly message to send to the server.</font> - <font color=red>// Notice that we're careful to add one to the strlen() so</font> - <font color=red>// that we also send the end-of-string NULL character.</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>// client will take ownership of the message block so that</font> - <font color=red>// we don't have to remember to release(). We *do* have</font> - <font color=red>// to remember not to use it after put() since it may be</font> - <font color=red>// released almost immediately.</font> - client.put( message ); - - ACE_Message_Block * response; - - <font color=red>// get() takes an ACE_Message_Block pointer reference. We then</font> - <font color=red>// assume ownership of it and must release() when we're done.</font> - if( client.get( response ) == -1 ) - { - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) Failed to get response from server\n</font>" )); - break; - } - - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) The server's response: (%s)\n</font>", - response->rd_ptr())); - - <font color=red>// Now that we're through with the response we have to</font> - <font color=red>// release() it to avoid memory leaks.</font> - response->release(); - } - - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) Shutting down the stream\n</font>" )); - - <font color=red>// Before we exit, it's a good idea to properly close() the connection.</font> - if( client.close() == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green><font color=#008888>Client::close</font>()</font>"), -1); - } - - return(0); -} -</PRE> -<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/015/page03.html b/docs/tutorials/015/page03.html deleted file mode 100644 index d097af1363c..00000000000 --- a/docs/tutorials/015/page03.html +++ /dev/null @@ -1,99 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The Client object is designed to hide all of the messy connection - logic from it's users. It also provides put/get methods for - sending data to the server and receiving the server's response. - Note the Protocol_Stream member that will take care of - converting and sending/receiving the data. -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>CLIENT_H</font> -<font color=blue>#define</font> <font color=purple>CLIENT_H</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=blue>#include</font> "<font color=green>Protocol_Stream.h</font>" - -class ACE_Message_Block; - -<font color=red>/* Hide the details of connection and protocol-conformance from the - application-level logic. -*/</font> -class Client -{ -public: - <font color=red>// Provide the server information when constructing the</font> - <font color=red>// object. This could (and probably should) be moved to the</font> - <font color=red>// open() method.</font> - Client (u_short port, - const char *server); - - <font color=red>// Cleanup...</font> - ~Client (void); - - <font color=red>// Open the connection to the server.</font> - int open (void); - - <font color=red>// Close the connection to the server. Be sure to do this</font> - <font color=red>// before you let the Client go out of scope.</font> - int close (void); - - <font color=red>// Put a message to the server. The Client assumes ownership of</font> - <font color=red>// <message> at that point and will release() it when done. Do not</font> - <font color=red>// use <message> after passing it to put().</font> - int put (ACE_Message_Block *message); - - <font color=red>// Get a response from the server. The caller becomes the owner of</font> - <font color=red>// <response> after this call and is responsible for invoking</font> - <font color=red>// release() when done.</font> - int get (ACE_Message_Block *&response); - -private: - <font color=red>// Protocol_Stream hides the protocol conformance details from us.</font> - Protocol_Stream stream_; - - <font color=red>// We create a connection on the peer_ and then pass ownership of it</font> - <font color=red>// to the protocol stream.</font> - ACE_SOCK_Stream peer_; - - <font color=red>// Endpoing information saved by the constructor for use by open().</font> - u_short port_; - const char *server_; - - <font color=red>// Accessors for the complex member variables.</font> - - Protocol_Stream &stream (void) - { - return this->stream_; - } - - ACE_SOCK_Stream &peer (void) - { - return this->peer_; - } -}; - -<font color=blue>#endif</font> <font color=red>/* CLIENT_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page04.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/015/page04.html b/docs/tutorials/015/page04.html deleted file mode 100644 index 0ad3b837366..00000000000 --- a/docs/tutorials/015/page04.html +++ /dev/null @@ -1,98 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The implementation of the Client object. Only the open() method - really does any work. The other methods simply delegate their - function to the Protocol_Stream. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Client_i.h</font>" -<font color=blue>#include</font> "<A HREF="../../../ace/Message_Block.h">ace/Message_Block.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/INET_Addr.h">ace/INET_Addr.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Connector.h">ace/SOCK_Connector.h</A>" - -<font color=red>// Simple constructor just remembers the endpoint information for use by open.</font> -<font color=#008888>Client::Client</font>( u_short _port, const char * _server) - : port_(_port), server_(_server) -{ - ; -} - -<font color=red>/* Do nothing. This should probably call close() if we can make sure - that it's OK to close() multiple times. -*/</font> -<font color=#008888>Client::~Client</font>(void) -{ - ; -} - -<font color=red>/* Open the connection to the server. This is traditional ACE. We - simply construct an endpoint and use a connector to establish the - link. -*/</font> -int <font color=#008888>Client::open</font>( void ) -{ - ACE_INET_Addr addr(port_,server_); - ACE_SOCK_Connector con; - - if( con.connect(peer(),addr) == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green><font color=#008888>ACE_SOCK_Connector::connect</font>()</font>"), -1); - } - - <font color=red>// Something new here... We have to use the protocol stream</font> - <font color=red>// to ensure that our data is in the correct format when</font> - <font color=red>// received by the server. Thus, we open the stream and</font> - <font color=red>// transfer ownership of the peer.</font> - return stream().open( peer() ); -} - -<font color=red>// The remainder of the functions just delegate to the stream.</font> - -int <font color=#008888>Client::close</font>( void ) -{ - return stream().close(); -} - -int <font color=#008888>Client::put</font>( ACE_Message_Block * _message ) -{ - return stream().put(_message,0); -} - -int <font color=#008888>Client::get</font>( ACE_Message_Block * & _response ) -{ - return stream().get(_response); -} -</PRE> -<HR> -<P> -Ok, that's it for the client. We've seen a very simple main() - followed by an equally simple Client object. -<P> -For a quick look back: -<UL> -<LI><A HREF="Makefile.client">client Makefile</A> -<LI><A HREF="client.cpp">client.cpp</A> -<LI><A HREF="Client_i.h">Client_i.h</A> -<LI><A HREF="Client_i.cpp">Client_i.cpp</A> -</UL> -<P> -Now we'll move on and examine the server counter-part of our client. -<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/015/page05.html b/docs/tutorials/015/page05.html deleted file mode 100644 index fa2aca0db49..00000000000 --- a/docs/tutorials/015/page05.html +++ /dev/null @@ -1,95 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -Like the client, we want to keep the main() part of our server code as - simple as possible. This is done by putting most of the work - into the Handler object that will deal with client connections. -From the looks of the code below, I think we've been successful in our -simplification. -<HR> - -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Server_i.h</font>" -<font color=blue>#include</font> "<A HREF="../../../ace/Select_Reactor.h">ace/Select_Reactor.h</A>" - -<font color=red>// A signal handler that will close the server object</font> -extern "<font color=green>C</font>" void handler (int) -{ - <font color=#008888>Server::close</font>(); -} - -int main (int, char **) -{ - <font color=red>/* On Win32, the WFMO reactor is used by default. - Unfortunately, that causes the sockets to be put into - non-blocking mode which will break <font color=#008888>Recv::recv</font>(). To - prevent that issue, I explicitly use the Select Reactor - instead. I'll talk more about the "<font color=green>problem</font>" in the Recv - comments. - */</font> - - <font color=red>// First, we create a Select_Reactor that will do the work.</font> - <font color=red>// To keep things simple, I'll create it on the stack.</font> - ACE_Select_Reactor mySelectReactor; - - <font color=red>// Next, we need an ACE_Reactor that is the bridge between the</font> - <font color=red>// code and the real reactor. It is given a pointer to the</font> - <font color=red>// real reactor.</font> - ACE_Reactor myReactor (&mySelectReactor); - - <font color=red>// Finally, we set the singleton instance to use the reactor</font> - <font color=red>// we've created.</font> - <font color=#008888>ACE_Reactor::instance</font> (&myReactor); - - <font color=red>// The server object that abstracts away all of the difficult parts.</font> - Server server; - - <font color=red>// Attempt to open the server. Like all good ACE-based</font> - <font color=red>// objects, we'll get -1 on failure.</font> - if( server.open() == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>server.open()</font>"), -1); - } - - <font color=red>// Install a signal handler for ^C so that we can exit gracefully</font> - ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT); - - <font color=red>// Run the server's main loop until we're interrupted</font> - if( server.run() == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>server.run()</font>"), -1); - } - - return 0; -} - -<font color=red>/* These explicit instantiations were taken from an earlier tutorial. - Your compiler may require others as well. -*/</font> -<font color=blue>#if defined</font> (<font color=purple>ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION</font>) -template class ACE_Acceptor <Handler, ACE_SOCK_ACCEPTOR>; -template class ACE_Svc_Handler<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 <Handler, ACE_SOCK_ACCEPTOR> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> -<font color=blue>#endif</font> <font color=red>/* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */</font> - -</PRE> -<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/015/page06.html b/docs/tutorials/015/page06.html deleted file mode 100644 index 828b5501600..00000000000 --- a/docs/tutorials/015/page06.html +++ /dev/null @@ -1,79 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The Server object exists in order simplify the -main() application level. To that end, it hides the details of -creating an acceptor and managing the reactor. -<P> -The static close() method available for a signal handler as you saw on -the previous page. Of course the assumption here is that there would -only be one Server instance but since you can't provide a TCP/IP port, -that's probably a valid assumption! -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>SERVER_H</font> -<font color=blue>#define</font> <font color=purple>SERVER_H</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Acceptor.h">ace/Acceptor.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Acceptor.h">ace/SOCK_Acceptor.h</A>" -<font color=blue>#include</font> "<font color=green>Handler.h</font>" - -<font color=red>/* Anytime I have templates I try to remember to create a typedef for - the parameterized object. It makes for much less typing later! -*/</font> -typedef ACE_Acceptor <Handler, ACE_SOCK_ACCEPTOR> Acceptor; - -class Server -{ -public: - <font color=red>// Our simple constructor takes no parameters. To make the</font> - <font color=red>// server a bit more useful, you may want to pass in the</font> - <font color=red>// TCP/IP port to be used by the acceptor.</font> - Server (void); - ~Server (void); - - <font color=red>// Open the server for business</font> - int open (void); - - <font color=red>// Close all server instances by setting the finished_ flag.</font> - <font color=red>// Actually, the way this class is written, you can only have</font> - <font color=red>// one instance.</font> - static int close (void); - - <font color=red>// Run the server's main loop. The use of the gloabl ACE_Reactor by</font> - <font color=red>// this method is what limits us to one Server instance.</font> - int run (void); - -private: - <font color=red>// This will accept client connection requests and instantiate a</font> - <font color=red>// Handler object for each new connection.</font> - Acceptor acceptor_; - - <font color=red>// Our shutdown flag</font> - static sig_atomic_t finished_; -}; - -<font color=blue>#endif</font> <font color=red>/* SERVER_H */</font> -</PRE> -<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/015/page07.html b/docs/tutorials/015/page07.html deleted file mode 100644 index 9adccc2c48d..00000000000 --- a/docs/tutorials/015/page07.html +++ /dev/null @@ -1,102 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -And now the implementation of Server. This is actually just the -main() code from a previous tutorial broken into appropriate method -calls. It may seem silly to do this rather than keeping the stuff in -main() but you'll find that you have less trouble enhancing an -application when you take this sort of approach. -<HR> - -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Server_i.h</font>" - -<font color=red>/* We have to allocate space for our static finished_ flag. We also - initialize it to 'false' so that we don't exit immediately. -*/</font> -sig_atomic_t <font color=#008888>Server::finished_</font> = 0; - -<font color=red>/* The simple constructor and destructor don't do anything but give us - a place to expand in the future if we want. -*/</font> -<font color=#008888>Server::Server</font>(void) -{ - ; -} - -<font color=#008888>Server::~Server</font>(void) -{ - ; -} - -<font color=red>/* Opening the server is as simple as opening the acceptor with the - default ACE_Reactor instance. If we want to allow multiple - instances of Server objects then we should have an ACE_Reactor - member variable that we can register with. -*/</font> -int <font color=#008888>Server::open</font>(void) -{ - if (acceptor_.open (ACE_INET_Addr (ACE_DEFAULT_SERVER_PORT), <font color=#008888>ACE_Reactor::instance</font>()) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>open</font>"), -1); - - return(0); -} - -<font color=red>/* Running the server just means that we execute the basic event - loop for the reactor. Again, if we had a private reactor then we - could have multiple server's in their run() method. -*/</font> -int <font color=#008888>Server::run</font>(void) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) starting up server daemon\n</font>")); - - <font color=red>// Here's the basic event loop. I have a 2-second timeout on</font> - <font color=red>// the handle_events() so that we don't have to wait too long</font> - <font color=red>// when we set the finished_ flag.</font> - while (!finished_) - { - <font color=red>// Some (all?) platforms return the "<font color=green>remaining time</font>" in the</font> - <font color=red>// timeout parameter. If we don't reset it each time, we</font> - <font color=red>// will end up with a 100% CPU spin loop!</font> - ACE_Time_Value timeout(2); - - <font color=#008888>ACE_Reactor::instance</font>()->handle_events (&timeout); - } - - <font color=red>// Close the acceptor when we're done. This may be handled by</font> - <font color=red>// the framework but it's good practice to be explicit about things.</font> - acceptor_.close(); - - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) shutting down server daemon\n</font>")); - - return 0; -} - -<font color=red>/* The close() method simply sets the finished_ flag so that run() - will leave the event loop and exit. -*/</font> -int <font color=#008888>Server::close</font>(void) -{ - finished_ = 1; - <font color=#008888>ACE_Reactor::instance</font>()->notify(); - return(0); -} -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page08.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/015/page08.html b/docs/tutorials/015/page08.html deleted file mode 100644 index 19a74c68690..00000000000 --- a/docs/tutorials/015/page08.html +++ /dev/null @@ -1,91 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The Handler object is our event handler. You can use either -ACE_Event_Handler or ACE_Svc_Handler<> for the baseclass. I generally -prefer the latter since it takes care of some housekeeping that I -would otherwise be responsible for. -<P> -The class declaration is taken almost exactly from a previous -tutorial. A good design will have a simple handler object that will -collect data from the peer and pass it along to another object for -processing. Again, keep it simple and delegate authority. -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>HANDLER_H</font> -<font color=blue>#define</font> <font color=purple>HANDLER_H</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Svc_Handler.h">ace/Svc_Handler.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" -<font color=blue>#include</font> "<font color=green>Protocol_Stream.h</font>" - -<font color=red>/* Just your basic event handler. We use ACE_Svc_Handler<> as a - baseclass so that it can maintain the peer() and other details for - us. We're not going to activate() this object, so we can get away - with the NULL synch choice. */</font> -class Handler : public ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> -{ -public: - Handler (void); - ~Handler (void); - - <font color=red>// Called by the acceptor when we're created in response to a client</font> - <font color=red>// connection.</font> - int open (void *); - - <font color=red>// Called when it's time for us to be deleted. We take care of</font> - <font color=red>// removing ourselves from the reactor and shutting down the peer()</font> - <font color=red>// connectin.</font> - void destroy (void); - - <font color=red>// Called when it's time for us to go away. There are subtle</font> - <font color=red>// differences between destroy() and close() so don't try to use</font> - <font color=red>// either for all cases.</font> - int close (u_long); - -protected: - <font color=red>// Respond to peer() activity.</font> - int handle_input (ACE_HANDLE); - - <font color=red>// This will be called when handle_input() returns a failure code.</font> - <font color=red>// That's our signal that it's time to begin the shutdown process.</font> - int handle_close (ACE_HANDLE, - ACE_Reactor_Mask mask); -private: - - <font color=red>// Like the Client, we have to abide by the protocol requirements.</font> - <font color=red>// We use a local Protocol_Stream object to take care of those</font> - <font color=red>// details. For us, I/O then just becomes a matter of interacting</font> - <font color=red>// with the stream.</font> - Protocol_Stream stream_; - - Protocol_Stream &stream (void) - { - return this->stream_; - } -}; - -<font color=blue>#endif</font> <font color=red>/* HANDLER_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page09.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/015/page09.html b/docs/tutorials/015/page09.html deleted file mode 100644 index 9d1b818fbd3..00000000000 --- a/docs/tutorials/015/page09.html +++ /dev/null @@ -1,227 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -Like any other event handler, the handle_input() method will be -responsible for getting data from the peer() and doing something with -it. In this case, we have a Protocol_Stream to deal with. We'll use -the stream for the actual I/O but we are ultimately responsible for -processing the data from the peer. To do that, we've created a -Handler_Task that fits within the Protocol_Stream framework to process -data that has been received. Handler::handle_input() will tell the stream that -it's time to read data and that data will eventually show up at -Handler_Task::recv() where we'll process it as required by our -application logic. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Handler.h</font>" -<font color=blue>#include</font> "<font color=green>Protocol_Task.h</font>" - -<font color=red>/* The Protocol_Stream gives us the option to insert a Protocol_Task - to process data received by the stream. We'll get into the details - more when we talk about the stream in detail. For now it's enough - to know that <font color=#008888>Handler_Task::recv</font>() will be invoked by the stream - after data from the client has been received and processed (eg -- - decrypted, uncompressed, and whatever else the protocol requires.) -*/</font> -class Handler_Task : public Protocol_Task -{ -public: - - <font color=red>// Typical...</font> - typedef Protocol_Task inherited; - - <font color=red>// Simple...</font> - Handler_Task(void); - ~Handler_Task(void); - -protected: - - <font color=red>// recv() is invoked after received data has been fully</font> - <font color=red>// processed by the protocol rules. Data processing typically</font> - <font color=red>// done in handle_input() can then be done here.</font> - int recv(ACE_Message_Block * message, - ACE_Time_Value *timeout = 0); -}; - -<font color=#008888>Handler::Handler</font>(void) -{ - ; -} - -<font color=#008888>Handler::~Handler</font>(void) -{ - ; -} - -<font color=red>/* The Acceptor will open() us once the peer() connection is - established. There are a couple of things we have to do here - before we're ready to receive data from the client. -*/</font> -int <font color=#008888>Handler::open</font> (void *) -{ - ACE_INET_Addr addr; - - <font color=red>// Make sure that we can get the peer's address. If we can't</font> - <font color=red>// then there may be a network error or something else that</font> - <font color=red>// will prevent communicating with the client. This is</font> - <font color=red>// something you'll want to do in every event handler you create.</font> - if (this->peer ().get_remote_addr (addr) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) Cannot get remote addr\n</font>"), -1); - - <font color=red>// Announce the client</font> - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) connected with %s\n</font>", addr.get_host_name() )); - - <font color=red>// Here's the first new twist to the old event handler.</font> - <font color=red>// Before we can use the Protocol_Stream to communicate with</font> - <font color=red>// the peer, we must open() it. We provide the stream with</font> - <font color=red>// the peer() so that it will have a valid socket on which to</font> - <font color=red>// read client requests and send our responses. We also</font> - <font color=red>// provide a Handler_Task instance that will ultimately be</font> - <font color=red>// responsible for processing any client data we receive.</font> - int rval = stream().open( this->peer(), new Handler_Task() ); - - <font color=red>// Of course, we have to account for the chance that the</font> - <font color=red>// stream's open() may fail.</font> - if( rval == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) Cannot open the protocol stream.\n</font>"), -1); - } - - <font color=red>// Now that we know the client is valid and that the stream is</font> - <font color=red>// ready for business we can register with the gloabl reactor</font> - <font color=red>// instance. Here again is an opportunity for improvement if</font> - <font color=red>// we expect to have mulitple Server object instances.</font> - if (<font color=#008888>ACE_Reactor::instance</font>()->register_handler (this, ACE_Event_Handler::READ_MASK) == -1) - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) Cannot register with reactor\n</font>"), -1); - - return rval; -} - -<font color=red>/* This is a fairly typical destroy() method that can be shared by - both close() and handle_close(). -*/</font> -void <font color=#008888>Handler::destroy</font> (void) -{ - <font color=#008888>ACE_Reactor::instance</font>()->remove_handler(this,ACE_Event_Handler::READ_MASK|ACE_Event_Handler::DONT_CALL); - - this->peer ().close (); - - delete this; -} - -<font color=red>/* In this simple application we just forward the close() and - handle_close() requests right on to the destroy() method. -*/</font> - -int <font color=#008888>Handler::close</font> (u_long) -{ - this->destroy (); - return 0; -} - -int <font color=#008888>Handler::handle_close</font>(ACE_HANDLE, ACE_Reactor_Mask) -{ - this->destroy(); - return 0; -} - -<font color=red>/* Unlike a "<font color=green>traditional</font>" handle_input() ours is very simple. Because - of the use of the protocol stream, we delegate the read function to - the stream's get() and rely on our Handler_Task to do the real work. -*/</font> -int <font color=#008888>Handler::handle_input</font> (ACE_HANDLE) -{ - ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) Activity from client\n</font>" )); - - <font color=red>// This will cause a blocking read from the peer(). The data</font> - <font color=red>// will then be pushed through the protocol stream.</font> - if( stream().get( ) == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) Cannot get data from protocol stream\n</font>"), -1); - } - - return 0; -} - -<font color=red>/* A Protocol_Task is derived from ACE_Task and has the option of - running in one or more threads. I've chosen here to construct the - baseclass with no threads but it should work just fine with one or - more if you need. Unless you're sharing the Handler_Task with - several peers, however, you're probably just wasting a thread to - activate it. On the other hand, if your reactor is running in a - single thread (as in this example) then you can easily implement - thread-per-connection concurrency by giving the baseclass one thread. -*/</font> -<font color=#008888>Handler_Task::Handler_Task</font>(void) - : inherited() -{ - ; -} - -<font color=#008888>Handler_Task::~Handler_Task</font>(void) -{ - ; -} - -<font color=red>/* When installed into the protocol stream, the Handler_Task's recv() - method will be called when data is ready for processing. - */</font> -int <font color=#008888>Handler_Task::recv</font>(ACE_Message_Block * message, - ACE_Time_Value *timeout ) -{ - <font color=red>// Announce the request we got from the client</font> - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) <font color=#008888>Handler_Task::recv</font>() got (%s)\n</font>", message->rd_ptr() )); - - <font color=red>// Create a response message to send to the client</font> - ACE_Message_Block * response = new ACE_Message_Block( 128 ); - - <font color=red>// Nothing very original about this I'm afraid...</font> - <font color=#008888>ACE_OS::sprintf</font>( response->wr_ptr(), "<font color=green>You Said: (%s)</font>", message->rd_ptr() ); - response->wr_ptr( strlen(response->wr_ptr())+1 ); - - <font color=red>// Release the original message block now that we're through</font> - <font color=red>// "<font color=green>processing</font>" it.</font> - message->release(); - - <font color=red>// Turn the message around and send it back down the Stream.</font> - <font color=red>// In other words, we invoke the put() method on the</font> - <font color=red>// Protocol_Stream without having to have a direct reference</font> - <font color=red>// to the stream object.</font> - return this->reply( response, timeout ); -} -</PRE> -<HR> -<P> -That's it for the server-specific code. I think I've been fairly -successful in keeping it simple and to the point. There are a couple -of places where the as-yet-undescribed Protocol_Stream pops up and may -cause confusion. We're going to discuss that mystery now but before -we do here's the list of server files if you want to review: - -<UL> -<LI><A HREF="Makefile.server">Server Makefile</A> -<LI><A HREF="server.cpp">server.cpp</A> -<LI><A HREF="Server_i.h">Server_i.h</A> -<LI><A HREF="Server_i.cpp">Server_i.cpp</A> -<LI><A HREF="Handler.h">Handler.h</A> -<LI><A HREF="Handler.cpp">Handler.cpp</A> -</UL> -<P> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page10.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/015/page10.html b/docs/tutorials/015/page10.html deleted file mode 100644 index ad8e5276f57..00000000000 --- a/docs/tutorials/015/page10.html +++ /dev/null @@ -1,128 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -And so finally we come to the Protocol_Stream. That, after all, is -the focus of the entire tutorial but it took us half of the day to get -here! -<P> -The Protocol_Stream uses an ACE_Stream to move an ACE_Message_Block -through a series of tasks. Each task in the stream is responsible for -performing some operation on the data in the message block. That is -the nature of a protocol stream (or "stack" if you prefer). In this -stream, the data is compressed and encrypted* on its way between -peers. We also allow users of the stream to install a reader task to -handle data that percolates up from the peer. As you saw a page or -two ago, this is most useful for a server. - -<P> -<font size=-1>*Again, I just pretend to do these things. It would -take another day or two to go through any sort of reasonable -encryption or compression!</font> -<P> -Before we get into the code, here's a picture that's shows what's -going on here. -<P><center><img src="stream.gif"></center></p> -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>PROTOCOL_STREAM_H</font> -<font color=blue>#define</font> <font color=purple>PROTOCOL_STREAM_H</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Stream.h">ace/Stream.h</A>" - -<font color=red>// Shorthand for the stream.</font> -typedef ACE_Stream<ACE_MT_SYNCH> Stream; - -<font color=red>// Forward references to cut down on the number of <font color=blue>#include</font>s</font> -class ACE_Message_Block; -class Recv; -class Protocol_Task; - -<font color=red>/* The Protocol_Stream provides a tidy interface to an ACE_Stream - setup to process a data block through a series of protocol stages. -*/</font> -class Protocol_Stream -{ -public: - Protocol_Stream (void); - ~Protocol_Stream (void); - - <font color=red>// Provide the stream with an ACE_SOCK_Stream on which it can</font> - <font color=red>// communicate. If _reader is non-null, it will be added as the</font> - <font color=red>// reader task just below the stream head so that it can process</font> - <font color=red>// data read from the peer.</font> - int open (ACE_SOCK_Stream &peer, - Protocol_Task *reader = 0); - - <font color=red>// Close the stream. All of the tasks & modules will also be</font> - <font color=red>// closed.</font> - int close (void); - - <font color=red>// putting data onto the stream will pass it through all protocol</font> - <font color=red>// levels and send it to the peer.</font> - int put (ACE_Message_Block *&message, - ACE_Time_Value *timeout = 0); - - <font color=red>// get will cause the Recv task (at the tail of the stream) to read</font> - <font color=red>// some data from the peer and pass it upstream. The message block</font> - <font color=red>// is then taken from the stream reader task's message queue.</font> - int get (ACE_Message_Block *&response, - ACE_Time_Value *timeout = 0); - - <font color=red>// Tell the Recv task to read some data and send it upstream. The</font> - <font color=red>// data will pass through the protocol tasks and be queued into the</font> - <font color=red>// stream head reader task's message queue. If you've installed a</font> - <font color=red>// _reader in open() then that task's recv() method will see the</font> - <font color=red>// message and may consume it instead of passing it to the stream</font> - <font color=red>// head for queueing.</font> - int get (void); - - ACE_SOCK_Stream &peer (void) - { - return this->peer_; - } - -private: - <font color=red>// Our peer connection</font> - ACE_SOCK_Stream peer_; - - <font color=red>// The stream managing the various protocol tasks</font> - Stream stream_; - - <font color=red>// A task which is capable of receiving data on a socket.</font> - <font color=red>// Note that this is only useful by client-side applications.</font> - Recv *recv_; - - Stream &stream (void) - { - return this->stream_; - } - - <font color=red>// Install the protocol tasks into the stream.</font> - int open (void); -}; - -<font color=blue>#endif</font> <font color=red>/* PROTOCOL_STREAM_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page11.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/015/page11.html b/docs/tutorials/015/page11.html deleted file mode 100644 index 76e646f2076..00000000000 --- a/docs/tutorials/015/page11.html +++ /dev/null @@ -1,221 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -And now the implementation of the Protocol_Stream. There are more -lines of code here than we've seen so far but it still isn't -complicated. The basic idea is to construct the ACE_Stream with our -set of protocol objects that will manipulate the data. Our primary -concern in this file is to get everything in the correct order! -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Protocol_Stream.h</font>" -<font color=blue>#include</font> "<font color=green>Protocol_Task.h</font>" - -<font color=blue>#include</font> "<font color=green>Xmit.h</font>" -<font color=blue>#include</font> "<font color=green>Recv.h</font>" - -<font color=blue>#include</font> "<font color=green>Compressor.h</font>" -<font color=blue>#include</font> "<font color=green>Crypt.h</font>" - -<font color=blue>#include</font> "<A HREF="../../../ace/Stream_Modules.h">ace/Stream_Modules.h</A>" - -<font color=red>/* You can choose at compile time to include/exclude the protocol - pieces. -*/</font> -<font color=blue>#define</font> <font color=purple>ENABLE_COMPRESSION</font> -<font color=blue>#define</font> <font color=purple>ENABLE_ENCRYPTION</font> - -<font color=red>// The usual typedefs to make things easier to type.</font> -typedef ACE_Module<ACE_MT_SYNCH> Module; -typedef ACE_Thru_Task<ACE_MT_SYNCH> Thru_Task; - -<font color=red>/* An ACE_Stream is a collection of ACE_Modules. You can think of it - as a doubly-linked list if you like. Each Module contains two - ACE_Task derivatives. One of these tasks is used when sending data - "<font color=green>upstream</font>", the other is used for "<font color=green>downstream</font>" operation. In some - cases, you'll only need to move data in one direction. To provide - a placeholder for the other direction, ACE_Thru_Task can be used. - ACE_Thru_Task responds to the put() by simply invoking put_next() - to send the data to the next module. - */</font> - -<font color=red>/* Do-nothing constructor and destructor - */</font> - -<font color=#008888>Protocol_Stream::Protocol_Stream</font> (void) -{ -} - -<font color=#008888>Protocol_Stream::~Protocol_Stream</font> (void) -{ -} - -<font color=red>/* Even opening the stream is rather simple. The important thing to - remember is that the modules you push onto the stream first will be - at the tail (eg -- most downstream) end of things when you're - done. - */</font> -int -<font color=#008888>Protocol_Stream::open</font> (ACE_SOCK_Stream &peer, - Protocol_Task *reader) -{ - <font color=red>// Initialize our peer() to read/write the socket we're given</font> - peer_.set_handle (peer.get_handle ()); - - <font color=red>// Construct (and remember) the Recv object so that we can read from</font> - <font color=red>// the peer().</font> - ACE_NEW_RETURN (recv_, - Recv ( this->peer ()), - -1); - - <font color=red>// Add the transmit and receive tasks to the head of the stream. As</font> - <font color=red>// we add more modules these will get pushed downstream and end up</font> - <font color=red>// nearest the tail by the time we're done.</font> - if (stream ().push (new Module ("<font color=green>Xmit/Recv</font>", - new Xmit ( this->peer ()), - recv_)) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>stream().push(xmit/recv)</font>"), - -1); - - <font color=red>// Add any other protocol tasks to the stream. Each one is added at</font> - <font color=red>// the head. The net result is that Xmit/Recv are at the tail.</font> - if (this->open () == -1) - return -1; - - <font color=red>// If a reader task was provided then push that in as the upstream</font> - <font color=red>// side of the next-to-head module. Any data read from the peer()</font> - <font color=red>// will be sent through here last. Server applications will</font> - <font color=red>// typically use this task to do the actual processing of data.</font> - <font color=red>// Note the use of Thru_Task. Since a module must always have a</font> - <font color=red>// pair of tasks we use this on the writer side as a no-op.</font> - if (reader) - { - if (stream ().push (new Module ("<font color=green>Reader</font>", - new Thru_Task (), - reader)) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>stream().push(reader)</font>"), - -1); - } - - return 0; -} - -<font color=red>/* Add the necessary protocol objects to the stream. The way we're - pushing things on we will compress the data before encrypting it. -*/</font> -int -<font color=#008888>Protocol_Stream::open</font> (void) -{ -<font color=blue>#if defined</font> (<font color=purple>ENABLE_ENCRYPTION</font>) - if (stream ().push (new Module ("<font color=green>crypt</font>", - new Crypt (), - new Crypt ())) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>stream().push(crypt)</font>"), - -1); -<font color=blue>#endif</font> <font color=red>/* ENABLE_ENCRYPTION */</font> - -<font color=blue>#if defined</font> (<font color=purple>ENABLE_COMPRESSION</font>) - if (stream ().push (new Module ("<font color=green>compress</font>", - new Compressor (), - new Compressor ())) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>stream().push(comprssor)</font>"), - -1); -<font color=blue>#endif</font> <font color=red>/* ENABLE_COMPRESSION */</font> - return 0; -} - -<font color=red>// Closing the Protocol_Stream is as simple as closing the ACE_Stream.</font> -int -<font color=#008888>Protocol_Stream::close</font> (void) -{ - return stream ().close (); -} - -<font color=red>// Simply pass the data directly to the ACE_Stream.</font> -int -<font color=#008888>Protocol_Stream::put</font> (ACE_Message_Block *&message, - ACE_Time_Value *timeout) -{ - return stream ().put (message, - timeout); -} - -<font color=red>/* Tell the Recv module to read some data from the peer and pass it - upstream. Servers will typically use this method in a - handle_input() method to tell the stream to get a client's request. */</font> - -int -<font color=#008888>Protocol_Stream::get</font>(void) -{ - <font color=red>// If there is no Recv module, we're in big trouble!</font> - if (recv_ == 0) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>(%P|%t) No Recv object!\n</font>"), - -1); - - <font color=red>// This tells the Recv module to go to it's peer() and read some</font> - <font color=red>// data. Once read, that data will be pushed upstream. If there is</font> - <font color=red>// a reader object then it will have a chance to process the data.</font> - <font color=red>// If not, the received data will be available in the message queue</font> - <font color=red>// of the stream head's reader object (eg --</font> - <font color=red>// stream().head()->reader()->msg_queue()) and can be read with our</font> - <font color=red>// other get() method below.</font> - if (recv_->get () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>(%P|%t) Cannot queue read request\n</font>"), - -1); - - <font color=red>// For flexibility I've added an error() method to tell us if</font> - <font color=red>// something bad has happened to the Recv object.</font> - if (recv_->error ()) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>(%P|%t) Recv object error!\n</font>"), - -1); - - return 0; -} - -<font color=red>/* Take a message block off of the stream head reader's message queue. - If the queue is empty, use get() to read from the peer. This is - most often used by client applications. Servers will generaly - insert a reader that will prevent the data from getting all the way - upstream to the head. */</font> -int -<font color=#008888>Protocol_Stream::get</font> (ACE_Message_Block *&response, - ACE_Time_Value *timeout ) -{ - if (stream ().head ()->reader ()->msg_queue ()->is_empty () - && this->get () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>(%P|%t) Cannot get data into the stream.\n</font>"), - -1); - - return stream ().head ()->reader ()->getq (response, - timeout); -} -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page12.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/015/page12.html b/docs/tutorials/015/page12.html deleted file mode 100644 index 8863a45fda9..00000000000 --- a/docs/tutorials/015/page12.html +++ /dev/null @@ -1,82 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -A quick look at the Protocol_Task header... -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>PROTOCOL_TASK_H</font> -<font color=blue>#define</font> <font color=purple>PROTOCOL_TASK_H</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Task.h">ace/Task.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> - -<font color=red>/* A typical ACE_Task<> derivative that adds a few things appropriate - to protocol stacks. To keep things a little simpler, we prevent - activation of the task and just borrow the thread of control from - the calling method in all cases. -*/</font> -class Protocol_Task : public ACE_Task<ACE_MT_SYNCH> -{ -public: - typedef ACE_Task<ACE_MT_SYNCH> inherited; - - Protocol_Task (void); - - ~Protocol_Task (void); - - <font color=red>// open() is invoked when the task is inserted into the stream.</font> - virtual int open (void *arg); - - <font color=red>// close() is invoked when the stream is closed (flags will be set</font> - <font color=red>// to '1') and when the svc() method exits (flags will be '0').</font> - virtual int close (u_long flags); - - <font color=red>// As data travels through the stream, the put() method of each task</font> - <font color=red>// is invoked to keep the data moving along.</font> - virtual int put (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - <font color=red>// We're obligated to provide this signature even though we won't be</font> - <font color=red>// allowing this object to be activated.</font> - virtual int svc (void); - -protected: - - <font color=red>// Called by put() or svc() as necessary to process a block of data.</font> - int process (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - <font color=red>// Tasks on the writer (downstream) side of the stream are called</font> - <font color=red>// upon to send() data that will ultimately go to the peer.</font> - virtual int send (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - <font color=red>// Tasks on the reader (upstream) side will be receiving data that</font> - <font color=red>// came from the peer.</font> - virtual int recv (ACE_Message_Block *message, - ACE_Time_Value *timeout); - -}; - -<font color=blue>#endif</font> <font color=red>/* PROTOCOL_TASK_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page13.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/015/page13.html b/docs/tutorials/015/page13.html deleted file mode 100644 index 74ce35e96fd..00000000000 --- a/docs/tutorials/015/page13.html +++ /dev/null @@ -1,105 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The Protocol_Task implementation takes care of the open(), close(), -put() and svc() methods so that derivatives can concentrate on the -send() and recv() methods. After a while you find that most -ACE_Task<> derivatives look very similar in the four basic methods and -only need one or two additional to do any real work. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Protocol_Task.h</font>" -<font color=blue>#include</font> "<A HREF="../../../ace/ACE.h">ace/ACE.h</A>" - -<font color=red>// Construct the object and remember the thread count.</font> -<font color=#008888>Protocol_Task::Protocol_Task</font>(void) -{ - ; -} - -<font color=#008888>Protocol_Task::~Protocol_Task</font>(void) -{ - ; -} - -int <font color=#008888>Protocol_Task::open</font>(void *arg) -{ - ACE_UNUSED_ARG(arg); - - return(0); -} - -int <font color=#008888>Protocol_Task::close</font>(u_long flags) -{ - ACE_UNUSED_ARG(flags); - return 0; -} - -<font color=red>/* When a message is put() onto the task, it's time to process() some data. -*/</font> -int <font color=#008888>Protocol_Task::put</font>(ACE_Message_Block *message,ACE_Time_Value *timeout) -{ - return this->process(message,timeout); -} - -<font color=red>/* Return an error since we don't want the task to ever be activated. - */</font> -int <font color=#008888>Protocol_Task::svc</font>(void) -{ - return -1; -} - -<font color=red>/* There's nothing really magic about process(). We just decide if - we're moving data upstream or downstream and invoke the appropriate - virtual function to handle it. -*/</font> -int <font color=#008888>Protocol_Task::process</font>(ACE_Message_Block * message, ACE_Time_Value *timeout) -{ - if( this->is_writer() ) - { - return this->send(message,timeout); - } - - return this->recv(message,timeout); -} - -<font color=red>/* We must insist that derivatives provide a meaningful overload for - these methods. It's fairly common for ACE object methods to return - an error when an overload is expected but the method cannot be - safely made pure virtual. - */</font> - -int <font color=#008888>Protocol_Task::send</font>(ACE_Message_Block *message, - ACE_Time_Value *timeout) -{ - ACE_UNUSED_ARG(message); - ACE_UNUSED_ARG(timeout); - return -1; -} - -int <font color=#008888>Protocol_Task::recv</font>(ACE_Message_Block * message, - ACE_Time_Value *timeout) -{ - ACE_UNUSED_ARG(message); - ACE_UNUSED_ARG(timeout); - return -1; -} -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page14.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/015/page14.html b/docs/tutorials/015/page14.html deleted file mode 100644 index 735a6ee32ca..00000000000 --- a/docs/tutorials/015/page14.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The Xmit object knows how to send data to the peer. It sits at the -tail of the stream and gets everything that flows down from the head. -In keeping with the spirit of things, this object does only one thing -and doesn't concern itself with anyone else' details. -<P> -The only thing you might want to do is combine it with Recv. Why? -As you'll realize in a page or two, the Xmit and Recv objects must -interact if you're going to ensure a safe transit. By having a single -object it's easier to coordinate and maintain the interaction. -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>XMIT_H</font> -<font color=blue>#define</font> <font color=purple>XMIT_h</font> - -<font color=blue>#include</font> "<font color=green>Protocol_Task.h</font>" - -<font color=red>// Forward reference reduces <font color=blue>#include</font> dependencies</font> -class ACE_SOCK_Stream; - -<font color=red>/* A class suitable for sending data to a peer from within an - ACE_Stream. - */</font> -class Xmit : public Protocol_Task -{ -public: - typedef Protocol_Task inherited; - - <font color=red>// We must be given a valid peer when constructed. Without that we</font> - <font color=red>// don't know who to send data to.</font> - Xmit (ACE_SOCK_Stream &peer); - ~Xmit (void); - - <font color=red>// As you know, close() will be called in a couple of ways by the</font> - <font color=red>// ACE framework. We use that opportunity to terminate the</font> - <font color=red>// connection to the peer.</font> - int close (u_long flags); - -protected: - - ACE_SOCK_Stream &peer (void) - { - return this->peer_; - } - - <font color=red>// Send the data to the peer. By now it will have been completely</font> - <font color=red>// protocol-ized by other tasks in the stream.</font> - int send (ACE_Message_Block *message, - ACE_Time_Value *timeout); - -private: - <font color=red>// A representation of the peer we're talking to.</font> - ACE_SOCK_Stream &peer_; -}; - -<font color=blue>#endif</font> <font color=red>/* XMIT_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page15.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/015/page15.html b/docs/tutorials/015/page15.html deleted file mode 100644 index 17c6fa772f3..00000000000 --- a/docs/tutorials/015/page15.html +++ /dev/null @@ -1,120 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The implementation of Xmit isn't too complicated. If we choose to -combine it with the Recv task we simply lift the recv() method from -that object and drop it into this one. -<P> -Note that close() must decide if it's being called when the stream is -shutdown or when it's svc() method exits. Since we tell the baseclass -not to use any threads it's a safe bet that flags will always be -non-zero. Still, it's good practice to plan for the future by -checking the value. -<P> -Note also that when we send the data we prefix it with the data size. -This let's our sibling Recv ensure that an entire block is received -together. This can be very important for compression and encryption -processes which typically work better with blocks of data instead of -streams of data. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Xmit.h</font>" -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" - -<font color=red>/* Construct the object with the peer connection and choose not to - activate ourselves into a dedicated thread. You might get some - performance gain by activating but if you really want a - multi-threaded apprroach you should handle that as a separate - issue. Attempting to force threading at this level will likely - cause more trouble than you want to deal with. -*/</font> -<font color=#008888>Xmit::Xmit</font>( ACE_SOCK_Stream & _peer ) - : Protocol_Task(), peer_(_peer) -{ -} - -<font color=#008888>Xmit::~Xmit</font>(void) -{ -} - -<font color=red>/* Check to see if we're being closed by the stream (flags != 0) or if - we're responding to the exit of our svc() method. -*/</font> -int <font color=#008888>Xmit::close</font>(u_long flags) -{ - <font color=red>// Take care of the baseclass closure.</font> - int rval = <font color=#008888>inherited::close</font>(flags); - - <font color=red>// Only if we're being called at the stream shutdown do we close</font> - <font color=red>// the peer connection. If, for some reason, we were activated</font> - <font color=red>// into one or more threads we wouldn't want to close the pipe</font> - <font color=red>// before all threads had a chance to flush their data.</font> - if( flags ) - { - peer().close(); - } - - return( rval ); -} - -<font color=red>/* Our overload of send() will take care of sending the data to the - peer. -*/</font> -int <font color=#008888>Xmit::send</font>(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - int rval; - - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) <font color=#008888>Xmit::send</font>() sending (%s)(%d)\n</font>", message->rd_ptr(), message->length() )); - - <font color=red>/* Since we're going to be sending data that may have been - compressed and encrypted it's probably important for the - receiver to get an entire "<font color=green>block</font>" instead of having a - partial read. - - For that reason, we'll send the length of the message block - (in clear-text) to the peer so that it can then recv_n() - the entire block contents in one read operation. - */</font> - char msize[32]; - sprintf(msize,"<font color=green>%d</font>",message->length()); - - <font color=red>// Be sure we send the end-of-string NULL so that Recv will</font> - <font color=red>// know when to stop assembling the length.</font> - rval = this->peer().send_n( msize, strlen(msize)+1, 0, timeout ); - - if( rval == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green><font color=#008888>Xmit::send</font>() Failed to send message size.</font>"), -1); - } - - <font color=red>/* Now we send the actual data. If you're worried about - network efficiency then you may choose to create one buffer - containing msize and the message data and send it all at - once. - */</font> - rval = this->peer().send_n( message->rd_ptr(), message->length(), 0, timeout ); - - <font color=red>// Release the message block since we're done with it.</font> - message->release(); - - return( rval ); -} -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page16.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/015/page16.html b/docs/tutorials/015/page16.html deleted file mode 100644 index 023fd224ee0..00000000000 --- a/docs/tutorials/015/page16.html +++ /dev/null @@ -1,91 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -Recv is the sibling to Xmit. Again, they could be combined into a -single object if you want. -<P> -An ACE_Stream is designed to handle downstream traffic very -well. You put() data into it and it flows along towards the tail. -However, there doesn't seem to be a way to put data in such that it -will travel upstream. To get around that, I've added a get() method -to Recv that will trigger a read on the socket. Recv will then put -the data to the next upstream module and we're on our way. As noted -earlier, that data will eventually show up either in the <i>reader</i> -(if installed on the stream open()) or the stream head reader task's -message queue. -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>RECV_H</font> -<font color=blue>#define</font> <font color=purple>RECV_h</font> - -<font color=blue>#include</font> "<font color=green>Protocol_Task.h</font>" - -class ACE_SOCK_Stream; - -<font color=red>/* Get some data from the peer and send it upstream for - de-protocol-ization. -*/</font> -class Recv : public Protocol_Task -{ -public: - typedef Protocol_Task inherited; - - <font color=red>// Give it someone to talk to...</font> - Recv (ACE_SOCK_Stream &peer); - ~Recv (void); - - <font color=red>// Trigger a read from the socket</font> - int get (void); - - <font color=red>// In some cases it might be easier to check the "<font color=green>state</font>" of the Recv</font> - <font color=red>// object than to rely on return codes filtering back to you.</font> - int error (void) - { - return this->error_; - } - -protected: - - ACE_SOCK_Stream &peer (void) - { - return this->peer_; - } - - <font color=red>// The baseclass will trigger this when our get() method is called.</font> - <font color=red>// A message block of the appropriate size is created, filled and</font> - <font color=red>// passed up the stream.</font> - int recv (ACE_Message_Block *message, - ACE_Time_Value *timeout = 0); - -private: - <font color=red>// Our endpoint</font> - ACE_SOCK_Stream &peer_; - - <font color=red>// get() uses a bogus message block to cause the baseclass to invoke</font> - <font color=red>// recv(). To avoid memory thrashing, we create that bogus message</font> - <font color=red>// once and reuse it for the life of Recv.</font> - ACE_Message_Block *tickler_; - - <font color=red>// Our error flag (duh)</font> - int error_; -}; - -<font color=blue>#endif</font> <font color=red>/* RECV_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page17.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/015/page17.html b/docs/tutorials/015/page17.html deleted file mode 100644 index 7d8d52bf788..00000000000 --- a/docs/tutorials/015/page17.html +++ /dev/null @@ -1,118 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The Recv implementation is nearly as simple as Xmit. There's -opportunity for error when we get the message size and we have to -manage the lifetime of the tickler but other than that it's pretty -basic stuff. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Recv.h</font>" -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" - -<font color=red>/* Construct the object with the peer reference and other appropriate - initializations. -*/</font> -<font color=#008888>Recv::Recv</font>( ACE_SOCK_Stream & _peer ) - : Protocol_Task(), peer_(_peer), error_(0) -{ - <font color=red>// Create the tickler that get() will use to trigger recv()</font> - <font color=red>// through the baseclass. Since we're single-threaded this is</font> - <font color=red>// probably overkill but it makes multi-threading easier if we</font> - <font color=red>// choose to do that.</font> - tickler_ = new ACE_Message_Block(1); -} - -<font color=red>/* Be sure we manage the lifetime of the tickler to prevent a memory - leak. -*/</font> -<font color=#008888>Recv::~Recv</font>(void) -{ - tickler_->release(); -} - -<font color=red>/* By putting the tickler to ourselves we cause things to happen in - the baseclass that will invoke recv(). If we know we're single - threaded we could directly call recv() and be done with it but then - we'd have to do something else if we're multi-threaded. Just let - the baseclass worry about those things! -*/</font> -int <font color=#008888>Recv::get</font>(void) -{ - return this->put( tickler_, 0 ); -} - -int <font color=#008888>Recv::recv</font>(ACE_Message_Block * message, ACE_Time_Value *timeout) -{ - int rval; - - <font color=red>/* Xmit will send us the message length in clear-text. I - assume that will be less than 32-bytes! - */</font> - char msize[32]; - int b = 0; - - <font color=red>/* Read from the socket one byte at a time until we see then - end-of-string NULL character. Since the OS layers (at least - in Unix) will provide some buffering this isn't as bad as - it may seem at first. - - The byte-at-a-time recv breaks horribly on Win32 where the - WFMO_Reactor is used. This is because the socket has been - placed into non-blocking mode and only the recv() of the - first byte will block. The solution is to use - ACE_Select_Reactor which doesn't change the socket - characteristics. We did that back in main(), so we should - be in good shape now. - */</font> - do - { - rval = this->peer().recv( &msize[b], 1, timeout ); - if( rval == -1 ) - { - error_ = 1; - ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green><font color=#008888>Recv::recv</font>() Failed to get message size.</font>"), -1); - } - } - while( msize[b++] != 0 ); - - int size = <font color=#008888>ACE_OS::atoi</font>(msize); - - <font color=red>// Make a block big enough to contain the data we'll read</font> - message = new ACE_Message_Block( size ); - - <font color=red>// Read the actual message data into our new message block</font> - rval = this->peer().recv_n( message->wr_ptr(), size, 0, timeout ); - - <font color=red>// If we got the data correctly then send it on upstream.</font> - if( rval > 0 ) - { - message->wr_ptr( rval ); - return( this->put_next( message ) ); - } - - <font color=red>// Something bad happend on the recv_n(). Set an error flag</font> - <font color=red>// and return error.</font> - error_ = 1; - - return( -1 ); -} -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page18.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/015/page18.html b/docs/tutorials/015/page18.html deleted file mode 100644 index 00ceb114591..00000000000 --- a/docs/tutorials/015/page18.html +++ /dev/null @@ -1,62 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -This and the next three pages present the protocol objects that -provide compression and encryption. If you were hoping to learn the -secrets of compression and encryption then I'm going to disappoint -you. There are some really good libraries out there that do this -stuff though and if anyone wants to integrate one of them into the -tutorial I'll be glad to take it! -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>COMPRESSOR_H</font> -<font color=blue>#define</font> <font color=purple>COMPRESSOR_h</font> - -<font color=blue>#include</font> "<font color=green>Protocol_Task.h</font>" - -<font color=red>/* A reallly dumb compression object. (It actually adds 3 bytes to - every message block.) -*/</font> -class Compressor : public Protocol_Task -{ -public: - - typedef Protocol_Task inherited; - - Compressor (void); - - ~Compressor (void); - -protected: - - <font color=red>// This is called when the compressor is on the downstream side.</font> - <font color=red>// We'll take the message, compress it and move it along to the next</font> - <font color=red>// module.</font> - int send (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - <font color=red>// This one is called on the upstream side. No surprise: we</font> - <font color=red>// decompress the data and send it on up the stream.</font> - int recv (ACE_Message_Block *message, - ACE_Time_Value *timeout); -}; - -<font color=blue>#endif</font> <font color=red>/* COMPRESSOR_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page19.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/015/page19.html b/docs/tutorials/015/page19.html deleted file mode 100644 index c352e4d24a9..00000000000 --- a/docs/tutorials/015/page19.html +++ /dev/null @@ -1,126 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -Here we implement the details of our compression. By having both -compression and decompression in one object it's easier to keep track -of implementation details. Splitting Xmit/Recv like I did will make -things more difficult if something has to change in their interaction. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Compressor.h</font>" -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" - -<font color=#008888>Compressor::Compressor</font>( void ) - : Protocol_Task() -{ - ; -} - -<font color=#008888>Compressor::~Compressor</font>(void) -{ - ; -} - -<font color=red>/* This is where you insert your compression code. Most compressors - want to work on a block of data instead of a byte-stream. - Fortunately the message block has a block that can be compressed. - Take a look at libz for a quick way to add compression to your - apps - */</font> -int <font color=#008888>Compressor::send</font>(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - ACE_UNUSED_ARG(message); - ACE_UNUSED_ARG(timeout); - - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) <font color=#008888>Compressor::send</font>() compressing (%s)\n</font>", message->rd_ptr() )); - - <font color=red>// Create a block to hold the compressed data. I belive libz</font> - <font color=red>// recommends a buffer about 10-20% larger than the source.</font> - <font color=red>// Other libraries/algorithms may have their own quirks.</font> - ACE_Message_Block * compressed = new ACE_Message_Block( - message->size() +16 ); - - <font color=red>// Perform a bogus compression algorithm. 'CD' just tells me</font> - <font color=red>// that this is compressed data and when we "<font color=green>decompress</font>" we'll</font> - <font color=red>// look for this signature to validate the data received.</font> - <font color=#008888>ACE_OS::sprintf</font>( compressed->wr_ptr(), "<font color=green>CD:%s</font>", message->rd_ptr() ); - compressed->wr_ptr( strlen(compressed->wr_ptr())+1 ); - - <font color=red>// Send the compressed data down the stream to the next module</font> - this->put_next( compressed ); - - <font color=red>// We're done here.</font> - message->release(); - - return( 0 ); -} - -<font color=red>/* And here's the decompression side. We've written Xmit/Recv so that - we're guaranteed to get an entire block of compressed data. If - we'd used recv() in the Recv object then we might have gotten a - partial block and that may not decompress very nicely. - */</font> -int <font color=#008888>Compressor::recv</font>(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - ACE_UNUSED_ARG(message); - ACE_UNUSED_ARG(timeout); - - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) <font color=#008888>Compress::recv</font>() decompressing (%s)\n</font>", message->rd_ptr() )); - - <font color=red>// Room for the decompressed data. In the real world you</font> - <font color=red>// would probably want to send the original (uncompressed)</font> - <font color=red>// data size in the message. You can predict the maximum</font> - <font color=red>// possible decompression size but it's cheap and easy just to</font> - <font color=red>// send that along. Look again at how I do exacly that</font> - <font color=red>// between Xmit and Recv.</font> - ACE_Message_Block * decompressed = new ACE_Message_Block( - message->size() + 16 ); - - <font color=red>// Check for our signature. Even when you use a real</font> - <font color=red>// compression algorithm you may want to include your own</font> - <font color=red>// signature so that you can verify the block. It pays to be</font> - <font color=red>// paranoid!</font> - if( <font color=#008888>ACE_OS::strncmp</font>( message->rd_ptr(), "<font color=green>CD:</font>", 3 ) ) - { - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) Improperly encompressed data.\n</font>" )); - message->release(); - return(-1); - } - - <font color=red>// Skip past the signature before going any further.</font> - message->rd_ptr( 3 ); - - <font color=red>// Perform a bogus decompression algorithm. This is where you</font> - <font color=red>// would feed to libz or your favorite decompressor. (It's</font> - <font color=red>// costly but you could invoke popen() on gzip!)</font> - <font color=#008888>ACE_OS::sprintf</font>( decompressed->wr_ptr(), "<font color=green>%s</font>", message->rd_ptr() ); - decompressed->wr_ptr( strlen(decompressed->wr_ptr())+1 ); - - <font color=red>// Recv the decompressed data down the stream to the next module</font> - this->put_next( decompressed ); - - <font color=red>// We're done here.</font> - message->release(); - - return( 0 ); -} - -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page20.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/015/page20.html b/docs/tutorials/015/page20.html deleted file mode 100644 index 4f2d5833320..00000000000 --- a/docs/tutorials/015/page20.html +++ /dev/null @@ -1,60 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -While I might be able to come up with a competitive compressor, I -don't have a snowball's chance to code up encryption. I'd be better -off piping the data through the standard Unix crypt command. -<P> -So, while I was lazy with Compress, I'm realistic with Crypt. I'll -show you the hooks and entry points and let someone else contribute an -encryptor. -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>CRYPT_H</font> -<font color=blue>#define</font> <font color=purple>CRYPT_h</font> - -<font color=blue>#include</font> "<font color=green>Protocol_Task.h</font>" - -<font color=red>/* An interface (adaptor) between your favorite encryption method and - an ACE_Stream. -*/</font> -class Crypt : public Protocol_Task -{ -public: - - typedef Protocol_Task inherited; - - Crypt (void); - - ~Crypt (void); - -protected: - - <font color=red>// Moving downstream will encrypt the data</font> - int send (ACE_Message_Block *message, - ACE_Time_Value *timeout); - - <font color=red>// And moving upstream will decrypt it.</font> - int recv (ACE_Message_Block *message, - ACE_Time_Value *timeout); -}; - -<font color=blue>#endif</font> <font color=red>/* CRYPT_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page21.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/015/page21.html b/docs/tutorials/015/page21.html deleted file mode 100644 index daf4d2bc065..00000000000 --- a/docs/tutorials/015/page21.html +++ /dev/null @@ -1,107 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The encryption implementation isn't any smarter than that of the -compressor. Still, the hooks are there for you to insert your -favorite library. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Crypt.h</font>" -<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Stream.h">ace/SOCK_Stream.h</A>" - -<font color=red>/* The expected constructor... - */</font> -<font color=#008888>Crypt::Crypt</font>( void ) - : Protocol_Task() -{ -} - -<font color=#008888>Crypt::~Crypt</font>(void) -{ -} - -<font color=red>/* To send the data we'll apply a signature and encryption. - */</font> -int <font color=#008888>Crypt::send</font>(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - ACE_UNUSED_ARG(timeout); - - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) <font color=#008888>Crypt::send</font>() encrypting (%s)\n</font>", message->rd_ptr() )); - - <font color=red>// I suspect that some encryptors might change the data size.</font> - <font color=red>// It probably isn't safe to create a same-size destination buffer.</font> - ACE_Message_Block * encrypted = new ACE_Message_Block( - message->size() +16 ); - - <font color=red>// Perform a bogus encryption algorithm and add our safety</font> - <font color=red>// signature. Adding the original data size is also probably</font> - <font color=red>// a good idea that I haven't encorporated here.</font> - <font color=#008888>ACE_OS::sprintf</font>( encrypted->wr_ptr(), "<font color=green>ED:%s</font>", message->rd_ptr() ); - encrypted->wr_ptr( strlen(encrypted->wr_ptr())+1 ); - - <font color=red>// Send the encrypted data down the stream to the next module</font> - this->put_next( encrypted ); - - <font color=red>// We're done here.</font> - message->release(); - - return( 0 ); -} - -<font color=red>/* The upstream movement requires that we decrypt what the peer has - given us. -*/</font> -int <font color=#008888>Crypt::recv</font>(ACE_Message_Block *message, ACE_Time_Value *timeout) -{ - ACE_UNUSED_ARG(timeout); - - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) <font color=#008888>Crypt::recv</font>() decrypting (%s)\n</font>", message->rd_ptr() )); - - <font color=red>// Create a destination for the decrypted data. The same</font> - <font color=red>// block size caveat exists of course.</font> - ACE_Message_Block * decrypted = new ACE_Message_Block( - message->size() +16 ); - - <font color=red>// Check the signature as expected.</font> - if( <font color=#008888>ACE_OS::strncmp</font>( message->rd_ptr(), "<font color=green>ED:</font>", 3 ) ) - { - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) Improperly encrypted data.\n</font>" )); - message->release(); - return(-1); - } - - <font color=red>// Don't forget to skip past the signature before decrypting</font> - <font color=red>// or things will be quite exciting!</font> - message->rd_ptr( 3 ); - - <font color=red>// Perform a bogus decryption algorithm</font> - <font color=#008888>ACE_OS::sprintf</font>( decrypted->wr_ptr(), "<font color=green>%s</font>", message->rd_ptr() ); - decrypted->wr_ptr( strlen(decrypted->wr_ptr())+1 ); - - <font color=red>// Send the decrypted data down the stream to the next module</font> - this->put_next( decrypted ); - - <font color=red>// We're done here.</font> - message->release(); - - return( 0 ); -} -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page22.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/015/page22.html b/docs/tutorials/015/page22.html deleted file mode 100644 index abdf21976cd..00000000000 --- a/docs/tutorials/015/page22.html +++ /dev/null @@ -1,84 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 015</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 015</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Building a protocol stream</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -Well, this has certainly been one of the more verbose tutorials to -date. I must say "thanks" to everyone who stuck it out this far! -<P> -A quick review of what we've done: -<UL> - -<LI>Create a simple client application and Client object that uses a -Protocol Stream without really knowing how they work. The app (and -object) rely on the public interface of the Protocol Stream to get the -job done. At this level the protocol details are irrelevant. -<P> -<LI>Next, we create a simple server application and Server object -similar to the client. The Protocol Stream is of course used and we -have to know a little more so that we can insert a <i>reader</i> that -will ultimately process the data from the client. -<P> -<LI>We then go into the details of the Protocol_Stream implementation -and it's Protocol_Task object that forms the basis for the stream -tasks. Each object is kept as small and simple as possible to improve -reusability and future maintenance. -<P> -<LI>Finally, the individual protocol objects are discused. Separate -objects for the peer interface were created as well as the bogus -compressor and encryptor. The protocol can be extended or modified by -creating new such objects and installing them in the Protocol_Stream's -open() method. - -</UL> -<P> - -It doesn't sound like much but it certainly took a bunch of files to -get there. It's easy to get lost in the details when there's so much -to cover so you're encouraged to go over things a couple of times. -As always, enhancments of the tutorials is welcome! -<P> -Here's the complete file list: -<UL> -<LI><A HREF="client">Makefile</A> -<P> -<LI><A HREF="Makefile.client">client Makefile</A> -<LI><A HREF="client.cpp">client.cpp</A> -<LI><A HREF="Client_i.h">Client_i.h</A> -<LI><A HREF="Client_i.cpp">Client_i.cpp</A> -<P> -<LI><A HREF="Makefile.server">Server Makefile</A> -<LI><A HREF="server.cpp">server.cpp</A> -<LI><A HREF="Server_i.h">Server_i.h</A> -<LI><A HREF="Server_i.cpp">Server_i.cpp</A> -<LI><A HREF="Handler.h">Handler.h</A> -<LI><A HREF="Handler.cpp">Handler.cpp</A> -<P> -<LI><A HREF="Protocol_Stream.cpp">Protocol_Stream.cpp</A> -<LI><A HREF="Protocol_Stream.h">Protocol_Stream.h</A> -<LI><A HREF="Protocol_Task.cpp">Protocol_Task.cpp</A> -<LI><A HREF="Protocol_Task.h">Protocol_Task.h</A> -<P> -<LI><A HREF="Xmit.cpp">Xmit.cpp</A> -<LI><A HREF="Xmit.h">Xmit.h</A> -<LI><A HREF="Recv.cpp">Recv.cpp</A> -<LI><A HREF="Recv.h">Recv.h</A> -<P> -<LI><A HREF="Compressor.cpp">Compressor.cpp</A> -<LI><A HREF="Compressor.h">Compressor.h</A> -<LI><A HREF="Crypt.cpp">Crypt.cpp</A> -<LI><A HREF="Crypt.h">Crypt.h</A> -</UL> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/015/server.cpp b/docs/tutorials/015/server.cpp deleted file mode 100644 index 6841a6c9b04..00000000000 --- a/docs/tutorials/015/server.cpp +++ /dev/null @@ -1,68 +0,0 @@ - -// $Id$ - -#include "Server_i.h" -#include "ace/Select_Reactor.h" - -// A signal handler that will close the server object -extern "C" void handler (int) -{ - Server::close(); -} - -int main (int, char **) -{ - /* On Win32, the WFMO reactor is used by default. - Unfortunately, that causes the sockets to be put into - non-blocking mode which will break Recv::recv(). To - prevent that issue, I explicitly use the Select Reactor - instead. I'll talk more about the "problem" in the Recv - comments. - */ - - // First, we create a Select_Reactor that will do the work. - // To keep things simple, I'll create it on the stack. - ACE_Select_Reactor mySelectReactor; - - // Next, we need an ACE_Reactor that is the bridge between the - // code and the real reactor. It is given a pointer to the - // real reactor. - ACE_Reactor myReactor (&mySelectReactor); - - // Finally, we set the singleton instance to use the reactor - // we've created. - ACE_Reactor::instance (&myReactor); - - // The server object that abstracts away all of the difficult parts. - Server server; - - // Attempt to open the server. Like all good ACE-based - // objects, we'll get -1 on failure. - if( server.open() == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "server.open()"), -1); - } - - // Install a signal handler for ^C so that we can exit gracefully - ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT); - - // Run the server's main loop until we're interrupted - if( server.run() == -1 ) - { - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "server.run()"), -1); - } - - return 0; -} - -/* These explicit instantiations were taken from an earlier tutorial. - Your compiler may require others as well. -*/ -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Acceptor <Handler, ACE_SOCK_ACCEPTOR>; -template class ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>; -#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate ACE_Acceptor <Handler, ACE_SOCK_ACCEPTOR> -#pragma instantiate ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> -#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ - diff --git a/docs/tutorials/015/stream.gif b/docs/tutorials/015/stream.gif Binary files differdeleted file mode 100644 index 856bb92eeb7..00000000000 --- a/docs/tutorials/015/stream.gif +++ /dev/null diff --git a/docs/tutorials/016/016.dsp b/docs/tutorials/016/016.dsp deleted file mode 100644 index 3adcf4cc9db..00000000000 --- a/docs/tutorials/016/016.dsp +++ /dev/null @@ -1,108 +0,0 @@ -# Microsoft Developer Studio Project File - Name="016" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=016 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "016.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "016.mak" CFG="016 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "016 - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "016 - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "016 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "016 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"condition.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "016 - Win32 Release"
-# Name "016 - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\condition.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\Condition_i.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\Condition_i.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/016/Condition_i.cpp b/docs/tutorials/016/Condition_i.cpp deleted file mode 100644 index 20377f3c935..00000000000 --- a/docs/tutorials/016/Condition_i.cpp +++ /dev/null @@ -1,201 +0,0 @@ - -// $Id$ - -// Get or declaration -#include "Condition_i.h" - -/* Initialize the condition variable and create the condition mutex. - Since I don't have any guarantees on the order of member variable - initialization, I have to new the condition mutex instead of - simply constructing it. - */ -Condition::Condition(value_t _value) - : value_(_value) -{ - condition_ = new condition_t( this->mutex() ); -} - -Condition::~Condition(void) -{ - // Be sure we don't have a memeory leak - delete condition_; -} - -/* The cast operator is the easiest way to return a copy of the value - to clients of the class. It also allows us to use a private method - for getting a reference to the value when we need to modify it. - */ -Condition::operator Condition::value_t (void) -{ - // Place a guard around the variable so that it won't change as - // we're copying it back to the client. - guard_t guard(mutex_); - return value(); -} - -/* Traditional prefix increment operator. - We place a guard around the operation so that we don't collide with - any other threads. After the modification, we broadcast() a - condition change to any waiting threads. You can also use signal() - but that will only tell one thread about the change. If that - thread, in turn, invokes signal() then all threads will eventually - find out. I just thought it would be easier to use broadcast() and - be done with it. - */ -Condition & Condition::operator++ (void) -{ - guard_t guard(mutex_); - - ++value(); - - condition().broadcast(); - - return *this; -} - -/* The remaining operators all follow the same pattern that we have - above. They only differ in the modification they make to the value(). - */ - -Condition & Condition::operator-- (void) -{ - guard_t guard(mutex_); - - --value(); - - condition().broadcast(); - - return *this; -} - -Condition & Condition::operator+= (int _inc) -{ - guard_t guard(mutex_); - - value() += _inc; - - condition().broadcast(); - - return *this; -} - -Condition & Condition::operator-= (int _inc) -{ - guard_t guard(mutex_); - - value() -= _inc; - - condition().broadcast(); - - return *this; -} - -Condition & Condition::operator*= (int _inc) -{ - guard_t guard(mutex_); - - value() *= _inc; - - condition().broadcast(); - - return *this; -} - -Condition & Condition::operator/= (int _inc) -{ - guard_t guard(mutex_); - - value() /= _inc; - - condition().broadcast(); - - return *this; -} - -Condition & Condition::operator%= (int _inc) -{ - guard_t guard(mutex_); - - value() %= _inc; - - condition().broadcast(); - - return *this; -} - -Condition & Condition::operator= ( value_t _value ) -{ - guard_t guard(mutex_); - - value() = _value; - - condition().broadcast(); - - return *this; -} - -/* Now we get into the comparison area. - Each one follows the pattern we've already established for - waiters. - */ - -/* - We begin with an equality operator that expects a function object. - In the while() test we pass a copy of the value to the function - object for evaluation. The object can then do any comparision it - wants to check for a desired condition. When the function object - returns non-zero, the condition is met and we leave. - */ -int Condition::operator== ( Condition::Compare & _compare ) -{ - guard_t guard(mutex_); - - while( ! _compare(this->value()) ) - condition().wait(); - - return 0; -} - -// As long as the variable equals _value, we wait... -int Condition::operator== ( value_t _value ) -{ - guard_t guard(mutex_); - - while( value() == _value ) - condition().wait(); - - return 0; -} - -// As long as the variable is not equal to _value, we wait... -int Condition::operator!= ( value_t _value ) -{ - guard_t guard(mutex_); - - while( value() != _value ) - condition().wait(); - - return 0; -} - -// As long as the variable is less than or equal to _value, we wait... -int Condition::operator<= ( value_t _value ) -{ - guard_t guard(mutex_); - - while( value() <= _value ) - condition().wait(); - - return 0; -} - -// As long as the variable is greater than or equal to _value, we wait... -int Condition::operator>= ( value_t _value ) -{ - guard_t guard(mutex_); - - while( value() >= _value ) - condition().wait(); - - return 0; -} diff --git a/docs/tutorials/016/Condition_i.h b/docs/tutorials/016/Condition_i.h deleted file mode 100644 index 83f32489d20..00000000000 --- a/docs/tutorials/016/Condition_i.h +++ /dev/null @@ -1,154 +0,0 @@ -// $Id$ - -#ifndef CONDITION_H -#define CONDITION_H - -#include "ace/Synch.h" - -/** A wrapper for ACE_Condition<>. When you're using an - ACE_Condition<> you have to have three things: - Some variable - that embodies the condition you're looking for - A mutex to - prevent simultaneous access to that variable from different - threads - An ACE_Condition<> that enables blocking on state - changes in the variable The class I create here will contain those - three things. For the actual condition variable I've chosen an - integer. You could easily turn this class into a template - parameterized on the condition variable's data type if 'int' isn't - what you want. */ -class Condition -{ -public: - // From here on I'll use value_t instead of 'int' to make any - // future upgrades easier. - typedef int value_t; - - // Initialize the condition variable - Condition (value_t value = 0); - ~Condition (void); - - /* I've created a number of arithmetic operators on the class that - pass their operation on to the variable. If you turn this into a - template then some of these may not be appropriate... For the - ones that take a parameter, I've stuck with 'int' instead of - 'value_t' to reinforce the fact that you'll need a close look at - these if you choose to change the 'value_t' typedef. */ - - // Increment & decrement - Condition &operator++ (void); - Condition &operator-- (void); - - // Increase & decrease - Condition &operator+= (int inc); - Condition &operator-= (int inc); - - // Just to be complete - Condition &operator*= (int inc); - Condition &operator/= (int inc); - Condition &operator%= (int inc); - - // Set/Reset the condition variable's value - Condition &operator= (value_t value); - - /* These four operators perform the actual waiting. For instance: - - operator!=(int _value) - - is implemented as: - - Guard guard(mutex_) - while( value_ != _value ) - condition_.wait(); - - This is the "typical" use for condition mutexes. Each of the - operators below behaves this way for their respective - comparisions. - - To use one of these in code, you would simply do: - - Condition mycondition; - ... - // Wait until the condition variable has the value 42 - mycondition != 42 - ... */ - - // As long as the condition variable is NOT EQUAL TO <value>, we wait - int operator!= (value_t value); - - // As long as the condition variable is EXACTLY EQUAL TO <value>, we - // wait - int operator== (value_t value); - - // As long as the condition variable is LESS THAN OR EQUAL TO - // <value>, we wait - int operator<= (value_t value); - - // As long as the condition variable is GREATER THAN OR EQUAL TO - // <value>, we wait - int operator>= (value_t value); - - // Return the value of the condition variable - operator value_t (void); - - /* In addition to the four ways of waiting above, I've also create a - method that will invoke a function object for each iteration of - the while() loop. Derive yourself an object from - Condition::Compare and overload operator()(value_t) to take - advantage of this. Have the function return non-zero when you - consider the condition to be met. */ - class Compare - { - public: - virtual int operator() (value_t value) = 0; - }; - - /* Wait on the condition until _compare(value) returns non-zero. - This is a little odd since we're not really testing equality. - Just be sure that _compare(value_) will return non-zero when you - consider the condition to be met. */ - int operator== (Compare & compare); - -private: - // Prevent copy construction and assignment. - Condition (const Condition &condition); - Condition &operator= (const Condition &condition); - - /* Typedefs make things easier to change later. - ACE_Condition_Thread_Mutex is used as a shorthand for - ACE_Condition<ACE_Thread_Mutex> and also because it may provide - optimizations we can use. */ - typedef ACE_Thread_Mutex mutex_t; - typedef ACE_Condition_Thread_Mutex condition_t; - typedef ACE_Guard<mutex_t> guard_t; - - // The mutex that keeps the data save - mutex_t mutex_; - - // The condition mutex that makes waiting on the condition easier. - condition_t *condition_; - - // The acutal variable that embodies the condition we're waiting - // for. - value_t value_; - - // Accessors for the two mutexes. - mutex_t &mutex (void) - { - return this->mutex_; - } - - condition_t &condition (void) - { - return *this->condition_; - } - - // This particular accessor will make things much easier if we - // decide that 'int' isn't the correct datatype for value_. Note - // that we keep this private and force clients of the class to use - // the cast operator to get a copy of the value. - value_t &value (void) - { - return this->value_; - } -}; - -#endif /* CONDITION_H */ diff --git a/docs/tutorials/016/Makefile b/docs/tutorials/016/Makefile deleted file mode 100644 index f367f64df66..00000000000 --- a/docs/tutorials/016/Makefile +++ /dev/null @@ -1,77 +0,0 @@ - -# $Id$ - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = condition - -FILES = Condition_i - -BUILD = $(VBIN) - -SRC = $(addsuffix .cpp,$(BIN)) -SRC += $(addsuffix .cpp,$(FILES)) - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -rename : # - for i in *.cxx ; do \ - n=`expr "$$i" : "\(.*\).cxx"` ;\ - mv $$i $$n.cpp ;\ - done - -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb -ts2 -bl -bli0 < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - -e 's/ / /g' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - -Depend : depend - perl ../fix.Makefile - -.depend : # - touch .depend - -HTML : # - [ -f hdr ] || $(MAKE) UNSHAR - perl ../combine *.pre - -SHAR : # - [ ! -f combine.shar ] || exit 1 - shar -T hdr bodies *.pre > combine.shar && $(RM) hdr bodies *.pre - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - -include .depend diff --git a/docs/tutorials/016/combine.shar b/docs/tutorials/016/combine.shar deleted file mode 100644 index ec4a311e54a..00000000000 --- a/docs/tutorials/016/combine.shar +++ /dev/null @@ -1,385 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/016'. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 422 -rw-rw-r-- hdr -# 51 -rw-rw-r-- bodies -# 2905 -rw-rw-r-- page01.pre -# 1349 -rw-rw-r-- page02.pre -# 247 -rw-rw-r-- page03.pre -# 310 -rw-rw-r-- page04.pre -# 606 -rw-rw-r-- page05.pre -# -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 _sh00306; 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 016</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> -X -<CENTER><B><FONT SIZE=+2>ACE Tutorial 016</FONT></B></CENTER> -X -<CENTER><B><FONT SIZE=+2>Making ACE_Condition easier to use</FONT></B></CENTER> -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -34600093c989939b7a2a6806f2b18f22 hdr -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`" - test 422 -eq "$shar_count" || - $echo 'hdr:' 'original size' '422,' '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 -Condition_i.h -Condition_i.cpp -condition.cpp -SHAR_EOF - $shar_touch -am 1029153398 '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' -53b96616ae101b38fd1e30b2ab8707a2 bodies -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`" - test 51 -eq "$shar_count" || - $echo 'bodies:' 'original size' '51,' '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' && -The ACE framework has quite a few objects for syncronizing your -threads and even processes. We've mentioned a few in passing already: -X ACE_Thread_Mutex and ACE_Barrier for instance. -<P> -Another interesting one is the ACE_Condition template. By using an -ACE_Condition you can have your code wait for an arbitrary condition -to occur. That condition is "embodied" in a variable of your choice. -That variable can, in turn, be any data type you wish. This makes -ACE_Condition much more flexible than a simple mutex, barrier or -semaphore. -<P> -In this tutorial, I'll create a wrapper class around the ACE_Condition -and the assorted housekeeping items necessary to make it work. I'll -use a simple integer as the condition variable but keep in mind that -you can use any data type you want. -<P> -Kirthika's abstract: -<ul> -An ACE_Condition class is a synchronisation mechanism employed in -situations where one or more threads cannot access the shared resource -unless some 'condition' becomes true. The ACE_Condition is associated -with a Mutex-lock which is released before blocking internally in the -wait call. Once the blocked thread is signaled to wake up again it -internally re-acquires the lock before checking the condition. -Unless the condition is true and it has the lock, it cant go ahead. -Once the shared resource is freed, a signal is sent to the waiting -threads which can now contend for the lock and access the resource. -<P> -Pizza-delivery metaphor: (courtesy Dr.Schmidt) -<ul> -Pizza delivery boy -- thread<br> -keys to delivery van -- mutex-lock<br> -pizza ready for delivery -- condition<br> -</Ul> -Situation: <br> -<ul> -Five pizza delivery boys use the same van. While the van is -unavailable, the boys go to sleep. When the van returns and the keys -are returned, the current user of the van nudges the other sleeping boys -to wake up and fight for the keys. Once the keys are obtained and the -pizza -is ready and out of the kitchen, the boy with the pizza and the keys can -now deliver it. -</ul> -<P> -This tutorial makes use of a wrapper class around the ACE_Condition and -uses a integer value as the condition. The four kinds of condition -implemented -are: !=, >=, <=, == by using C++ operator overloading. Guards are used -within -the methods to make sure that the method is thread-safe. Once the thread -completes -its job, it broadcasts to the waiting on it. -<P> -An ACE_Task is used to stress test the various conditions. -A test object is created for each condition and the main thread waits -until the condition becomes true. For instance: <= condition: -Five threads are spwaned which in turn increment the condition -variable, which is initialised to 1 by 2. Remember that you are waiting -on -the <= condition. So once 3 threads have been thru it, the value becomes -6 -and the condition becomes true! -<P> -This simple example shows us how to program and use the Condition -variable for -synchronisation. -</ul> -SHAR_EOF - $shar_touch -am 03191459100 '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' -a6fd2e6607a2b96c93d8a829a1fb53cc page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 2905 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '2905,' '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 the declaration of the wrapper class. -<P> -The way you use ACE_Condition is something like this: -<UL> -<LI>First, the setup... -<UL> -<LI>Create a variable using your choice of data types -<LI>Create a mutex that will provide thread-safe access to that -variable -<LI>Create an ACE_Condition that uses the mutex -</UL> -<P> -<LI>Waiting for the condition... -<UL> -<PRE> -the_mutex.acquire(); -while( the_variable != some_desired_state_or_value ) -X the_condition.wait(); -the_mutex.release(); -</PRE> -Note that when <i>the_condition</i> is created, it must be given a -reference to the mutex. That's because the wait() method will release -the mutex before waiting and reacquire it after being signaled. -</UL> -<P> -<LI>Setting the condition... -<UL> -<PRE> -the_mutex.acquire(); -the_variable = some_new_value_or_state; -the_condition.signal() <i>OR</i> the_condition.broadcast() -</pre> -</UL> -</UL> -<P> -The problem I have is remembering to setup everything and co-ordinate -the locking, waiting and signaling. Even if I remember it all -correctly it just makes my application code more complex than it -should be. -<P> -To help out with that, I've created the class below to encapsulate the -three elements necessary for the condition to work. I've then added -methods for manipulation of the condition variable and waiting for the -condition to occur. -<HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -6c1b6e8f9597666558619d52c87be915 page02.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`" - test 1349 -eq "$shar_count" || - $echo 'page02.pre:' 'original size' '1349,' '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' && -Ok, now we'll take a look at the definition of the class. You already -know how to use an ACE_Condition & it's not really that difficult. -Still, imagine how much more cluttered your code would be if it had to -include the mess I've got below! -<HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -bdf2bed6845300288a14d1a41f6ef8a6 page03.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`" - test 247 -eq "$shar_count" || - $echo 'page03.pre:' 'original size' '247,' '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' && -We finally get to the main() application. I create a simple Task -derivative that will serve as a baseclass for other objects that test -specific functions of the Condition class. Notice how easy it is to -integrate a Condition into the application without keeping track of -three related member variables. -<HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -a2b2c42216f88e006a18d37adcb31c1d page04.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`" - test 310 -eq "$shar_count" || - $echo 'page04.pre:' 'original size' '310,' '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' && -And that's all... -<P> -For general use, it would make sense to convert Condition into a -template and get rid of some of the operators that don't make sense. -Using an integer as the condition type probably isn't realistic since -you could just use a semaphore or barrier for that case. Still, the -Tutorial shows the basics and provides a foundation on which you can -create a more useful class for your application. -<P> -<UL> -<LI><A HREF="Condition_i.h">Condition_i.h</A> -<LI><A HREF="Condition_i.cpp">Condition_i.cpp</A> -<LI><A HREF="condition.cpp">condition.cpp</A> -<LI><A HREF="Makefile">Makefile</A> -</UL> -SHAR_EOF - $shar_touch -am 03191459100 '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' -3926547773016bf56d809fae9170625e page05.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`" - test 606 -eq "$shar_count" || - $echo 'page05.pre:' 'original size' '606,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh00306 -exit 0 diff --git a/docs/tutorials/016/condition.cpp b/docs/tutorials/016/condition.cpp deleted file mode 100644 index 39690ca689b..00000000000 --- a/docs/tutorials/016/condition.cpp +++ /dev/null @@ -1,252 +0,0 @@ - -// $Id$ - -#include "Condition_i.h" -#include "ace/Task.h" - -/* In order to test our Condition we'll derive from ACE_Task<> so that - we can have several threads accessing the condition variable - together. - */ -class Test : public ACE_Task<ACE_NULL_SYNCH> -{ -public: - // Construct the condition variable with an initial value. - Test( int _max_threads, Condition::value_t _value ); - ~Test(void); - - // Open the Task with enough threads to make a useful test. - int open(void); - -protected: - // Each thread will do work on the Condition. - int svc(void); - - // Override this method to modify the Condition in some way. - virtual void modify(void) = 0; - - // Override this to test the Condition in some way. - virtual void test(void) = 0; - - // How many threads to use in the test. This is also used in the - // modify() and test() methods of the derivatives. - int max_threads_; - - // We want to sleep for a random amount of time to simulate - // work. The seed is necessary for proper random number generation. - ACE_RANDR_TYPE seed_; - - // This is the actual condition variable set. - Condition condition_; -}; - -// Initialize the condition variable. -Test::Test( int _max_threads, Condition::value_t _value ) - : max_threads_(_max_threads), condition_(_value) -{ - ; -} - -Test::~Test(void) -{ - ; -} - -// Seed the random number generator and start the threads. -int Test::open(void) -{ - seed_ = ACE_OS::gettimeofday().usec(); - - ACE_OS::srand( seed_ ); - - // This is not a place where we want to use THR_DETACHED. - // We're going to be waiting for our threads and if we detach - // them, we'll loose track and horrible things will happen. - return this->activate(THR_NEW_LWP, max_threads_); -} - -/* Each thread will modify the condition variable in some way and then - wait for the condition to be satisfied. The derived classes - overload modify() and test() to implement a specific test of the - Condition class. - */ -int Test::svc(void) -{ - // Take a moment before we modify the condition. This will - // cause test() in other threads to delay a bit. - int stime = ACE_OS::rand_r( seed_ ) % 5; - ACE_OS::sleep(abs(stime)+2); - - ACE_DEBUG ((LM_INFO, "(%P|%t|%T)\tTest::svc() befor modify, condition_ is: %d\n", (int)condition_ )); - - // Change the condition variable's value - modify(); - - ACE_DEBUG ((LM_INFO, "(%P|%t|%T)\tTest::svc() after modify, condition_ is: %d\n", (int)condition_ )); - - // Test for the condition we want - test(); - - ACE_DEBUG ((LM_INFO, "(%P|%t|%T)\tTest::svc() leaving.\n" )); - - return(0); -} - -/* Test Condition::operator!=() - The task's svc() method will increment the condition variable and - then wait until the variable's value reaches max_threads_. - */ -class Test_ne : public Test -{ -public: - // Initialize the condition variable to zero since we're counting up. - Test_ne( int _max_threads ) - : Test(_max_threads,0) - { - ACE_DEBUG ((LM_INFO, "\n(%P|%t|%T)\tTesting condition_ != %d\n", max_threads_)); - } - - // Increment the variable - void modify(void) - { - ++condition_; - } - - // Wait until it equals max_threads_ - void test(void) - { - condition_ != max_threads_; - } -}; - -/* Test Condition::operator>=() - Each svc() method will decrement the condition variable and wait - until it is less than max_threads_. To do this correctly, we have - to be careful where we start the condition variable. - */ -class Test_ge : public Test -{ -public: - // For max_threads_ == 5, we will start the condition variable at - // the value 9. When the "last" thread decrements it, the value - // will be 4 which satisfies the condition. - Test_ge( int _max_threads ) - : Test(_max_threads,_max_threads*2-1) - { - ACE_DEBUG ((LM_INFO, "\n(%P|%t|%T)\tTesting condition_ >= %d\n", max_threads_)); - } - - // Decrement by one... - void modify(void) - { - --condition_; - } - - // while( value >= max_threads_ ) wait(); - void test(void) - { - condition_ >= max_threads_; - } -}; - -/* Test Condition::operator<=() - This time we will increment the condition until it is greater than - max_threads_. Again, we have to be careful where we start the - value and how we increment. - */ -class Test_le : public Test -{ -public: - // I'm starting the value at 1 so that if we increment by one in - // each thread, the "last" thread (of 5) will set the value to - // 6. Since I actually increment by 2, we could start somewhat lower. - Test_le( int _max_threads ) - : Test( _max_threads, 1 ) - { - ACE_DEBUG ((LM_INFO, "\n(%P|%t|%T)\tTesting condition_ <= %d\n", max_threads_)); - } - - // Try out Condition::operator+=(int) - // This will cause the third thread to satisfy the condition. - void modify(void) - { - condition_ += 2; - } - - // while( value <= max_threads_ ) wait(); - void test(void) - { - condition_ <= max_threads_; - } -}; - -/* For our final test, we'll go after Condition::operator=(Condition::Compare) - By deriving from Condition::Compare we can perform any arbitrary - test on the value of the condition variable. - */ -class Test_fo : public Test -{ -public: - // We'll be using operator*=(int) to increment the condition - // variable, so we need to start with a non-zero value. - Test_fo( int _max_threads ) - : Test( _max_threads, 1 ) - { - ACE_DEBUG ((LM_INFO, "\n(%P|%t|%T)\tTesting condition_ == FunctionObject\n" )); - } - - // Double the value for each thread that we have. - void modify(void) - { - condition_ *= 2; - } - - /* Derive our CompareFunction and provide the operator() that - performs our test. In this case, we'll compare the value to - the number 32. - */ - class CompareFunction : public Condition::Compare - { - public: - // When this returns non-zero, the condition test operator - // will unblock in each thread. - // Note that 32 was chosen because 2**5 == 32. That is, the - // fifth thread will modify() the value to 32. - int operator() ( Condition::value_t _value ) - { - return _value == 32; - } - }; - - // Create the CompareFunction and wait for the condition variable - // to reach the state we want. - void test(void) - { - CompareFunction compare; - condition_ == compare; - } -}; - -/* In main() we just instantiate each of the four test objects that we - created. After open()ing each, we wait() for it's threads to exit. - */ -int main(int, char **) -{ - Test_ne test_ne(5); - test_ne.open(); - test_ne.wait(); - - Test_ge test_ge(5); - test_ge.open(); - test_ge.wait(); - - Test_le test_le(5); - test_le.open(); - test_le.wait(); - - Test_fo test_fo(5); - test_fo.open(); - test_fo.wait(); - - return(0); -} diff --git a/docs/tutorials/016/page01.html b/docs/tutorials/016/page01.html deleted file mode 100644 index 3bba1fd518b..00000000000 --- a/docs/tutorials/016/page01.html +++ /dev/null @@ -1,86 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 016</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 016</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Making ACE_Condition easier to use</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The ACE framework has quite a few objects for syncronizing your -threads and even processes. We've mentioned a few in passing already: - ACE_Thread_Mutex and ACE_Barrier for instance. -<P> -Another interesting one is the ACE_Condition template. By using an -ACE_Condition you can have your code wait for an arbitrary condition -to occur. That condition is "embodied" in a variable of your choice. -That variable can, in turn, be any data type you wish. This makes -ACE_Condition much more flexible than a simple mutex, barrier or -semaphore. -<P> -In this tutorial, I'll create a wrapper class around the ACE_Condition -and the assorted housekeeping items necessary to make it work. I'll -use a simple integer as the condition variable but keep in mind that -you can use any data type you want. -<P> -Kirthika's abstract: -<ul> -An ACE_Condition class is a synchronisation mechanism employed in -situations where one or more threads cannot access the shared resource -unless some 'condition' becomes true. The ACE_Condition is associated -with a Mutex-lock which is released before blocking internally in the -wait call. Once the blocked thread is signaled to wake up again it -internally re-acquires the lock before checking the condition. -Unless the condition is true and it has the lock, it cant go ahead. -Once the shared resource is freed, a signal is sent to the waiting -threads which can now contend for the lock and access the resource. -<P> -Pizza-delivery metaphor: (courtesy Dr.Schmidt) -<ul> -Pizza delivery boy -- thread<br> -keys to delivery van -- mutex-lock<br> -pizza ready for delivery -- condition<br> -</Ul> -Situation: <br> -<ul> -Five pizza delivery boys use the same van. While the van is -unavailable, the boys go to sleep. When the van returns and the keys -are returned, the current user of the van nudges the other sleeping boys -to wake up and fight for the keys. Once the keys are obtained and the -pizza -is ready and out of the kitchen, the boy with the pizza and the keys can -now deliver it. -</ul> -<P> -This tutorial makes use of a wrapper class around the ACE_Condition and -uses a integer value as the condition. The four kinds of condition -implemented -are: !=, >=, <=, == by using C++ operator overloading. Guards are used -within -the methods to make sure that the method is thread-safe. Once the thread -completes -its job, it broadcasts to the waiting on it. -<P> -An ACE_Task is used to stress test the various conditions. -A test object is created for each condition and the main thread waits -until the condition becomes true. For instance: <= condition: -Five threads are spwaned which in turn increment the condition -variable, which is initialised to 1 by 2. Remember that you are waiting -on -the <= condition. So once 3 threads have been thru it, the value becomes -6 -and the condition becomes true! -<P> -This simple example shows us how to program and use the Condition -variable for -synchronisation. -</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/016/page02.html b/docs/tutorials/016/page02.html deleted file mode 100644 index e84ce3853ad..00000000000 --- a/docs/tutorials/016/page02.html +++ /dev/null @@ -1,220 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 016</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 016</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Making ACE_Condition easier to use</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -We'll look first at the declaration of the wrapper class. -<P> -The way you use ACE_Condition is something like this: -<UL> -<LI>First, the setup... -<UL> -<LI>Create a variable using your choice of data types -<LI>Create a mutex that will provide thread-safe access to that -variable -<LI>Create an ACE_Condition that uses the mutex -</UL> -<P> -<LI>Waiting for the condition... -<UL> -<PRE> -the_mutex.acquire(); -while( the_variable != some_desired_state_or_value ) - the_condition.wait(); -the_mutex.release(); -</PRE> -Note that when <i>the_condition</i> is created, it must be given a -reference to the mutex. That's because the wait() method will implicitly release -the mutex before waiting and reacquire it after being signaled. -</UL> -<P> -<LI>Setting the condition... -<UL> -<PRE> -the_mutex.acquire(); -the_variable = some_new_value_or_state; -the_condition.signal() <i>OR</i> the_condition.broadcast() -the_mutex.release(); -</pre> -</UL> -</UL> -<P> -The problem I have is remembering to setup everything and co-ordinate -the locking, waiting and signaling. Even if I remember it all -correctly it just makes my application code more complex than it -should be. -<P> -To help out with that, I've created the class below to encapsulate the -three elements necessary for the condition to work. I've then added -methods for manipulation of the condition variable and waiting for the -condition to occur. -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>CONDITION_H</font> -<font color=blue>#define</font> <font color=purple>CONDITION_H</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Synch.h">ace/Synch.h</A>" - -<font color=red>/** A wrapper for ACE_Condition<>. When you're using an - ACE_Condition<> you have to have three things: - Some variable - that embodies the condition you're looking for - A mutex to - prevent simultaneous access to that variable from different - threads - An ACE_Condition<> that enables blocking on state - changes in the variable The class I create here will contain those - three things. For the actual condition variable I've chosen an - integer. You could easily turn this class into a template - parameterized on the condition variable's data type if 'int' isn't - what you want. */</font> -class Condition -{ -public: - <font color=red>// From here on I'll use value_t instead of 'int' to make any</font> - <font color=red>// future upgrades easier.</font> - typedef int value_t; - - <font color=red>// Initialize the condition variable</font> - Condition (value_t value = 0); - ~Condition (void); - - <font color=red>/* I've created a number of arithmetic operators on the class that - pass their operation on to the variable. If you turn this into a - template then some of these may not be appropriate... For the - ones that take a parameter, I've stuck with 'int' instead of - 'value_t' to reinforce the fact that you'll need a close look at - these if you choose to change the 'value_t' typedef. */</font> - - <font color=red>// Increment & decrement</font> - Condition &operator++ (void); - Condition &operator-- (void); - - <font color=red>// Increase & decrease</font> - Condition &operator+= (int inc); - Condition &operator-= (int inc); - - <font color=red>// Just to be complete</font> - Condition &operator*= (int inc); - Condition &operator/= (int inc); - Condition &operator%= (int inc); - - <font color=red>// Set/Reset the condition variable's value</font> - Condition &operator= (value_t value); - - <font color=red>/* These four operators perform the actual waiting. For instance: - - operator!=(int _value) - - is implemented as: - - Guard guard(mutex_) - while( value_ != _value ) - condition_.wait(); - - This is the "<font color=green>typical</font>" use for condition mutexes. Each of the - operators below behaves this way for their respective - comparisions. - - To use one of these in code, you would simply do: - - Condition mycondition; - ... - <font color=red>// Wait until the condition variable has the value 42</font> - mycondition != 42 - ... */</font> - - <font color=red>// As long as the condition variable is NOT EQUAL TO <value>, we wait</font> - int operator!= (value_t value); - - <font color=red>// As long as the condition variable is EXACTLY EQUAL TO <value>, we</font> - <font color=red>// wait</font> - int operator== (value_t value); - - <font color=red>// As long as the condition variable is LESS THAN OR EQUAL TO</font> - <font color=red>// <value>, we wait</font> - int operator<= (value_t value); - - <font color=red>// As long as the condition variable is GREATER THAN OR EQUAL TO</font> - <font color=red>// <value>, we wait</font> - int operator>= (value_t value); - - <font color=red>// Return the value of the condition variable</font> - operator value_t (void); - - <font color=red>/* In addition to the four ways of waiting above, I've also create a - method that will invoke a function object for each iteration of - the while() loop. Derive yourself an object from - <font color=#008888>Condition::Compare</font> and overload operator()(value_t) to take - advantage of this. Have the function return non-zero when you - consider the condition to be met. */</font> - class Compare - { - public: - virtual int operator() (value_t value) = 0; - }; - - <font color=red>/* Wait on the condition until _compare(value) returns non-zero. - This is a little odd since we're not really testing equality. - Just be sure that _compare(value_) will return non-zero when you - consider the condition to be met. */</font> - int operator== (Compare & compare); - -private: - <font color=red>// Prevent copy construction and assignment.</font> - Condition (const Condition &condition); - Condition &operator= (const Condition &condition); - - <font color=red>/* Typedefs make things easier to change later. - ACE_Condition_Thread_Mutex is used as a shorthand for - ACE_Condition<ACE_Thread_Mutex> and also because it may provide - optimizations we can use. */</font> - typedef ACE_Thread_Mutex mutex_t; - typedef ACE_Condition_Thread_Mutex condition_t; - typedef ACE_Guard<mutex_t> guard_t; - - <font color=red>// The mutex that keeps the data save</font> - mutex_t mutex_; - - <font color=red>// The condition mutex that makes waiting on the condition easier.</font> - condition_t *condition_; - - <font color=red>// The acutal variable that embodies the condition we're waiting</font> - <font color=red>// for.</font> - value_t value_; - - <font color=red>// Accessors for the two mutexes.</font> - mutex_t &mutex (void) - { - return this->mutex_; - } - - condition_t &condition (void) - { - return *this->condition_; - } - - <font color=red>// This particular accessor will make things much easier if we</font> - <font color=red>// decide that 'int' isn't the correct datatype for value_. Note</font> - <font color=red>// that we keep this private and force clients of the class to use</font> - <font color=red>// the cast operator to get a copy of the value.</font> - value_t &value (void) - { - return this->value_; - } -}; - -<font color=blue>#endif</font> <font color=red>/* CONDITION_H */</font> -</PRE> -<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/016/page03.html b/docs/tutorials/016/page03.html deleted file mode 100644 index 608eb388e5d..00000000000 --- a/docs/tutorials/016/page03.html +++ /dev/null @@ -1,226 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 016</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 016</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Making ACE_Condition easier to use</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -Ok, now we'll take a look at the definition of the class. You already -know how to use an ACE_Condition & it's not really that difficult. -Still, imagine how much more cluttered your code would be if it had to -include the mess I've got below! -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=red>// Get or declaration</font> -<font color=blue>#include</font> "<font color=green>Condition_i.h</font>" - -<font color=red>/* Initialize the condition variable and create the condition mutex. - Since I don't have any guarantees on the order of member variable - initialization, I have to new the condition mutex instead of - simply constructing it. - */</font> -<font color=#008888>Condition::Condition</font>(value_t _value) - : value_(_value) -{ - condition_ = new condition_t( this->mutex() ); -} - -<font color=#008888>Condition::~Condition</font>(void) -{ - <font color=red>// Be sure we don't have a memeory leak</font> - delete condition_; -} - -<font color=red>/* The cast operator is the easiest way to return a copy of the value - to clients of the class. It also allows us to use a private method - for getting a reference to the value when we need to modify it. - */</font> -<font color=#008888>Condition::operator</font> Condition::value_t (void) -{ - <font color=red>// Place a guard around the variable so that it won't change as</font> - <font color=red>// we're copying it back to the client.</font> - guard_t guard(mutex_); - return value(); -} - -<font color=red>/* Traditional prefix increment operator. - We place a guard around the operation so that we don't collide with - any other threads. After the modification, we broadcast() a - condition change to any waiting threads. You can also use signal() - but that will only tell one thread about the change. If that - thread, in turn, invokes signal() then all threads will eventually - find out. I just thought it would be easier to use broadcast() and - be done with it. - */</font> -Condition & <font color=#008888>Condition::operator</font>++ (void) -{ - guard_t guard(mutex_); - - ++value(); - - condition().broadcast(); - - return *this; -} - -<font color=red>/* The remaining operators all follow the same pattern that we have - above. They only differ in the modification they make to the value(). - */</font> - -Condition & <font color=#008888>Condition::operator</font>-- (void) -{ - guard_t guard(mutex_); - - --value(); - - condition().broadcast(); - - return *this; -} - -Condition & <font color=#008888>Condition::operator</font>+= (int _inc) -{ - guard_t guard(mutex_); - - value() += _inc; - - condition().broadcast(); - - return *this; -} - -Condition & <font color=#008888>Condition::operator</font>-= (int _inc) -{ - guard_t guard(mutex_); - - value() -= _inc; - - condition().broadcast(); - - return *this; -} - -Condition & <font color=#008888>Condition::operator</font>*= (int _inc) -{ - guard_t guard(mutex_); - - value() *= _inc; - - condition().broadcast(); - - return *this; -} - -Condition & <font color=#008888>Condition::operator</font>/= (int _inc) -{ - guard_t guard(mutex_); - - value() /= _inc; - - condition().broadcast(); - - return *this; -} - -Condition & <font color=#008888>Condition::operator</font>%= (int _inc) -{ - guard_t guard(mutex_); - - value() %= _inc; - - condition().broadcast(); - - return *this; -} - -Condition & <font color=#008888>Condition::operator</font>= ( value_t _value ) -{ - guard_t guard(mutex_); - - value() = _value; - - condition().broadcast(); - - return *this; -} - -<font color=red>/* Now we get into the comparison area. - Each one follows the pattern we've already established for - waiters. - */</font> - -<font color=red>/* - We begin with an equality operator that expects a function object. - In the while() test we pass a copy of the value to the function - object for evaluation. The object can then do any comparision it - wants to check for a desired condition. When the function object - returns non-zero, the condition is met and we leave. - */</font> -int <font color=#008888>Condition::operator</font>== ( Condition::Compare & _compare ) -{ - guard_t guard(mutex_); - - while( ! _compare(this->value()) ) - condition().wait(); - - return 0; -} - -<font color=red>// As long as the variable equals _value, we wait...</font> -int <font color=#008888>Condition::operator</font>== ( value_t _value ) -{ - guard_t guard(mutex_); - - while( value() == _value ) - condition().wait(); - - return 0; -} - -<font color=red>// As long as the variable is not equal to _value, we wait...</font> -int <font color=#008888>Condition::operator</font>!= ( value_t _value ) -{ - guard_t guard(mutex_); - - while( value() != _value ) - condition().wait(); - - return 0; -} - -<font color=red>// As long as the variable is less than or equal to _value, we wait...</font> -int <font color=#008888>Condition::operator</font><= ( value_t _value ) -{ - guard_t guard(mutex_); - - while( value() <= _value ) - condition().wait(); - - return 0; -} - -<font color=red>// As long as the variable is greater than or equal to _value, we wait...</font> -int <font color=#008888>Condition::operator</font>>= ( value_t _value ) -{ - guard_t guard(mutex_); - - while( value() >= _value ) - condition().wait(); - - return 0; -} -</PRE> -<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/016/page04.html b/docs/tutorials/016/page04.html deleted file mode 100644 index 5b803954c34..00000000000 --- a/docs/tutorials/016/page04.html +++ /dev/null @@ -1,278 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 016</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 016</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Making ACE_Condition easier to use</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -We finally get to the main() application. I create a simple Task -derivative that will serve as a baseclass for other objects that test -specific functions of the Condition class. Notice how easy it is to -integrate a Condition into the application without keeping track of -three related member variables. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Condition_i.h</font>" -<font color=blue>#include</font> "<A HREF="../../../ace/Task.h">ace/Task.h</A>" - -<font color=red>/* In order to test our Condition we'll derive from ACE_Task<> so that - we can have several threads accessing the condition variable - together. - */</font> -class Test : public ACE_Task<ACE_NULL_SYNCH> -{ -public: - <font color=red>// Construct the condition variable with an initial value.</font> - Test( int _max_threads, <font color=#008888>Condition::value_t</font> _value ); - ~Test(void); - - <font color=red>// Open the Task with enough threads to make a useful test.</font> - int open(void); - -protected: - <font color=red>// Each thread will do work on the Condition.</font> - int svc(void); - - <font color=red>// Override this method to modify the Condition in some way.</font> - virtual void modify(void) = 0; - - <font color=red>// Override this to test the Condition in some way.</font> - virtual void test(void) = 0; - - <font color=red>// How many threads to use in the test. This is also used in the</font> - <font color=red>// modify() and test() methods of the derivatives.</font> - int max_threads_; - - <font color=red>// We want to sleep for a random amount of time to simulate</font> - <font color=red>// work. The seed is necessary for proper random number generation.</font> - ACE_RANDR_TYPE seed_; - - <font color=red>// This is the actual condition variable set.</font> - Condition condition_; -}; - -<font color=red>// Initialize the condition variable.</font> -<font color=#008888>Test::Test</font>( int _max_threads, Condition::value_t _value ) - : max_threads_(_max_threads), condition_(_value) -{ - ; -} - -<font color=#008888>Test::~Test</font>(void) -{ - ; -} - -<font color=red>// Seed the random number generator and start the threads.</font> -int <font color=#008888>Test::open</font>(void) -{ - seed_ = <font color=#008888>ACE_OS::gettimeofday</font>().usec(); - - <font color=#008888>ACE_OS::srand</font>( seed_ ); - - <font color=red>// This is not a place where we want to use THR_DETACHED.</font> - <font color=red>// We're going to be waiting for our threads and if we detach</font> - <font color=red>// them, we'll loose track and horrible things will happen.</font> - return this->activate(THR_NEW_LWP, max_threads_); -} - -<font color=red>/* Each thread will modify the condition variable in some way and then - wait for the condition to be satisfied. The derived classes - overload modify() and test() to implement a specific test of the - Condition class. - */</font> -int <font color=#008888>Test::svc</font>(void) -{ - <font color=red>// Take a moment before we modify the condition. This will</font> - <font color=red>// cause test() in other threads to delay a bit.</font> - int stime = <font color=#008888>ACE_OS::rand_r</font>( seed_ ) % 5; - <font color=#008888>ACE_OS::sleep</font>(abs(stime)+2); - - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\<font color=#008888>tTest::svc</font>() befor modify, condition_ is: %d\n</font>", (int)condition_ )); - - <font color=red>// Change the condition variable's value</font> - modify(); - - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\<font color=#008888>tTest::svc</font>() after modify, condition_ is: %d\n</font>", (int)condition_ )); - - <font color=red>// Test for the condition we want</font> - test(); - - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\<font color=#008888>tTest::svc</font>() leaving.\n</font>" )); - - return(0); -} - -<font color=red>/* Test <font color=#008888>Condition::operator</font>!=() - The task's svc() method will increment the condition variable and - then wait until the variable's value reaches max_threads_. - */</font> -class Test_ne : public Test -{ -public: - <font color=red>// Initialize the condition variable to zero since we're counting up.</font> - Test_ne( int _max_threads ) - : Test(_max_threads,0) - { - ACE_DEBUG ((LM_INFO, "<font color=green>\n(%P|%t|%T)\tTesting condition_ != %d\n</font>", max_threads_)); - } - - <font color=red>// Increment the variable</font> - void modify(void) - { - ++condition_; - } - - <font color=red>// Wait until it equals max_threads_</font> - void test(void) - { - condition_ != max_threads_; - } -}; - -<font color=red>/* Test <font color=#008888>Condition::operator</font>>=() - Each svc() method will decrement the condition variable and wait - until it is less than max_threads_. To do this correctly, we have - to be careful where we start the condition variable. - */</font> -class Test_ge : public Test -{ -public: - <font color=red>// For max_threads_ == 5, we will start the condition variable at</font> - <font color=red>// the value 9. When the "<font color=green>last</font>" thread decrements it, the value</font> - <font color=red>// will be 4 which satisfies the condition.</font> - Test_ge( int _max_threads ) - : Test(_max_threads,_max_threads*2-1) - { - ACE_DEBUG ((LM_INFO, "<font color=green>\n(%P|%t|%T)\tTesting condition_ >= %d\n</font>", max_threads_)); - } - - <font color=red>// Decrement by one...</font> - void modify(void) - { - --condition_; - } - - <font color=red>// while( value >= max_threads_ ) wait();</font> - void test(void) - { - condition_ >= max_threads_; - } -}; - -<font color=red>/* Test <font color=#008888>Condition::operator</font><=() - This time we will increment the condition until it is greater than - max_threads_. Again, we have to be careful where we start the - value and how we increment. - */</font> -class Test_le : public Test -{ -public: - <font color=red>// I'm starting the value at 1 so that if we increment by one in</font> - <font color=red>// each thread, the "<font color=green>last</font>" thread (of 5) will set the value to</font> - <font color=red>// 6. Since I actually increment by 2, we could start somewhat lower.</font> - Test_le( int _max_threads ) - : Test( _max_threads, 1 ) - { - ACE_DEBUG ((LM_INFO, "<font color=green>\n(%P|%t|%T)\tTesting condition_ <= %d\n</font>", max_threads_)); - } - - <font color=red>// Try out <font color=#008888>Condition::operator</font>+=(int)</font> - <font color=red>// This will cause the third thread to satisfy the condition.</font> - void modify(void) - { - condition_ += 2; - } - - <font color=red>// while( value <= max_threads_ ) wait();</font> - void test(void) - { - condition_ <= max_threads_; - } -}; - -<font color=red>/* For our final test, we'll go after <font color=#008888>Condition::operator</font>=(Condition::Compare) - By deriving from <font color=#008888>Condition::Compare</font> we can perform any arbitrary - test on the value of the condition variable. - */</font> -class Test_fo : public Test -{ -public: - <font color=red>// We'll be using operator*=(int) to increment the condition</font> - <font color=red>// variable, so we need to start with a non-zero value.</font> - Test_fo( int _max_threads ) - : Test( _max_threads, 1 ) - { - ACE_DEBUG ((LM_INFO, "<font color=green>\n(%P|%t|%T)\tTesting condition_ == FunctionObject\n</font>" )); - } - - <font color=red>// Double the value for each thread that we have.</font> - void modify(void) - { - condition_ *= 2; - } - - <font color=red>/* Derive our CompareFunction and provide the operator() that - performs our test. In this case, we'll compare the value to - the number 32. - */</font> - class CompareFunction : public <font color=#008888>Condition::Compare</font> - { - public: - <font color=red>// When this returns non-zero, the condition test operator</font> - <font color=red>// will unblock in each thread.</font> - <font color=red>// Note that 32 was chosen because 2**5 == 32. That is, the</font> - <font color=red>// fifth thread will modify() the value to 32.</font> - int operator() ( <font color=#008888>Condition::value_t</font> _value ) - { - return _value == 32; - } - }; - - <font color=red>// Create the CompareFunction and wait for the condition variable</font> - <font color=red>// to reach the state we want.</font> - void test(void) - { - CompareFunction compare; - condition_ == compare; - } -}; - -<font color=red>/* In main() we just instantiate each of the four test objects that we - created. After open()ing each, we wait() for it's threads to exit. - */</font> -int main(int, char **) -{ - Test_ne test_ne(5); - test_ne.open(); - test_ne.wait(); - - Test_ge test_ge(5); - test_ge.open(); - test_ge.wait(); - - Test_le test_le(5); - test_le.open(); - test_le.wait(); - - Test_fo test_fo(5); - test_fo.open(); - test_fo.wait(); - - return(0); -} -</PRE> -<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/016/page05.html b/docs/tutorials/016/page05.html deleted file mode 100644 index c48eb8d0fba..00000000000 --- a/docs/tutorials/016/page05.html +++ /dev/null @@ -1,33 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 016</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 016</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Making ACE_Condition easier to use</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -And that's all... -<P> -For general use, it would make sense to convert Condition into a -template and get rid of some of the operators that don't make sense. -Using an integer as the condition type probably isn't realistic since -you could just use a semaphore or barrier for that case. Still, the -Tutorial shows the basics and provides a foundation on which you can -create a more useful class for your application. -<P> -<UL> -<LI><A HREF="Condition_i.h">Condition_i.h</A> -<LI><A HREF="Condition_i.cpp">Condition_i.cpp</A> -<LI><A HREF="condition.cpp">condition.cpp</A> -<LI><A HREF="Makefile">Makefile</A> -</UL> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/017/017.dsp b/docs/tutorials/017/017.dsp deleted file mode 100644 index 932599a7a46..00000000000 --- a/docs/tutorials/017/017.dsp +++ /dev/null @@ -1,108 +0,0 @@ -# Microsoft Developer Studio Project File - Name="017" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=017 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "017.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "017.mak" CFG="017 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "017 - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "017 - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "017 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "017 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"barrier.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "017 - Win32 Release"
-# Name "017 - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\barrier.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\Barrier_i.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\Barrier_i.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/017/Barrier_i.cpp b/docs/tutorials/017/Barrier_i.cpp deleted file mode 100644 index 0784205360a..00000000000 --- a/docs/tutorials/017/Barrier_i.cpp +++ /dev/null @@ -1,160 +0,0 @@ - -// $Id$ - -#include "Barrier_i.h" - -/* Initialize the threads_ count to zero and the barrier_ pointer to a - safe value. At the same time, we remember the thread that created - us so that we can allow it to change the thread count. -*/ -Barrier::Barrier(void) - : threads_(0) - ,barrier_(0) - ,new_barrier_(0) -{ - owner_ = ACE_OS::thr_self(); -} - -/* Ensure that barrier_ get's deleted so that we don't have a memory leak. - */ -Barrier::~Barrier(void) -{ - delete barrier_; -} - -void Barrier::owner( ACE_thread_t _owner ) -{ - owner_ = _owner; -} - -// Report on the number of threads. -u_int Barrier::threads(void) -{ - return threads_.value(); -} - -/* Allow the owning thread to (re)set the number of threads. - make_barrier() is called because it will wait() if we were already - configured. Typical usage would be for the worker threads to - wait() while the primary (eg -- owner) thread adjusts the thread - count. - - For instance: - In the worker threads: - if( myBarrier.threads() != current_thread_count ) - myBarrier.wait(); - - In the primary thread: - if( myBarrier.threads() != current_thread_count ) - myBarrier.threads( current_thread_count, 1 ); - */ -int Barrier::threads( u_int _threads, int _wait ) -{ - if( ! ACE_OS::thr_equal(ACE_OS::thr_self(), owner_) ) - { - return -1; - } - - threads_ = _threads; - - return make_barrier(_wait); -} - -/* Wait for all threads to synch if the thread count is valid. Note - that barrier_ will be 0 if the threads() mutator has not been - invoked. -*/ -int Barrier::wait(void) -{ - if( ! barrier_ ) - { - return -1; - } - - // If the threads() mutator has been used, new_barrier_ will - // point to a new ACE_Barrier instance. We'll use a - // traditional double-check here to move that new object into - // place and cleanup the old one. - if( new_barrier_ ) - { - // mutex so that only one thread can do this part. - ACE_Guard<ACE_Mutex> mutex(barrier_mutex_); - - // We only want the first thread to plug in the new barrier... - if( new_barrier_ ) - { - // out with the old and in with the new. - delete barrier_; - barrier_ = new_barrier_; - new_barrier_ = 0; - } - } - - return barrier_->wait(); -} - -/* Wait for all threads to synch. As each thread passes wait(), it - will decrement our thread counter. (That is why we had to make - threads_ an atomic op.) When the last thread decrements the - counter it will also delete the ACE_Barrier & free up a little - memory. -*/ -int Barrier::done(void) -{ - if( this->wait() == -1 ) - { - return -1; - } - - --threads_; - - if( ! threads_.value() ) - { - delete barrier_; - barrier_ = 0; - } - - return 0; -} - -/* This will build the actual barrier. I broke this code out of the - threads() mutator in case it might be useful elsewhere. - If a barrier already exists, we will wait for all threads before - creating a new one. This trait is what allows the threads mutator - to be used as shown above. - */ -int Barrier::make_barrier( int _wait ) -{ - // Ensure we have a valid thread count. - if( ! threads_.value() ) - { - return -1; - } - - // If a barrier already exists, we'll arrange for it to be - // replaced through the wait() method above. - if( barrier_ ) - { - // Create the new barrier that wait() will install for us. - ACE_NEW_RETURN(new_barrier_,ACE_Barrier(threads_.value()),-1); - - // Wait for our siblings to synch before continuing - if( _wait ) - { - barrier_->wait(); - } - } - else - { - // Create the initial barrier. - ACE_NEW_RETURN(barrier_,ACE_Barrier(threads_.value()),-1); - } - - return 0; -} - -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Atomic_Op <ACE_Mutex, u_int>; -#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate ACE_Atomic_Op <ACE_Mutex, u_int> -#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/docs/tutorials/017/Barrier_i.h b/docs/tutorials/017/Barrier_i.h deleted file mode 100644 index cb9c3d4ce0e..00000000000 --- a/docs/tutorials/017/Barrier_i.h +++ /dev/null @@ -1,67 +0,0 @@ -// $Id$ - -#ifndef BARRIER_H -#define BARRIER_H - -#include "ace/Synch.h" -#include "ace/Atomic_Op.h" - -/* Barrier is a simple wrapper for the ACE_Barrier synchronization - class. The ACE_Barrier is already pretty easy to use but I thought - I'd wrap it up to create just a bit more abstraction at the - application level. */ - -class Barrier -{ -public: - // Basic constructor and destructor. If you only need to synch the - // start of your threads, you can safely delete your Barrier object - // after invoking done(). Of course, you should be careful to only - // delete the object once! - Barrier (void); - ~Barrier (void); - - // Set and get the number of threads that the barrier will manage. - // If you add or remove threads to your application at run-time you - // can use the mutator to reflect that change. Note, however, that - // you can only do that from the thread which first created the - // Barrier. (This is a limitation of my Barrier object, not the - // ACE_Barrier.) The optional _wait parameter will cause wait() to - // be invoked if there is already a valid threads value. - int threads (u_int threads, int wait = 0); - u_int threads (void); - - // Wait for all threads to reach the point where this is invoked. - // Because of the snappy way in which ACE_Barrier is implemented, - // you can invoke these back-to-back with no ill-effects. - int wait (void); - - // done() will invoke wait(). Before returning though, it will - // delete the barrier_ pointer below to reclaim some memory. - int done (void); - - // Reset the owning thread of the barrier. - void owner( ACE_thread_t _owner ); - -protected: - // The number of threads we're synching - ACE_Atomic_Op<ACE_Mutex, u_int> threads_; - - // The ACE_Barrier that does all of the work - ACE_Barrier *barrier_; - - // If we mutate the number of threads we have to do some black magic - // to make sure there isn't a memory leak. These two member - // variables are a part of that magic. - ACE_Barrier *new_barrier_; - ACE_Mutex barrier_mutex_; - - // The thread which created the Barrier in the first place. Only - // this thread can change the threads_ value. - ACE_thread_t owner_; - - // An internal method that constructs the barrier_ as needed. - int make_barrier (int wait); -}; - -#endif /* BARRIER_H */ diff --git a/docs/tutorials/017/Makefile b/docs/tutorials/017/Makefile deleted file mode 100644 index 21e349dd929..00000000000 --- a/docs/tutorials/017/Makefile +++ /dev/null @@ -1,77 +0,0 @@ - -# $Id$ - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = barrier barrier2 - -FILES = Barrier_i - -BUILD = $(VBIN) - -LSRC = $(addsuffix .cpp,$(BIN)) -SRC = $(addsuffix .cpp,$(FILES)) - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -rename : # - for i in *.cxx ; do \ - n=`expr "$$i" : "\(.*\).cxx"` ;\ - mv $$i $$n.cpp ;\ - done - -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb -ts2 -bl -bli0 < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - -e 's/ / /g' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - -Depend : depend - perl ../007/fix.Makefile - -.depend : # - touch .depend - -HTML : # - [ -f hdr ] || $(MAKE) UNSHAR - perl ../combine *.pre - -SHAR : # - [ ! -f combine.shar ] || exit 1 - shar -T hdr bodies *.pre *.pst > combine.shar && $(RM) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - -include .depend diff --git a/docs/tutorials/017/barrier.cpp b/docs/tutorials/017/barrier.cpp deleted file mode 100644 index 93caedee8b3..00000000000 --- a/docs/tutorials/017/barrier.cpp +++ /dev/null @@ -1,166 +0,0 @@ - -// $Id$ - -#include "Barrier_i.h" -#include "ace/Task.h" - -/* We'll use a simple Task<> derivative to test our new Barrier - object. -*/ -class Test : public ACE_Task<ACE_NULL_SYNCH> -{ -public: - - // Construct the object with a desired thread count - Test(int _threads); - - // Open/begin the test. As usual, we have to match the - // ACE_Task signature. - int open(void * _unused = 0); - - // Change the threads_ value for the next invocation of open() - void threads(int _threads); - - // Get the current threads_ value. - int threads(void); - - // Perform the test - int svc(void); - -protected: - // How many threads the barrier will test. - int threads_; - - // The Barrier object we'll use in our tests below - Barrier barrier_; -}; - -/* Construct the object & initialize the threads value for open() to - use. -*/ -Test::Test(int _threads) - : threads_(_threads) -{ -} - -/* As usual, our open() will create one or more threads where we'll do - the interesting work. -*/ -int Test::open(void * _unused) -{ - ACE_UNUSED_ARG(_unused); - - // One thing about the barrier: You have to tell it how many - // threads it will be synching. The threads() mutator on my - // Barrier class lets you do that and hides the implementation - // details at the same time. - barrier_.threads(threads_); - - // Activate the tasks as usual... Like the other cases where - // we're joining (or waiting for) our threads, we can't use - // THR_DETACHED. - return this->activate(THR_NEW_LWP, threads_); -} - -void Test::threads(int _threads) -{ - threads_ = _threads; -} - -int Test::threads(void) -{ - return threads_; -} - -/* svc() will execute in each thread & do a few things with the - Barrier we have. - */ -int Test::svc(void) -{ - ACE_DEBUG ((LM_INFO, "(%P|%t|%T)\tTest::svc() Entry\n")); - - // Initialize the random number generator. We'll use this to - // create sleep() times in each thread. This will help us see - // if the barrier synch is working. - ACE_Time_Value now(ACE_OS::gettimeofday()); - ACE_RANDR_TYPE seed = now.usec(); - ACE_OS::srand(seed); - int delay; - - // After saying hello above, sleep for a random amount of time - // from 1 to 6 seconds. That will cause the next message - // "Entering wait()" to be staggered on the output as each - // thread's sleep() returns. - delay = ACE_OS::rand_r(seed)%5; - ACE_OS::sleep(abs(delay)+1); - - // When executing the app you should see these messages - // staggered in an at-most 6 second window. That is, you - // won't likely see them all at once. - ACE_DEBUG ((LM_INFO, "(%P|%t|%T)\tTest::svc() Entering wait()\n")); - - // All of the threads will now wait at this point. As each - // thread finishes the sleep() above it will join the waiters. - if( barrier_.wait() == -1 ) - { - ACE_DEBUG ((LM_INFO, "(%P|%t|%T)\tbarrier_.wait() failed!\n")); - return 0; - } - - // When all threads have reached wait() they will give us this - // message. If you execute this, you should see all of the - // "Everybody together" messages at about the same time. - ACE_DEBUG ((LM_INFO, "(%P|%t|%T)\tTest::svc() Everybody together?\n")); - - // Now we do the sleep() cycle again... - delay = ACE_OS::rand_r(seed)%5; - ACE_OS::sleep(abs(delay)+1); - - // As before, these will trickle in over a few seconds. - ACE_DEBUG ((LM_INFO, "(%P|%t|%T)\tTest::svc() Entering done()\n")); - - // This time we call done() instead of wait(). done() - // actually invokes wait() but before returning here, it will - // clean up a few resources. The goal is to prevent carrying - // around objects you don't need. - if( barrier_.done() == -1 ) - { - ACE_DEBUG ((LM_INFO, "(%P|%t|%T)\tbarrier_.done() failed!\n")); - return 0; - } - - // Since done() invokes wait() internally, we'll see this - // message from each thread simultaneously - ACE_DEBUG ((LM_INFO, "(%P|%t|%T)\tTest::svc() Is everyone still here?\n")); - - // A final sleep() - delay = ACE_OS::rand_r(seed)%5; - ACE_OS::sleep(abs(delay)+1); - - // These should be randomly spaced like all of the other - // post-sleep messages. - ACE_DEBUG ((LM_INFO, "(%P|%t|%T)\tTest::svc() Chaos and anarchy for all!\n")); - - return(0); -} - -/* Our test application... - */ -int main(int, char**) -{ - // Create the test object with 10 threads - Test test(10); - - // and open it to test the barrier. - test.open(); - // Now wait for them all to exit. - test.wait(); - - // Re-open the Test object with just 5 threads - test.threads(5); - test.open(); - // and wait for them to complete also. - test.wait(); - - return(0); -} diff --git a/docs/tutorials/017/barrier2.cpp b/docs/tutorials/017/barrier2.cpp deleted file mode 100644 index 2ed76decc34..00000000000 --- a/docs/tutorials/017/barrier2.cpp +++ /dev/null @@ -1,178 +0,0 @@ - -// $Id$ - -#include "Barrier_i.h" -#include "ace/Task.h" - -/* We'll use a simple Task<> derivative to test our new Barrier - object. -*/ -class Test : public ACE_Task<ACE_NULL_SYNCH> -{ -public: - - // Construct the object with a desired thread count - Test(int _threads); - - // Open/begin the test. As usual, we have to match the - // ACE_Task signature. - int open(void * _unused = 0); - - // Change the threads_ value for the next invocation of open() - void threads(int _threads); - - // Get the current threads_ value. - int threads(void); - - // Perform the test - int svc(void); - -protected: - // How many threads the barrier will test. - u_int threads_; - - // The Barrier object we'll use in our tests below - Barrier barrier_; - - // This lets us pick one (eg -- the first) thread as the - // "controller" for our little test... - ACE_Atomic_Op<ACE_Mutex,u_int> tcount_; -}; - -/* Construct the object & initialize the threads value for open() to - use. -*/ -Test::Test(int _threads) - : threads_(_threads), tcount_(0) -{ -} - -/* As usual, our open() will create one or more threads where we'll do - the interesting work. -*/ -int Test::open(void * _unused) -{ - ACE_UNUSED_ARG(_unused); - - // One thing about the barrier: You have to tell it how many - // threads it will be synching. The threads() mutator on my - // Barrier class lets you do that and hides the implementation - // details at the same time. - barrier_.threads(threads_); - - // Activate the tasks as usual... - return this->activate(THR_NEW_LWP, threads_, 1); -} - -void Test::threads(int _threads) -{ - threads_ = _threads; -} - -int Test::threads(void) -{ - return threads_; -} - -/* svc() will execute in each thread & do a few things with the - Barrier we have. - */ -int Test::svc(void) -{ - // Say hello to everyone first. - ACE_DEBUG(( LM_INFO, "(%P|%t|%T) Created\n" )); - - // Increment and save the "tcount" value. We'll use it in - // just a moment... - int me = ++tcount_; - - // Wait for all initial threads to get to this point before we - // go any further. This is standard barrier usage... - barrier_.wait(); - - // Setup our random number generator. - ACE_Time_Value now(ACE_OS::gettimeofday()); - ACE_RANDR_TYPE seed = now.usec(); - ACE_OS::srand(seed); - int delay; - - // We'll arbitrarily choose the first activated thread to be - // the controller. After it sleeps a few seconds, it will add - // five threads. - if( me == 1 ) - { - // Sleep from 1 to 10 seconds so that some of the other - // threads will be into their for() loop. - delay = ACE_OS::rand_r(seed)%10; - ACE_OS::sleep(abs(delay)+1); - - // Make ourselves the barrier owner so that we can change - // the number of threads. This should be done with care... - barrier_.owner( ACE_OS::thr_self() ); - - // Add 5 threads to the barrier and then activate() to - // make them real. Notice the third parameter to - // activate(). Without this parameter, the threads won't - // be created. - if( barrier_.threads(threads_+5) == 0 ) - { - this->activate(THR_NEW_LWP,5,1); - } - } - - // This for() loop represents an "infinite" work loop in an - // application. The theory is that the threads are dividing up - // some work but need to "recalibrate" if more threads are - // added. I'll just do five iterations so that the test - // doesn't run forever. - int i; - for( i = 0 ; i < 5 ; ++i ) - { - // The sleep() represents time doing work. - delay = ACE_OS::rand_r(seed)%7; - ACE_OS::sleep(abs(delay)+1); - - ACE_DEBUG(( LM_INFO, "(%P|%t|%T)\tThread %.2d of %.2d iteration %.2d\n", me, threads_, i )); - - // If the local threads_ variable doesn't match the number - // in the barrier, then the controller must have changed - // the thread count. We'll wait() for everyone and then - // recalibrate ourselves before continuing. - if( this->threads_ != barrier_.threads() ) - { - ACE_DEBUG(( LM_INFO, "(%P|%t|%T) Waiting for thread count to increase to %d from %d\n", - barrier_.threads(), this->threads_ )); - - // Wait for all our sibling threads... - barrier_.wait(); - - // Set our local variable so that we don't come here again. - this->threads_ = barrier_.threads(); - - // Recalibration can be anything you want. At this - // point, we know that all of the threads are synch'd - // and ready to go. - } - } - - // Re-synch all of the threads before they exit. This isn't - // really necessary but I like to do it. - barrier_.done(); - - return(0); -} - -/* Our test application... - */ -int main(int, char**) -{ - // Create the test object with 5 threads - Test test(5); - - // and open it to test the barrier. - test.open(); - // Now wait for them all to exit. - test.wait(); - - return(0); -} diff --git a/docs/tutorials/017/combine.shar b/docs/tutorials/017/combine.shar deleted file mode 100644 index c50680b0bd2..00000000000 --- a/docs/tutorials/017/combine.shar +++ /dev/null @@ -1,380 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/017'. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 422 -rw-rw-r-- hdr -# 65 -rw-rw-r-- bodies -# 1393 -rw-rw-r-- page01.pre -# 420 -rw-rw-r-- page02.pre -# 736 -rw-rw-r-- page03.pre -# 479 -rw-rw-r-- page04.pre -# 375 -rw-rw-r-- page05.pre -# 374 -rw-rw-r-- page06.pre -# 216 -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 _sh00331; 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 017</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> -X -<CENTER><B><FONT SIZE=+2>ACE Tutorial 017</FONT></B></CENTER> -X -<CENTER><B><FONT SIZE=+2>Using the ACE_Barrier synch object</FONT></B></CENTER> -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -9991b747f6aff75784cbeb88a79c06fc hdr -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`" - test 422 -eq "$shar_count" || - $echo 'hdr:' 'original size' '422,' '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 -barrier.cpp -Barrier_i.h -Barrier_i.cpp -PAGE=6 -barrier2.cpp -SHAR_EOF - $shar_touch -am 0224165499 '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' -95ff65d56968b60df92224ca27a34387 bodies -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`" - test 65 -eq "$shar_count" || - $echo 'bodies:' 'original size' '65,' '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' && -The ACE_Barrier implements the barrier synchronization pattern. -<P> -That's nice. What does it mean? -<P> -What it means is that you can use the ACE_Barrier to cause a set of -threads to all wait at a specific point in your application. In other -words: the threads reach a barrier that none can pass until all are -present. -<P> -This would typically be used in scientific applications where a set of -threads are all working in parallel on some great computation but they -have to synch and summarize before continuing to the next stage of calculation. With -proper use of ACE_Barrier, the threads can easily synch before -continuing. -<P> -In this tutorial I'll create a simple wrapper for the ACE_Barrier. In -reality, the ACE_Barrier is so easy that a wrapper isn't really -needed. I created the wrapper anyway though just because I wanted to. -<P> -Kirthika's abstract: -<ul> -The ACE_Barrier class is used for collective thread syncronisation. All -the threads block at the barrier and advance only after everyone is at -the -barrier. A thread blocks by calling the wait() method and stays until -all the other threads invoke wait() one-by-one at the barrier and then -all -move ahead. -Here, an abstract barrier class is created which incorporates the -ACE_Barrier -mechanism and is used in a test case of an ACE_Task with 10 and 5 -threads respectively -which illustrate the use of the barrier pattern. -</ul> -SHAR_EOF - $shar_touch -am 03191459100 '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' -6d94644272d64ed997ae76b98475d84e page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 1393 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '1393,' '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' && -First, lets take a look at the main() routine and how it will use the -Barrier wrapper class. A simple ACE_Task derivative is used so that -we can perform work in multiple threads. These threads will use the -barrier to synch in a couple of places. -<P> -Obviously this isn't a very realistic example but you should be able -to get the idea of how to use a Barrier without getting hung up in -application-level details. -<HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -9e2b4b85abf1bff15b94b6d20bc20f91 page02.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`" - test 420 -eq "$shar_count" || - $echo 'page02.pre:' 'original size' '420,' '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' && -The Barrier class used by the test task is a simple wrapper around -ACE_Barrier. One of the things about ACE_Barrier is that you have to -tell it how many threads it will be managing. Since that number -usually isn't known when you create your Task derivative, you have to -dynamically allocate the ACE_Barrier. My Barrier wrapper takes care -of that for you and even provides for a clean way to delete the -ACE_Barrier instance if you want to save a few bytes. -<P> -An interesting extension of this Barrier class would be to wrap it up -in a smart pointer. You could then have the Barrier destructor invoke -wait() as a now-protected method. The result would allow you to treat -the Barrier object almost as a "synchronization guard". -<HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -4d6cead716800d7625b2a903d0df1b34 page03.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`" - test 736 -eq "$shar_count" || - $echo 'page03.pre:' 'original size' '736,' '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' && -The Barrier implementation is quite simple. The threads() mutator -took a couple of tries to get right. In particular, be sure you know -when to apply the _wait paramter and when not to! In fact, the -requirement that only the "owning" thread can change the thread count -is rather limiting. A more appropriate solution would allow any -thread to safely change the count but that would require more complex -locking that is just a bit more than what I wanted to present here. -<HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -0c46b51370a57179cea56ef57fd0b1f4 page04.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`" - test 479 -eq "$shar_count" || - $echo 'page04.pre:' 'original size' '479,' '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' && -Well, that's it for the simple Barrier Tutorial. I encourage you to -try it out and see what you like and dislike. Any improvements or -enhancements will gladly be integrated into the Tutorial. -<P> -<UL> -<LI><A HREF="Makefile">Makefile</A> -<LI><A HREF="barrier.cpp">barrier.cpp</A> -<LI><A HREF="Barrier_i.h">Barrier_i.h</A> -<LI><A HREF="Barrier_i.cpp">Barrier_i.cpp</A> -</UL> -SHAR_EOF - $shar_touch -am 03191459100 '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' -616a2293adddb11896d28c7172436a65 page05.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`" - test 375 -eq "$shar_count" || - $echo 'page05.pre:' 'original size' '375,' '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' && -I could have included this in the first Test object of the tutorial -but that may have complicated things a bit. What we're doing here is -recognizing when the "owner" thread adds more threads to the pool. -When we notice that, we use the barrier to wait until everything -stabilizes and then we recalibrate and move on. -<P> -The source is <A HREF="barrier2.cpp">here</A>. -<HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -0e05cdb27f2d6bfda8fc2246ed981aab page06.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page06.pre'`" - test 374 -eq "$shar_count" || - $echo 'page06.pre:' 'original size' '374,' '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> -Before we call it a wrap though, there's one more thing I want to show -you. Remember the comments around Barrier::threads()? On the next -page, I'll show you how to synch up when the number of threads changes. -SHAR_EOF - $shar_touch -am 03191459100 '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' -4f18e2b82827f498992bd11b36c4ca09 page05.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pst'`" - test 216 -eq "$shar_count" || - $echo 'page05.pst:' 'original size' '216,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh00331 -exit 0 diff --git a/docs/tutorials/017/page01.html b/docs/tutorials/017/page01.html deleted file mode 100644 index a2ff33ca8ca..00000000000 --- a/docs/tutorials/017/page01.html +++ /dev/null @@ -1,52 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 017</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 017</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Using the ACE_Barrier synch object</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The ACE_Barrier implements the barrier synchronization pattern. -<P> -That's nice. What does it mean? -<P> -What it means is that you can use the ACE_Barrier to cause a set of -threads to all wait at a specific point in your application. In other -words: the threads reach a barrier that none can pass until all are -present. -<P> -This would typically be used in scientific applications where a set of -threads are all working in parallel on some great computation but they -have to synch and summarize before continuing to the next stage of calculation. With -proper use of ACE_Barrier, the threads can easily synch before -continuing. -<P> -In this tutorial I'll create a simple wrapper for the ACE_Barrier. In -reality, the ACE_Barrier is so easy that a wrapper isn't really -needed. I created the wrapper anyway though just because I wanted to. -<P> -Kirthika's abstract: -<ul> -The ACE_Barrier class is used for collective thread syncronisation. All -the threads block at the barrier and advance only after everyone is at -the -barrier. A thread blocks by calling the wait() method and stays until -all the other threads invoke wait() one-by-one at the barrier and then -all -move ahead. -Here, an abstract barrier class is created which incorporates the -ACE_Barrier -mechanism and is used in a test case of an ACE_Task with 10 and 5 -threads respectively -which illustrate the use of the barrier pattern. -</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/017/page02.html b/docs/tutorials/017/page02.html deleted file mode 100644 index 81aeb9d0b8b..00000000000 --- a/docs/tutorials/017/page02.html +++ /dev/null @@ -1,195 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 017</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 017</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Using the ACE_Barrier synch object</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -First, lets take a look at the main() routine and how it will use the -Barrier wrapper class. A simple ACE_Task derivative is used so that -we can perform work in multiple threads. These threads will use the -barrier to synch in a couple of places. -<P> -Obviously this isn't a very realistic example but you should be able -to get the idea of how to use a Barrier without getting hung up in -application-level details. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Barrier_i.h</font>" -<font color=blue>#include</font> "<A HREF="../../../ace/Task.h">ace/Task.h</A>" - -<font color=red>/* We'll use a simple Task<> derivative to test our new Barrier - object. -*/</font> -class Test : public ACE_Task<ACE_NULL_SYNCH> -{ -public: - - <font color=red>// Construct the object with a desired thread count</font> - Test(int _threads); - - <font color=red>// Open/begin the test. As usual, we have to match the</font> - <font color=red>// ACE_Task signature.</font> - int open(void * _unused = 0); - - <font color=red>// Change the threads_ value for the next invocation of open()</font> - void threads(int _threads); - - <font color=red>// Get the current threads_ value.</font> - int threads(void); - - <font color=red>// Perform the test</font> - int svc(void); - -protected: - <font color=red>// How many threads the barrier will test.</font> - int threads_; - - <font color=red>// The Barrier object we'll use in our tests below</font> - Barrier barrier_; -}; - -<font color=red>/* Construct the object & initialize the threads value for open() to - use. -*/</font> -<font color=#008888>Test::Test</font>(int _threads) - : threads_(_threads) -{ -} - -<font color=red>/* As usual, our open() will create one or more threads where we'll do - the interesting work. -*/</font> -int <font color=#008888>Test::open</font>(void * _unused) -{ - ACE_UNUSED_ARG(_unused); - - <font color=red>// One thing about the barrier: You have to tell it how many</font> - <font color=red>// threads it will be synching. The threads() mutator on my</font> - <font color=red>// Barrier class lets you do that and hides the implementation</font> - <font color=red>// details at the same time.</font> - barrier_.threads(threads_); - - <font color=red>// Activate the tasks as usual... Like the other cases where</font> - <font color=red>// we're joining (or waiting for) our threads, we can't use</font> - <font color=red>// THR_DETACHED.</font> - return this->activate(THR_NEW_LWP, threads_); -} - -void <font color=#008888>Test::threads</font>(int _threads) -{ - threads_ = _threads; -} - -int <font color=#008888>Test::threads</font>(void) -{ - return threads_; -} - -<font color=red>/* svc() will execute in each thread & do a few things with the - Barrier we have. - */</font> -int <font color=#008888>Test::svc</font>(void) -{ - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\<font color=#008888>tTest::svc</font>() Entry\n</font>")); - - <font color=red>// Initialize the random number generator. We'll use this to</font> - <font color=red>// create sleep() times in each thread. This will help us see</font> - <font color=red>// if the barrier synch is working.</font> - ACE_Time_Value now(<font color=#008888>ACE_OS::gettimeofday</font>()); - ACE_RANDR_TYPE seed = now.usec(); - <font color=#008888>ACE_OS::srand</font>(seed); - int delay; - - <font color=red>// After saying hello above, sleep for a random amount of time</font> - <font color=red>// from 1 to 6 seconds. That will cause the next message</font> - <font color=red>// "<font color=green>Entering wait()</font>" to be staggered on the output as each</font> - <font color=red>// thread's sleep() returns.</font> - delay = <font color=#008888>ACE_OS::rand_r</font>(seed)%5; - <font color=#008888>ACE_OS::sleep</font>(abs(delay)+1); - - <font color=red>// When executing the app you should see these messages</font> - <font color=red>// staggered in an at-most 6 second window. That is, you</font> - <font color=red>// won't likely see them all at once.</font> - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\<font color=#008888>tTest::svc</font>() Entering wait()\n</font>")); - - <font color=red>// All of the threads will now wait at this point. As each</font> - <font color=red>// thread finishes the sleep() above it will join the waiters.</font> - if( barrier_.wait() == -1 ) - { - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\tbarrier_.wait() failed!\n</font>")); - return 0; - } - - <font color=red>// When all threads have reached wait() they will give us this</font> - <font color=red>// message. If you execute this, you should see all of the</font> - <font color=red>// "<font color=green>Everybody together</font>" messages at about the same time.</font> - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\<font color=#008888>tTest::svc</font>() Everybody together?\n</font>")); - - <font color=red>// Now we do the sleep() cycle again...</font> - delay = <font color=#008888>ACE_OS::rand_r</font>(seed)%5; - <font color=#008888>ACE_OS::sleep</font>(abs(delay)+1); - - <font color=red>// As before, these will trickle in over a few seconds.</font> - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\<font color=#008888>tTest::svc</font>() Entering done()\n</font>")); - - <font color=red>// This time we call done() instead of wait(). done()</font> - <font color=red>// actually invokes wait() but before returning here, it will</font> - <font color=red>// clean up a few resources. The goal is to prevent carrying</font> - <font color=red>// around objects you don't need.</font> - if( barrier_.done() == -1 ) - { - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\tbarrier_.done() failed!\n</font>")); - return 0; - } - - <font color=red>// Since done() invokes wait() internally, we'll see this</font> - <font color=red>// message from each thread simultaneously</font> - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\<font color=#008888>tTest::svc</font>() Is everyone still here?\n</font>")); - - <font color=red>// A final sleep()</font> - delay = <font color=#008888>ACE_OS::rand_r</font>(seed)%5; - <font color=#008888>ACE_OS::sleep</font>(abs(delay)+1); - - <font color=red>// These should be randomly spaced like all of the other</font> - <font color=red>// post-sleep messages.</font> - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t|%T)\<font color=#008888>tTest::svc</font>() Chaos and anarchy for all!\n</font>")); - - return(0); -} - -<font color=red>/* Our test application... - */</font> -int main(int, char**) -{ - <font color=red>// Create the test object with 10 threads</font> - Test test(10); - - <font color=red>// and open it to test the barrier.</font> - test.open(); - <font color=red>// Now wait for them all to exit.</font> - test.wait(); - - <font color=red>// Re-open the Test object with just 5 threads</font> - test.threads(5); - test.open(); - <font color=red>// and wait for them to complete also.</font> - test.wait(); - - return(0); -} -</PRE> -<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/017/page03.html b/docs/tutorials/017/page03.html deleted file mode 100644 index fe2d6ec5eda..00000000000 --- a/docs/tutorials/017/page03.html +++ /dev/null @@ -1,100 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 017</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 017</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Using the ACE_Barrier synch object</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The Barrier class used by the test task is a simple wrapper around -ACE_Barrier. One of the things about ACE_Barrier is that you have to -tell it how many threads it will be managing. Since that number -usually isn't known when you create your Task derivative, you have to -dynamically allocate the ACE_Barrier. My Barrier wrapper takes care -of that for you and even provides for a clean way to delete the -ACE_Barrier instance if you want to save a few bytes. -<P> -An interesting extension of this Barrier class would be to wrap it up -in a smart pointer. You could then have the Barrier destructor invoke -wait() as a now-protected method. The result would allow you to treat -the Barrier object almost as a "synchronization guard". -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>BARRIER_H</font> -<font color=blue>#define</font> <font color=purple>BARRIER_H</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Synch.h">ace/Synch.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/Atomic_Op.h">ace/Atomic_Op.h</A>" - -<font color=red>/* Barrier is a simple wrapper for the ACE_Barrier synchronization - class. The ACE_Barrier is already pretty easy to use but I thought - I'd wrap it up to create just a bit more abstraction at the - application level. */</font> - -class Barrier -{ -public: - <font color=red>// Basic constructor and destructor. If you only need to synch the</font> - <font color=red>// start of your threads, you can safely delete your Barrier object</font> - <font color=red>// after invoking done(). Of course, you should be careful to only</font> - <font color=red>// delete the object once!</font> - Barrier (void); - ~Barrier (void); - - <font color=red>// Set and get the number of threads that the barrier will manage.</font> - <font color=red>// If you add or remove threads to your application at run-time you</font> - <font color=red>// can use the mutator to reflect that change. Note, however, that</font> - <font color=red>// you can only do that from the thread which first created the</font> - <font color=red>// Barrier. (This is a limitation of my Barrier object, not the</font> - <font color=red>// ACE_Barrier.) The optional _wait parameter will cause wait() to</font> - <font color=red>// be invoked if there is already a valid threads value.</font> - int threads (u_int threads, int wait = 0); - u_int threads (void); - - <font color=red>// Wait for all threads to reach the point where this is invoked.</font> - <font color=red>// Because of the snappy way in which ACE_Barrier is implemented,</font> - <font color=red>// you can invoke these back-to-back with no ill-effects.</font> - int wait (void); - - <font color=red>// done() will invoke wait(). Before returning though, it will</font> - <font color=red>// delete the barrier_ pointer below to reclaim some memory.</font> - int done (void); - - <font color=red>// Reset the owning thread of the barrier.</font> - void owner( ACE_thread_t _owner ); - -protected: - <font color=red>// The number of threads we're synching</font> - ACE_Atomic_Op<ACE_Mutex, u_int> threads_; - - <font color=red>// The ACE_Barrier that does all of the work</font> - ACE_Barrier *barrier_; - - <font color=red>// If we mutate the number of threads we have to do some black magic</font> - <font color=red>// to make sure there isn't a memory leak. These two member</font> - <font color=red>// variables are a part of that magic.</font> - ACE_Barrier *new_barrier_; - ACE_Mutex barrier_mutex_; - - <font color=red>// The thread which created the Barrier in the first place. Only</font> - <font color=red>// this thread can change the threads_ value.</font> - ACE_thread_t owner_; - - <font color=red>// An internal method that constructs the barrier_ as needed.</font> - int make_barrier (int wait); -}; - -<font color=blue>#endif</font> <font color=red>/* BARRIER_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page04.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/017/page04.html b/docs/tutorials/017/page04.html deleted file mode 100644 index 01aea4ed8c4..00000000000 --- a/docs/tutorials/017/page04.html +++ /dev/null @@ -1,188 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 017</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 017</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Using the ACE_Barrier synch object</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The Barrier implementation is quite simple. The threads() mutator -took a couple of tries to get right. In particular, be sure you know -when to apply the _wait paramter and when not to! In fact, the -requirement that only the "owning" thread can change the thread count -is rather limiting. A more appropriate solution would allow any -thread to safely change the count but that would require more complex -locking that is just a bit more than what I wanted to present here. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Barrier_i.h</font>" - -<font color=red>/* Initialize the threads_ count to zero and the barrier_ pointer to a - safe value. At the same time, we remember the thread that created - us so that we can allow it to change the thread count. -*/</font> -<font color=#008888>Barrier::Barrier</font>(void) - : threads_(0) - ,barrier_(0) - ,new_barrier_(0) -{ - owner_ = <font color=#008888>ACE_OS::thr_self</font>(); -} - -<font color=red>/* Ensure that barrier_ get's deleted so that we don't have a memory leak. - */</font> -<font color=#008888>Barrier::~Barrier</font>(void) -{ - delete barrier_; -} - -void <font color=#008888>Barrier::owner</font>( ACE_thread_t _owner ) -{ - owner_ = _owner; -} - -<font color=red>// Report on the number of threads.</font> -u_int <font color=#008888>Barrier::threads</font>(void) -{ - return threads_.value(); -} - -<font color=red>/* Allow the owning thread to (re)set the number of threads. - make_barrier() is called because it will wait() if we were already - configured. Typical usage would be for the worker threads to - wait() while the primary (eg -- owner) thread adjusts the thread - count. - - For instance: - In the worker threads: - if( myBarrier.threads() != current_thread_count ) - myBarrier.wait(); - - In the primary thread: - if( myBarrier.threads() != current_thread_count ) - myBarrier.threads( current_thread_count, 1 ); - */</font> -int <font color=#008888>Barrier::threads</font>( u_int _threads, int _wait ) -{ - if( ! <font color=#008888>ACE_OS::thr_equal</font>(ACE_OS::thr_self(), owner_) ) - { - return -1; - } - - threads_ = _threads; - - return make_barrier(_wait); -} - -<font color=red>/* Wait for all threads to synch if the thread count is valid. Note - that barrier_ will be 0 if the threads() mutator has not been - invoked. -*/</font> -int <font color=#008888>Barrier::wait</font>(void) -{ - if( ! barrier_ ) - { - return -1; - } - - <font color=red>// If the threads() mutator has been used, new_barrier_ will</font> - <font color=red>// point to a new ACE_Barrier instance. We'll use a</font> - <font color=red>// traditional double-check here to move that new object into</font> - <font color=red>// place and cleanup the old one.</font> - if( new_barrier_ ) - { - <font color=red>// mutex so that only one thread can do this part.</font> - ACE_Guard<ACE_Mutex> mutex(barrier_mutex_); - - <font color=red>// We only want the first thread to plug in the new barrier...</font> - if( new_barrier_ ) - { - <font color=red>// out with the old and in with the new.</font> - delete barrier_; - barrier_ = new_barrier_; - new_barrier_ = 0; - } - } - - return barrier_->wait(); -} - -<font color=red>/* Wait for all threads to synch. As each thread passes wait(), it - will decrement our thread counter. (That is why we had to make - threads_ an atomic op.) When the last thread decrements the - counter it will also delete the ACE_Barrier & free up a little - memory. -*/</font> -int <font color=#008888>Barrier::done</font>(void) -{ - if( this->wait() == -1 ) - { - return -1; - } - - --threads_; - - if( ! threads_.value() ) - { - delete barrier_; - barrier_ = 0; - } - - return 0; -} - -<font color=red>/* This will build the actual barrier. I broke this code out of the - threads() mutator in case it might be useful elsewhere. - If a barrier already exists, we will wait for all threads before - creating a new one. This trait is what allows the threads mutator - to be used as shown above. - */</font> -int <font color=#008888>Barrier::make_barrier</font>( int _wait ) -{ - <font color=red>// Ensure we have a valid thread count.</font> - if( ! threads_.value() ) - { - return -1; - } - - <font color=red>// If a barrier already exists, we'll arrange for it to be</font> - <font color=red>// replaced through the wait() method above.</font> - if( barrier_ ) - { - <font color=red>// Create the new barrier that wait() will install for us.</font> - ACE_NEW_RETURN(new_barrier_,ACE_Barrier(threads_.value()),-1); - - <font color=red>// Wait for our siblings to synch before continuing</font> - if( _wait ) - { - barrier_->wait(); - } - } - else - { - <font color=red>// Create the initial barrier.</font> - ACE_NEW_RETURN(barrier_,ACE_Barrier(threads_.value()),-1); - } - - return 0; -} - -<font color=blue>#if defined</font> (<font color=purple>ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION</font>) -template class ACE_Atomic_Op <ACE_Mutex, u_int>; -<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_Atomic_Op <ACE_Mutex, u_int> -<font color=blue>#endif</font> <font color=red>/* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */</font> -</PRE> -<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/017/page05.html b/docs/tutorials/017/page05.html deleted file mode 100644 index 1fc924890fc..00000000000 --- a/docs/tutorials/017/page05.html +++ /dev/null @@ -1,32 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 017</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 017</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Using the ACE_Barrier synch object</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -Well, that's it for the simple Barrier Tutorial. I encourage you to -try it out and see what you like and dislike. Any improvements or -enhancements will gladly be integrated into the Tutorial. -<P> -<UL> -<LI><A HREF="Makefile">Makefile</A> -<LI><A HREF="barrier.cpp">barrier.cpp</A> -<LI><A HREF="Barrier_i.h">Barrier_i.h</A> -<LI><A HREF="Barrier_i.cpp">Barrier_i.cpp</A> -</UL> -<HR> -Before we call it a wrap though, there's one more thing I want to show -you. Remember the comments around Barrier::threads()? On the next -page, I'll show you how to synch up when the number of threads changes. -<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/017/page06.html b/docs/tutorials/017/page06.html deleted file mode 100644 index 8e3704b1b32..00000000000 --- a/docs/tutorials/017/page06.html +++ /dev/null @@ -1,206 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 017</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 017</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Using the ACE_Barrier synch object</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -I could have included this in the first Test object of the tutorial -but that may have complicated things a bit. What we're doing here is -recognizing when the "owner" thread adds more threads to the pool. -When we notice that, we use the barrier to wait until everything -stabilizes and then we recalibrate and move on. -<P> -The source is <A HREF="barrier2.cpp">here</A>. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>Barrier_i.h</font>" -<font color=blue>#include</font> "<A HREF="../../../ace/Task.h">ace/Task.h</A>" - -<font color=red>/* We'll use a simple Task<> derivative to test our new Barrier - object. -*/</font> -class Test : public ACE_Task<ACE_NULL_SYNCH> -{ -public: - - <font color=red>// Construct the object with a desired thread count</font> - Test(int _threads); - - <font color=red>// Open/begin the test. As usual, we have to match the</font> - <font color=red>// ACE_Task signature.</font> - int open(void * _unused = 0); - - <font color=red>// Change the threads_ value for the next invocation of open()</font> - void threads(int _threads); - - <font color=red>// Get the current threads_ value.</font> - int threads(void); - - <font color=red>// Perform the test</font> - int svc(void); - -protected: - <font color=red>// How many threads the barrier will test.</font> - u_int threads_; - - <font color=red>// The Barrier object we'll use in our tests below</font> - Barrier barrier_; - - <font color=red>// This lets us pick one (eg -- the first) thread as the</font> - <font color=red>// "<font color=green>controller</font>" for our little test...</font> - ACE_Atomic_Op<ACE_Mutex,u_int> tcount_; -}; - -<font color=red>/* Construct the object & initialize the threads value for open() to - use. -*/</font> -<font color=#008888>Test::Test</font>(int _threads) - : threads_(_threads), tcount_(0) -{ -} - -<font color=red>/* As usual, our open() will create one or more threads where we'll do - the interesting work. -*/</font> -int <font color=#008888>Test::open</font>(void * _unused) -{ - ACE_UNUSED_ARG(_unused); - - <font color=red>// One thing about the barrier: You have to tell it how many</font> - <font color=red>// threads it will be synching. The threads() mutator on my</font> - <font color=red>// Barrier class lets you do that and hides the implementation</font> - <font color=red>// details at the same time.</font> - barrier_.threads(threads_); - - <font color=red>// Activate the tasks as usual...</font> - return this->activate(THR_NEW_LWP, threads_, 1); -} - -void <font color=#008888>Test::threads</font>(int _threads) -{ - threads_ = _threads; -} - -int <font color=#008888>Test::threads</font>(void) -{ - return threads_; -} - -<font color=red>/* svc() will execute in each thread & do a few things with the - Barrier we have. - */</font> -int <font color=#008888>Test::svc</font>(void) -{ - <font color=red>// Say hello to everyone first.</font> - ACE_DEBUG(( LM_INFO, "<font color=green>(%P|%t|%T) Created\n</font>" )); - - <font color=red>// Increment and save the "<font color=green>tcount</font>" value. We'll use it in</font> - <font color=red>// just a moment...</font> - int me = ++tcount_; - - <font color=red>// Wait for all initial threads to get to this point before we</font> - <font color=red>// go any further. This is standard barrier usage...</font> - barrier_.wait(); - - <font color=red>// Setup our random number generator.</font> - ACE_Time_Value now(<font color=#008888>ACE_OS::gettimeofday</font>()); - ACE_RANDR_TYPE seed = now.usec(); - <font color=#008888>ACE_OS::srand</font>(seed); - int delay; - - <font color=red>// We'll arbitrarily choose the first activated thread to be</font> - <font color=red>// the controller. After it sleeps a few seconds, it will add</font> - <font color=red>// five threads.</font> - if( me == 1 ) - { - <font color=red>// Sleep from 1 to 10 seconds so that some of the other</font> - <font color=red>// threads will be into their for() loop.</font> - delay = <font color=#008888>ACE_OS::rand_r</font>(seed)%10; - <font color=#008888>ACE_OS::sleep</font>(abs(delay)+1); - - <font color=red>// Make ourselves the barrier owner so that we can change</font> - <font color=red>// the number of threads. This should be done with care...</font> - barrier_.owner( <font color=#008888>ACE_OS::thr_self</font>() ); - - <font color=red>// Add 5 threads to the barrier and then activate() to</font> - <font color=red>// make them real. Notice the third parameter to</font> - <font color=red>// activate(). Without this parameter, the threads won't</font> - <font color=red>// be created.</font> - if( barrier_.threads(threads_+5) == 0 ) - { - this->activate(THR_NEW_LWP,5,1); - } - } - - <font color=red>// This for() loop represents an "<font color=green>infinite</font>" work loop in an</font> - <font color=red>// application. The theory is that the threads are dividing up</font> - <font color=red>// some work but need to "<font color=green>recalibrate</font>" if more threads are</font> - <font color=red>// added. I'll just do five iterations so that the test</font> - <font color=red>// doesn't run forever.</font> - int i; - for( i = 0 ; i < 5 ; ++i ) - { - <font color=red>// The sleep() represents time doing work.</font> - delay = <font color=#008888>ACE_OS::rand_r</font>(seed)%7; - <font color=#008888>ACE_OS::sleep</font>(abs(delay)+1); - - ACE_DEBUG(( LM_INFO, "<font color=green>(%P|%t|%T)\tThread %.2d of %.2d iteration %.2d\n</font>", me, threads_, i )); - - <font color=red>// If the local threads_ variable doesn't match the number</font> - <font color=red>// in the barrier, then the controller must have changed</font> - <font color=red>// the thread count. We'll wait() for everyone and then</font> - <font color=red>// recalibrate ourselves before continuing.</font> - if( this->threads_ != barrier_.threads() ) - { - ACE_DEBUG(( LM_INFO, "<font color=green>(%P|%t|%T) Waiting for thread count to increase to %d from %d\n</font>", - barrier_.threads(), this->threads_ )); - - <font color=red>// Wait for all our sibling threads...</font> - barrier_.wait(); - - <font color=red>// Set our local variable so that we don't come here again.</font> - this->threads_ = barrier_.threads(); - - <font color=red>// Recalibration can be anything you want. At this</font> - <font color=red>// point, we know that all of the threads are synch'd</font> - <font color=red>// and ready to go.</font> - } - } - - <font color=red>// Re-synch all of the threads before they exit. This isn't</font> - <font color=red>// really necessary but I like to do it.</font> - barrier_.done(); - - return(0); -} - -<font color=red>/* Our test application... - */</font> -int main(int, char**) -{ - <font color=red>// Create the test object with 5 threads</font> - Test test(5); - - <font color=red>// and open it to test the barrier.</font> - test.open(); - <font color=red>// Now wait for them all to exit.</font> - test.wait(); - - return(0); -} -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/018/018.dsp b/docs/tutorials/018/018.dsp deleted file mode 100644 index cf22bcbfaba..00000000000 --- a/docs/tutorials/018/018.dsp +++ /dev/null @@ -1,116 +0,0 @@ -# Microsoft Developer Studio Project File - Name="018" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=018 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "018.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "018.mak" CFG="018 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "018 - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "018 - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "018 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "018 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /out:"token.exe" /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "018 - Win32 Release"
-# Name "018 - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\Test_T.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\token.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\Mutex_i.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Test_T.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\Token_i.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/018/Makefile b/docs/tutorials/018/Makefile deleted file mode 100644 index 97bcfde576f..00000000000 --- a/docs/tutorials/018/Makefile +++ /dev/null @@ -1,77 +0,0 @@ - -# $Id$ - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = token - -FILES = - -BUILD = $(VBIN) - -SRC = $(addsuffix .cpp,$(BIN)) -SRC += $(addsuffix .cpp,$(FILES)) - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -rename : # - for i in *.cxx ; do \ - n=`expr "$$i" : "\(.*\).cxx"` ;\ - mv $$i $$n.cpp ;\ - done - -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb -ts2 -bl -bli0 < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - -e 's/ / /g' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - -Depend : depend - perl ../fix.Makefile - -.depend : # - touch .depend - -HTML : # - [ -f hdr ] || $(MAKE) UNSHAR - perl ../combine *.pre - -SHAR : # - [ ! -f combine.shar ] || exit 1 - shar -T hdr bodies *.pre > combine.shar && $(RM) hdr bodies *.pre - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - -include .depend diff --git a/docs/tutorials/018/Mutex_i.h b/docs/tutorials/018/Mutex_i.h deleted file mode 100644 index f360c446679..00000000000 --- a/docs/tutorials/018/Mutex_i.h +++ /dev/null @@ -1,17 +0,0 @@ -// $Id$ - -#ifndef MUTEX_I_H -#define MUTEX_I_H - -#include "Test_T.h" - -/* Create a very simple derivative of our Test template. All we have - to do is provide our mutex choice and a name. - */ -class Mutex : public Test_T<ACE_Mutex> -{ -public: - Mutex (void) : Test_T<ACE_Mutex> ("Mutex") {} -}; - -#endif /* MUTEX_I_H */ diff --git a/docs/tutorials/018/Test_T.cpp b/docs/tutorials/018/Test_T.cpp deleted file mode 100644 index 086ffcdfcdd..00000000000 --- a/docs/tutorials/018/Test_T.cpp +++ /dev/null @@ -1,196 +0,0 @@ -// $Id$ - -/* This is something new... Since we're included by the header, we - have to provide a sentry to protect against recursive inclusion. - */ -#ifndef TEST_T_C -#define TEST_T_C - -// Get our definition -#include "Test_T.h" - -// We'll hard-code the thread count. Mucking around with that isn't -// really the point of the exercise today... -#define TEST_THREAD_COUNT 5 - -/* Construction time... - Initialize the baseclass, the name and the barrier. Since the - client will probably invoke run() next, we go ahead an announce our - creation to make the output more readable. - */ -template <class MUTEX> -Test_T<MUTEX>::Test_T (const char *name) - : ACE_Task<ACE_MT_SYNCH>(), - name_ (name), - barrier_ (TEST_THREAD_COUNT) -{ - ACE_DEBUG ((LM_INFO, - "(%P|%t|%T)\tTest_T (%s) created\n", - name)); -} - -/* Activate the threads and create some test data... - */ -template <class MUTEX> int -Test_T<MUTEX>::run (void) -{ - // Try to activate the set of threads that will test the mutex - if (this->open () == -1) - return -1; - - // Create a set of messages. I chose twice the thread count so that - // we can see how they get distributed. - for (int i = 0; i < TEST_THREAD_COUNT*2; ++i) - { - // A message block big enough for a simple message. - ACE_Message_Block *message; - - ACE_NEW_RETURN (message, - ACE_Message_Block (64), - -1); - - // Put some text into the message block so that we can know - // what's going on when we get to svc() - sprintf (message->wr_ptr (), - "Message Number %d", - i); - message->wr_ptr (ACE_OS::strlen (message->rd_ptr ()) + 1); - - // Send the message to the thread pool - if (this->send (message) == -1) - break; - } - - // Send a hangup to the thread pool so that we can exit. - if (this->send () == -1) - return -1; - - // Wait for all of the threads to exit and then return to the client. - return this->wait (); -} - -/* Send a message to the thread pool - */ -template <class MUTEX> int -Test_T<MUTEX>::send (ACE_Message_Block *message) -{ - // If no message was provided, create a hangup message. - if (message == 0) - { - ACE_Message_Block::ACE_Message_Type mb_hangup = - ACE_Message_Block::MB_HANGUP ; - - ACE_NEW_RETURN (message, - ACE_Message_Block (0, mb_hangup), - -1); - } - - // Use the duplicate() method when sending the message. For this - // simple application, that may be overkill but it's a good habit. - // duplicate() will increment the reference count so that each user - // of the message can release() it when done. The last user to call - // release() will cause the data to be deleted. - if (this->putq (message->duplicate ()) == -1) - { - // Error? release() the message block and return failure. - message->release (); - return -1; - } - - // release() the data to prevent memory leaks. - message->release(); - - return 0; -} - -/* A farily typical open(). Just activate the set of threads and return. - */ -template <class MUTEX> int -Test_T<MUTEX>::open (void *arg) -{ - ACE_UNUSED_ARG(arg); - return this->activate (THR_NEW_LWP, - TEST_THREAD_COUNT); -} - -/* svc() is also fairly typical. The new part is the use of the guard - to simulate protection of shared resources. - */ -template <class MUTEX> int -Test_T<MUTEX>::svc (void) -{ - // Keep a simple thread identifier. We could always use the - // thread id but this is a nice, simple number. - int my_number = ++thread_num_; - - ACE_DEBUG ((LM_INFO, - "%d (%P|%t|%T)\tTest_T::svc() Entry\n", - my_number)); - - // Wait for all of threads to get started so that they all have a - // fair shot at the message queue. Comment this out and see how the - // behaviour changes. Does it surprise you? - barrier_.wait (); - - ACE_Message_Block *message; - int mcount = 0; - - // This would usually be an almost-infinite loop. Instead, I've - // governed it so that no single thread can get more than "thread - // count" number of messages. You'll see that with ACE_Mutex, this - // is just about the only way to keep the first thread from getting - // all the action. Ths is obviously just for sake of the test since - // you don't want your real-world app to exit after a fixed number - // of messages! - while (mcount < TEST_THREAD_COUNT) - { - // Get a message. Since the message queue is already - // thread-safe we don't have to guard it. In fact, moving the - // guard up above getq() will decrease your parallelization. - if (getq (message) == -1) - break; - - // Now we pretend that there are shared resources required to - // process the data. We grab the mutex through the guard and - // "do work". In a real application, you'll want to keep these - // critical sections as small as possible since they will reduce - // the usefulness of multi-threading. - guard_t guard (mutex_); - - // Increase our message count for the debug output and the - // governor. - ++mcount; - - // Check for a hangup request... Notice the use of release() - // again to prevent leaks - if (message->msg_type () == ACE_Message_Block::MB_HANGUP) - { - message->release (); - break; - } - - // Display the message so that we can see if things are working - // the way we want. - ACE_DEBUG ((LM_INFO, - "%d (%P|%t|%T)\tTest_T::svc() received message #%d (%s)\n", - my_number, - mcount, - message->rd_ptr ())); - - // Pretend that the work takes some time to complete. Remember, - // we're holding that lock during this time! - ACE_OS::sleep (1); - - // No leaks... - message->release (); - } - - // Send a hangup to the other threads in the pool. If we don't do - // this then wait() will never exit since all of the other threads - // are still blocked on getq(). - this->send (); - - return 0; -}; - -#endif /* TEST_T_C */ diff --git a/docs/tutorials/018/Test_T.h b/docs/tutorials/018/Test_T.h deleted file mode 100644 index 82c84c5be9a..00000000000 --- a/docs/tutorials/018/Test_T.h +++ /dev/null @@ -1,81 +0,0 @@ -// $Id$ - -#ifndef TEST_T_H -#define TEST_T_H - -#include "ace/Task.h" -#include "ace/Atomic_Op.h" - -/* We'll create a simple ACE_Task derivative for testing a couple of - different locking mechanisms. We've hidden the open() method to - force our client into using the run() method instead. - - The naming convention *_T is fairly typical for ACE. The _T suffix - on the object name (and it's source files) indicates that this is a - templated class. Generally, there is a non-templated class defined - also such as foobar.h that would be included instead of foobar_T.h. - */ - -template <class MUTEX> -class Test_T : public ACE_Task<ACE_MT_SYNCH> -{ -public: - // Allow our derivative to name the class so that we can tell the - // user what's going on as we test the lock. - Test_T (const char *name); - - // This will run the entire test. open() will be called to activate - // the task's threads. We then add a number of messages to the - // queue for svc() to process. - int run (void); - -protected: - - // Activate a few threads - int open (void *arg = 0); - - // Read some things from the message queue and exercise the lock. - int svc (void); - - // Send a message block to svc(). If _message is 0 then send a - // shutdown request (e.g., MB_HANGUP) - int send (ACE_Message_Block * message = 0); - - // The object's name. Typically provided by a derivative. - const char *name_; - - // We want to barrier the svc() methods to give all of the threads a - // fair chance - ACE_Barrier barrier_; - - // As each thread enters svc() it will increment this. While we - // have a thread id available to us, I wanted a simple value to - // display in debug messages. - ACE_Atomic_Op<ACE_Mutex,int> thread_num_; - - // Set our mutex type based on the template parameter. We then - // build a guard type based on that type. - typedef MUTEX mutex_t; - typedef ACE_Guard<mutex_t> guard_t; - - // Our mutex. We'll use this in svc() to protect imaginary shared - // resources. - mutex_t mutex_; -}; - -/* Although different compilers differ in their details, almost all of - them require that you provide the definition of the templated - object along with the declaration. With any luck, this will change - someday & we'll have smaller object files. Until then, the lines - below will take care of you. - */ - -#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) -#include "Test_T.cpp" -#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ - -#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) -#pragma implementation ("Test_T.cpp") -#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ - -#endif /* TEST_T_H */ diff --git a/docs/tutorials/018/Token_i.h b/docs/tutorials/018/Token_i.h deleted file mode 100644 index d07fe366a51..00000000000 --- a/docs/tutorials/018/Token_i.h +++ /dev/null @@ -1,20 +0,0 @@ -// $Id$ - -#ifndef TOKEN_I_H -#define TOKEN_I_H - -#include "Test_T.h" - -// Go get ace/Token.h so that we know what an ACE_Token is. -#include "ace/Token.h" - -/* Create a very simple derivative of our Test template. All we have - to do is provide our mutex choice and a name. - */ -class Token : public Test_T<ACE_Token> -{ -public: - Token (void): Test_T<ACE_Token> ("Token") {} -}; - -#endif /* TOKEN_I_H */ diff --git a/docs/tutorials/018/combine.shar b/docs/tutorials/018/combine.shar deleted file mode 100644 index a653d49c3ce..00000000000 --- a/docs/tutorials/018/combine.shar +++ /dev/null @@ -1,440 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/018'. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 416 -rw-rw-r-- hdr -# 64 -rw-rw-r-- bodies -# 2586 -rw-rw-r-- page01.pre -# 430 -rw-rw-r-- page02.pre -# 1279 -rw-rw-r-- page03.pre -# 688 -rw-rw-r-- page04.pre -# 259 -rw-rw-r-- page05.pre -# 1519 -rw-rw-r-- page06.pre -# 476 -rw-rw-r-- page07.pre -# -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 _sh00359; 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 018</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> -X -<CENTER><B><FONT SIZE=+2>ACE Tutorial 018</FONT></B></CENTER> -X -<CENTER><B><FONT SIZE=+2>The FIFO Nature of ACE_Token</FONT></B></CENTER> -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -66dbcd27e23cdcc9c230089e9c289bcb hdr -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`" - test 416 -eq "$shar_count" || - $echo 'hdr:' 'original size' '416,' '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 -token.cpp -Test_T.h -Test_T.cpp -Token_i.h Mutex_i.h -output -SHAR_EOF - $shar_touch -am 1114165298 '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' -22e70b25b6f23655b44d31fcf1a669f8 bodies -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`" - test 64 -eq "$shar_count" || - $echo 'bodies:' 'original size' '64,' '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 -Welcome to Tutorial 18! -<P> -We've seen various ACE methods for synchronization in this and other -tutorial sections. Something we haven't yet seen is the ACE_Token. -ACE_Token has a really cool thing: it behaves in a FIFO manner. -<P> -Why is that cool? -<P> -In the other tutorials, you may have found that one thread will end up -with all of the work. Even though other threads are available, the OS -scheduling and lock management just causes it to happen. With -ACE_Token, the threads are queued up on the token and served in a -traditional first-in-first-out manner. -<P> -Why is FIFO important? -<P> -Well, if your app is running in a bunch of threads and each is doing -the same thing on the local host then FIFO may not be important. -However, take the case where each thread is connected to a remote -system. Let's say you have a dozen threads in your app and each is -connected to a different remote system. Each of the threads will be -given a block of data which will be passed to the remote for some -intense calculation. If you use the FIFO then you'll spread the work -more-or-less evenly between the remote peers. If you use the -traditional mutex then one peer may get the lion's share of the work. -<P> -It gets down to a personal decision based on the application's needs. -Consider your application, examine its behavior & decide for yourself -if you want to spread the work evenly or if it's OK to let some -threads work harder than others. -<P> -Kirthika's abstract: -<UL> -A token is similar to a mutex-lock, with the difference being that -the token is given to the waiting threads in a FIFO order. In the case -of the mutex-lock, any thread (depending on the OS) could acquire -the lock when its released. It internally implements a recursive mutex, -i.e. the thread that owns the mutex can reqacquire it without deadlocking. -The token also has two FIFO lists for writers and readers with writer- -acquires having a higher priority than reader-acquires. -<P> -This tutorial throws light on the differences on having a shared resource governed by -a lock and a token, both derive from a Task which simply updates a counter with the -number-of-threads value. A barrier is used for ensuring that all threads get a equal -opportunity of grabbing the token. The message queue with the message containing the -thread count moves among the threads to be obtained and read. -<P> -On obtaining the results, we conclude that on using the Token, the job to be completed -can be distributed evenly among available threads. This cant be guaranteed -in case of simply using the lock for synchronisation. -</ul> -SHAR_EOF - $shar_touch -am 03191459100 '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' -c2c450403d3a23fb5c1d2f1dc23a1eb4 page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 2586 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '2586,' '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' && -Our main() just keeps getting simpler! I guess that's a good thing. -<P> -What we've done is create two Task-derived objects that test different -locking mechanisms. The Token object uses ACE_Token and the Mutex -object uses ACE_Mutex. When you execute the application you should -see quite a difference in thread utilization. At the end of the -tutorial I've included a link to the output of a typical run of the -application. -<HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -a36353959f7874c8e31884d2acd7eb43 page02.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`" - test 430 -eq "$shar_count" || - $echo 'page02.pre:' 'original size' '430,' '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 Test object is a simple derivative of ACE_Task. Although we've -certainly used templates in other tutorials, this is the first time -we've created one of our own. -<P> -In a lot of ways, you can think of templates as the sophisticated -cousin of the old C-style pre-processor macros. With templates, -however, you get better type-checking and much easier debugging. There -are certainly other benefits but these are my favorites. -<P> -Our template's MUTEX parameter is used to set the mutex type -<i>mutex_t</i>. That'll be used in svc() so that we can protect -shared resources needed during the processing of data received on our -message queue. -<P> -Note at the bottom how we have to include the <i>cpp</i> file -associated with us. Most compilers have to see the definition of -templated classes along with their declaration. You might be tempted, -therefore, to just put the definitions in the header file. Resist -that temptation because templates are one of the fastest growing areas -of compilers. Including the definition like we do here leads to long -compile times and overly-large binaries. With luck, the compilers -will get smarter in the future and we won't need definition -inclusion. If you've already got them broken out then you'll save -yourself a lot of time! -<HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -68432fc61bf23fe391f4ead60fe26b17 page03.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`" - test 1279 -eq "$shar_count" || - $echo 'page03.pre:' 'original size' '1279,' '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 Test implementation looks much like the other ACE_Task derivatives -we've used in the past. The most obvious change is the addition of -the run() method. run() will activate the threads and put a few -messages into the queue. We could have done that in main() but it -just makes more sense here. -<P> -Notice how svc() grabs the guard after getting a message from the -queue. Since we constructed our Task baseclass with ACE_MT_SYNCH, we -know that the queue is already thread-safe. Our purpose in grabbing -the additional lock is to show how ACE_Token and ACE_Mutex behave -differently. In a real app, you'd be doing this to protect shared -resources that the threads might clobber. -<HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -51ea4870a85f49c113951fedd695e35f page04.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`" - test 688 -eq "$shar_count" || - $echo 'page04.pre:' 'original size' '688,' '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' && -Here we create simple derivatives of our Test templated class. Each -is parameterized with our mutex of choice and "named". Using the Test -template we're able to reuse all of the code with practially no -retyping and certainly much less chance of error! -<HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -31b8531c267e036e6f463249cd04b53a page05.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`" - test 259 -eq "$shar_count" || - $echo 'page05.pre:' 'original size' '259,' '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' && -That's it for the code, now let's take a quick look at some output. -The first set of output is from the Token test, the second is Mutex -test. Notice how the threads are evenly utilized in the Token test. -Each thread gets to see exactly two messages. There's also an -interesting side-effect that the messages are processed in order. (You -can't rely on that, it just happend in this particular run.) -<P> -With the Mutex test, however, we see that the first thread gets no -less than 1/2 of all messages. In fact, if we didn't have the -governor in svc() it might have gotten them all! -<P> -Why does this happen? -<P> -Primarily because of time slicing. Even though each thread takes time -to do work (1 second in our test), it can still own the timeslice when -it gets back to the mutex acquire. Since the other threads are still -switched out, the current thread regets the lock and continues. On -the other hand, the ACE_Token is very careful about the order in which -the acquisition is allowed and more evenly distributes the work. -<P> -Play around with the sleep() call in svc(). You'll find that as you -decrease it, there is more chance that even the Token test will do -most of its work in one thread. You're still at the mercy of the OS -time slicing. In reality, though, it will take a moment or two for -work to be done. The end goal isn't necessarily to distribute the -work evenly over all threads but, rather, to distribute it evenly -among <i>available</i> threads. The distinction is subtle but important. -<HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -ac415a062a971ba79a088d929dda5f36 page06.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page06.pre'`" - test 1519 -eq "$shar_count" || - $echo 'page06.pre:' 'original size' '1519,' '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' && -And now we're at the end of another Tutorial. As always, feel free to -send in questions and comments. There are certainly more -implementation possibilites and I'll gladly integrate yours into these -Tutorials. -<P> -<UL> -<LI><A HREF="Makefile">Makefile</A> -<LI><A HREF="token.cpp">token.cpp</A> -<LI><A HREF="Test.h">Test.h</A> -<LI><A HREF="Test.cpp">Test.cpp</A> -<LI><A HREF="Token_i.h">Token_i.h</A> -<LI><A HREF="Mutex_i.h">Mutex_i.h</A> -<LI><A HREF="output">output</A> -</UL> -SHAR_EOF - $shar_touch -am 03191459100 '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' -b7e7273c9bbeec45bdf2df2e8af06323 page07.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page07.pre'`" - test 476 -eq "$shar_count" || - $echo 'page07.pre:' 'original size' '476,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh00359 -exit 0 diff --git a/docs/tutorials/018/output b/docs/tutorials/018/output deleted file mode 100644 index b292728e4d6..00000000000 --- a/docs/tutorials/018/output +++ /dev/null @@ -1,33 +0,0 @@ -(21386|1024|15:26:32.366520) Test (Token) created -1 (21386|1025|15:26:32.390340) Test::svc() Entry -2 (21386|2050|15:26:32.408330) Test::svc() Entry -3 (21386|3075|15:26:32.427363) Test::svc() Entry -4 (21386|4100|15:26:32.447285) Test::svc() Entry -5 (21386|5125|15:26:32.482479) Test::svc() Entry -1 (21386|1025|15:26:32.498583) Test::svc() received message #1 (Message Number 0) -2 (21386|2050|15:26:33.517770) Test::svc() received message #1 (Message Number 1) -3 (21386|3075|15:26:34.537701) Test::svc() received message #1 (Message Number 2) -4 (21386|4100|15:26:35.557675) Test::svc() received message #1 (Message Number 3) -5 (21386|5125|15:26:36.577650) Test::svc() received message #1 (Message Number 4) -1 (21386|1025|15:26:37.597689) Test::svc() received message #2 (Message Number 5) -2 (21386|2050|15:26:38.607689) Test::svc() received message #2 (Message Number 6) -3 (21386|3075|15:26:39.617675) Test::svc() received message #2 (Message Number 7) -4 (21386|4100|15:26:40.637653) Test::svc() received message #2 (Message Number 8) -5 (21386|5125|15:26:41.657637) Test::svc() received message #2 (Message Number 9) - -(21386|1024|15:26:42.679919) Test (Mutex) created -1 (21386|6150|15:26:42.700301) Test::svc() Entry -2 (21386|7175|15:26:42.737413) Test::svc() Entry -3 (21386|8200|15:26:42.754241) Test::svc() Entry -4 (21386|9225|15:26:42.772122) Test::svc() Entry -5 (21386|10250|15:26:42.788867) Test::svc() Entry -1 (21386|6150|15:26:42.806260) Test::svc() received message #1 (Message Number 0) -1 (21386|6150|15:26:43.807539) Test::svc() received message #2 (Message Number 5) -1 (21386|6150|15:26:44.817569) Test::svc() received message #3 (Message Number 6) -1 (21386|6150|15:26:45.827571) Test::svc() received message #4 (Message Number 7) -1 (21386|6150|15:26:46.837581) Test::svc() received message #5 (Message Number 8) -2 (21386|7175|15:26:47.847908) Test::svc() received message #1 (Message Number 1) -2 (21386|7175|15:26:48.857555) Test::svc() received message #2 (Message Number 9) -4 (21386|9225|15:26:49.867991) Test::svc() received message #1 (Message Number 3) -3 (21386|8200|15:26:50.887559) Test::svc() received message #1 (Message Number 2) -5 (21386|10250|15:26:51.898275) Test::svc() received message #1 (Message Number 4) diff --git a/docs/tutorials/018/page01.html b/docs/tutorials/018/page01.html deleted file mode 100644 index e6a3db6f086..00000000000 --- a/docs/tutorials/018/page01.html +++ /dev/null @@ -1,70 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 018</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 018</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>The FIFO Nature of ACE_Token</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> - -Welcome to Tutorial 18! -<P> -We've seen various ACE methods for synchronization in this and other -tutorial sections. Something we haven't yet seen is the ACE_Token. -ACE_Token has a really cool thing: it behaves in a FIFO manner. -<P> -Why is that cool? -<P> -In the other tutorials, you may have found that one thread will end up -with all of the work. Even though other threads are available, the OS -scheduling and lock management just causes it to happen. With -ACE_Token, the threads are queued up on the token and served in a -traditional first-in-first-out manner. -<P> -Why is FIFO important? -<P> -Well, if your app is running in a bunch of threads and each is doing -the same thing on the local host then FIFO may not be important. -However, take the case where each thread is connected to a remote -system. Let's say you have a dozen threads in your app and each is -connected to a different remote system. Each of the threads will be -given a block of data which will be passed to the remote for some -intense calculation. If you use the FIFO then you'll spread the work -more-or-less evenly between the remote peers. If you use the -traditional mutex then one peer may get the lion's share of the work. -<P> -It gets down to a personal decision based on the application's needs. -Consider your application, examine its behavior & decide for yourself -if you want to spread the work evenly or if it's OK to let some -threads work harder than others. -<P> -Kirthika's abstract: -<UL> -A token is similar to a mutex-lock, with the difference being that -the token is given to the waiting threads in a FIFO order. In the case -of the mutex-lock, any thread (depending on the OS) could acquire -the lock when its released. It internally implements a recursive mutex, -i.e. the thread that owns the mutex can reqacquire it without deadlocking. -The token also has two FIFO lists for writers and readers with writer- -acquires having a higher priority than reader-acquires. -<P> -This tutorial throws light on the differences on having a shared resource governed by -a lock and a token, both derive from a Task which simply updates a counter with the -number-of-threads value. A barrier is used for ensuring that all threads get a equal -opportunity of grabbing the token. The message queue with the message containing the -thread count moves among the threads to be obtained and read. -<P> -On obtaining the results, we conclude that on using the Token, the job to be completed -can be distributed evenly among available threads. This cant be guaranteed -in case of simply using the lock for synchronisation. -</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/018/page02.html b/docs/tutorials/018/page02.html deleted file mode 100644 index 84dc9c9c281..00000000000 --- a/docs/tutorials/018/page02.html +++ /dev/null @@ -1,61 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 018</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 018</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>The FIFO Nature of ACE_Token</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -Our main() just keeps getting simpler! I guess that's a good thing. -<P> -What we've done is create two Task-derived objects that test different -locking mechanisms. The Token object uses ACE_Token and the Mutex -object uses ACE_Mutex. When you execute the application you should -see quite a difference in thread utilization. At the end of the -tutorial I've included a link to the output of a typical run of the -application. -<HR> -<PRE> - -<font color=red>// $Id$</font> - -<font color=red>// Get our two Test derivatives...</font> -<font color=blue>#include</font> "<font color=green>Token_i.h</font>" -<font color=blue>#include</font> "<font color=green>Mutex_i.h</font>" - -int main(int,char**) -{ - <font color=red>// See what an ACE_Token does for us.</font> - Token token; - token.run(); - - <font color=red>// And now the ACE_Mutex.</font> - Mutex mutex; - mutex.run(); - - return(0); -} -<font color=blue>#if defined</font> (<font color=purple>ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION</font>) -template class Test_T <ACE_Mutex>; -template class Test_T <ACE_Token>; -template class ACE_Atomic_Op <ACE_Mutex, int>; -<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> Test_T <ACE_Mutex> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> Test_T <ACE_Token> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Atomic_Op <ACE_Mutex, int> -<font color=blue>#endif</font> <font color=red>/* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */</font> - - - - -</PRE> -<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/018/page03.html b/docs/tutorials/018/page03.html deleted file mode 100644 index d148b339cdc..00000000000 --- a/docs/tutorials/018/page03.html +++ /dev/null @@ -1,126 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 018</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 018</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>The FIFO Nature of ACE_Token</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -Our Test object is a simple derivative of ACE_Task. Although we've -certainly used templates in other tutorials, this is the first time -we've created one of our own. -<P> -In a lot of ways, you can think of templates as the sophisticated -cousin of the old C-style pre-processor macros. With templates, -however, you get better type-checking and much easier debugging. There -are certainly other benefits but these are my favorites. -<P> -Our template's MUTEX parameter is used to set the mutex type -<i>mutex_t</i>. That'll be used in svc() so that we can protect -shared resources needed during the processing of data received on our -message queue. -<P> -Note at the bottom how we have to include the <i>cpp</i> file -associated with us. Most compilers have to see the definition of -templated classes along with their declaration. You might be tempted, -therefore, to just put the definitions in the header file. Resist -that temptation because templates are one of the fastest growing areas -of compilers. Including the definition like we do here leads to long -compile times and overly-large binaries. With luck, the compilers -will get smarter in the future and we won't need definition -inclusion. If you've already got them broken out then you'll save -yourself a lot of time! -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>TEST_T_H</font> -<font color=blue>#define</font> <font color=purple>TEST_T_H</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Task.h">ace/Task.h</A>" -<font color=blue>#include</font> "<A HREF="../../../ace/Atomic_Op.h">ace/Atomic_Op.h</A>" - -<font color=red>/* We'll create a simple ACE_Task derivative for testing a couple of - different locking mechanisms. We've hidden the open() method to - force our client into using the run() method instead. - - The naming convention *_T is fairly typical for ACE. The _T suffix - on the object name (and it's source files) indicates that this is a - templated class. Generally, there is a non-templated class defined - also such as foobar.h that would be included instead of foobar_T.h. - */</font> - -template <class MUTEX> -class Test_T : public ACE_Task<ACE_MT_SYNCH> -{ -public: - <font color=red>// Allow our derivative to name the class so that we can tell the</font> - <font color=red>// user what's going on as we test the lock.</font> - Test_T (const char *name); - - <font color=red>// This will run the entire test. open() will be called to activate</font> - <font color=red>// the task's threads. We then add a number of messages to the</font> - <font color=red>// queue for svc() to process.</font> - int run (void); - -protected: - - <font color=red>// Activate a few threads</font> - int open (void *arg = 0); - - <font color=red>// Read some things from the message queue and exercise the lock.</font> - int svc (void); - - <font color=red>// Send a message block to svc(). If _message is 0 then send a</font> - <font color=red>// shutdown request (e.g., MB_HANGUP)</font> - int send (ACE_Message_Block * message = 0); - - <font color=red>// The object's name. Typically provided by a derivative.</font> - const char *name_; - - <font color=red>// We want to barrier the svc() methods to give all of the threads a</font> - <font color=red>// fair chance</font> - ACE_Barrier barrier_; - - <font color=red>// As each thread enters svc() it will increment this. While we</font> - <font color=red>// have a thread id available to us, I wanted a simple value to</font> - <font color=red>// display in debug messages.</font> - ACE_Atomic_Op<ACE_Mutex,int> thread_num_; - - <font color=red>// Set our mutex type based on the template parameter. We then</font> - <font color=red>// build a guard type based on that type.</font> - typedef MUTEX mutex_t; - typedef ACE_Guard<mutex_t> guard_t; - - <font color=red>// Our mutex. We'll use this in svc() to protect imaginary shared</font> - <font color=red>// resources.</font> - mutex_t mutex_; -}; - -<font color=red>/* Although different compilers differ in their details, almost all of - them require that you provide the definition of the templated - object along with the declaration. With any luck, this will change - someday & we'll have smaller object files. Until then, the lines - below will take care of you. - */</font> - -<font color=blue>#if defined</font> (<font color=purple>ACE_TEMPLATES_REQUIRE_SOURCE</font>) -<font color=blue>#include</font> "<font color=green>Test_T.cpp</font>" -<font color=blue>#endif</font> <font color=red>/* ACE_TEMPLATES_REQUIRE_SOURCE */</font> - -<font color=blue>#if defined</font> (<font color=purple>ACE_TEMPLATES_REQUIRE_PRAGMA</font>) -<font color=blue>#pragma</font> <font color=purple>implementation</font> ("<font color=green>Test_T.cpp</font>") -<font color=blue>#endif</font> <font color=red>/* ACE_TEMPLATES_REQUIRE_PRAGMA */</font> - -<font color=blue>#endif</font> <font color=red>/* TEST_T_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page04.html">Continue This Tutorial</A>]</CENTER> - diff --git a/docs/tutorials/018/page04.html b/docs/tutorials/018/page04.html deleted file mode 100644 index 809d05e06fd..00000000000 --- a/docs/tutorials/018/page04.html +++ /dev/null @@ -1,229 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 018</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 018</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>The FIFO Nature of ACE_Token</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -Our Test implementation looks much like the other ACE_Task derivatives -we've used in the past. The most obvious change is the addition of -the run() method. run() will activate the threads and put a few -messages into the queue. We could have done that in main() but it -just makes more sense here. -<P> -Notice how svc() grabs the guard after getting a message from the -queue. Since we constructed our Task baseclass with ACE_MT_SYNCH, we -know that the queue is already thread-safe. Our purpose in grabbing -the additional lock is to show how ACE_Token and ACE_Mutex behave -differently. In a real app, you'd be doing this to protect shared -resources that the threads might clobber. -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=red>/* This is something new... Since we're included by the header, we - have to provide a sentry to protect against recursive inclusion. - */</font> -<font color=blue>#ifndef</font> <font color=purple>TEST_T_C</font> -<font color=blue>#define</font> <font color=purple>TEST_T_C</font> - -<font color=red>// Get our definition</font> -<font color=blue>#include</font> "<font color=green>Test_T.h</font>" - -<font color=red>// We'll hard-code the thread count. Mucking around with that isn't</font> -<font color=red>// really the point of the exercise today...</font> -<font color=blue>#define</font> <font color=purple>TEST_THREAD_COUNT</font> 5 - -<font color=red>/* Construction time... - Initialize the baseclass, the name and the barrier. Since the - client will probably invoke run() next, we go ahead an announce our - creation to make the output more readable. - */</font> -template <class MUTEX> -Test_T<MUTEX>::Test_T (const char *name) - : ACE_Task<ACE_MT_SYNCH>(), - name_ (name), - barrier_ (TEST_THREAD_COUNT) -{ - ACE_DEBUG ((LM_INFO, - "<font color=green>(%P|%t|%T)\tTest_T (%s) created\n</font>", - name)); -} - -<font color=red>/* Activate the threads and create some test data... - */</font> -template <class MUTEX> int -Test_T<MUTEX>::run (void) -{ - <font color=red>// Try to activate the set of threads that will test the mutex</font> - if (this->open () == -1) - return -1; - - <font color=red>// Create a set of messages. I chose twice the thread count so that</font> - <font color=red>// we can see how they get distributed.</font> - for (int i = 0; i < TEST_THREAD_COUNT*2; ++i) - { - <font color=red>// A message block big enough for a simple message.</font> - ACE_Message_Block *message; - - ACE_NEW_RETURN (message, - ACE_Message_Block (64), - -1); - - <font color=red>// Put some text into the message block so that we can know</font> - <font color=red>// what's going on when we get to svc()</font> - sprintf (message->wr_ptr (), - "<font color=green>Message Number %d</font>", - i); - message->wr_ptr (<font color=#008888>ACE_OS::strlen</font> (message->rd_ptr ()) + 1); - - <font color=red>// Send the message to the thread pool</font> - if (this->send (message) == -1) - break; - } - - <font color=red>// Send a hangup to the thread pool so that we can exit.</font> - if (this->send () == -1) - return -1; - - <font color=red>// Wait for all of the threads to exit and then return to the client.</font> - return this->wait (); -} - -<font color=red>/* Send a message to the thread pool - */</font> -template <class MUTEX> int -Test_T<MUTEX>::send (ACE_Message_Block *message) -{ - <font color=red>// If no message was provided, create a hangup message.</font> - if (message == 0) - { - <font color=#008888>ACE_Message_Block::ACE_Message_Type</font> mb_hangup = - <font color=#008888>ACE_Message_Block::MB_HANGUP</font> ; - - ACE_NEW_RETURN (message, - ACE_Message_Block (0, mb_hangup), - -1); - } - - <font color=red>// Use the duplicate() method when sending the message. For this</font> - <font color=red>// simple application, that may be overkill but it's a good habit.</font> - <font color=red>// duplicate() will increment the reference count so that each user</font> - <font color=red>// of the message can release() it when done. The last user to call</font> - <font color=red>// release() will cause the data to be deleted.</font> - if (this->putq (message->duplicate ()) == -1) - { - <font color=red>// Error? release() the message block and return failure.</font> - message->release (); - return -1; - } - - <font color=red>// release() the data to prevent memory leaks.</font> - message->release(); - - return 0; -} - -<font color=red>/* A farily typical open(). Just activate the set of threads and return. - */</font> -template <class MUTEX> int -Test_T<MUTEX>::open (void *arg) -{ - ACE_UNUSED_ARG(arg); - return this->activate (THR_NEW_LWP, - TEST_THREAD_COUNT); -} - -<font color=red>/* svc() is also fairly typical. The new part is the use of the guard - to simulate protection of shared resources. - */</font> -template <class MUTEX> int -Test_T<MUTEX>::svc (void) -{ - <font color=red>// Keep a simple thread identifier. We could always use the</font> - <font color=red>// thread id but this is a nice, simple number.</font> - int my_number = ++thread_num_; - - ACE_DEBUG ((LM_INFO, - "<font color=green>%d (%P|%t|%T)\<font color=#008888>tTest_T::svc</font>() Entry\n</font>", - my_number)); - - <font color=red>// Wait for all of threads to get started so that they all have a</font> - <font color=red>// fair shot at the message queue. Comment this out and see how the</font> - <font color=red>// behaviour changes. Does it surprise you?</font> - barrier_.wait (); - - ACE_Message_Block *message; - int mcount = 0; - - <font color=red>// This would usually be an almost-infinite loop. Instead, I've</font> - <font color=red>// governed it so that no single thread can get more than "thread</font> - <font color=red>// count" number of messages. You'll see that with ACE_Mutex, this</font> - <font color=red>// is just about the only way to keep the first thread from getting</font> - <font color=red>// all the action. Ths is obviously just for sake of the test since</font> - <font color=red>// you don't want your real-world app to exit after a fixed number</font> - <font color=red>// of messages!</font> - while (mcount < TEST_THREAD_COUNT) - { - <font color=red>// Get a message. Since the message queue is already</font> - <font color=red>// thread-safe we don't have to guard it. In fact, moving the</font> - <font color=red>// guard up above getq() will decrease your parallelization.</font> - if (getq (message) == -1) - break; - - <font color=red>// Now we pretend that there are shared resources required to</font> - <font color=red>// process the data. We grab the mutex through the guard and</font> - <font color=red>// "<font color=green>do work</font>". In a real application, you'll want to keep these</font> - <font color=red>// critical sections as small as possible since they will reduce</font> - <font color=red>// the usefulness of multi-threading.</font> - guard_t guard (mutex_); - - <font color=red>// Increase our message count for the debug output and the</font> - <font color=red>// governor.</font> - ++mcount; - - <font color=red>// Check for a hangup request... Notice the use of release()</font> - <font color=red>// again to prevent leaks</font> - if (message->msg_type () == <font color=#008888>ACE_Message_Block::MB_HANGUP</font>) - { - message->release (); - break; - } - - <font color=red>// Display the message so that we can see if things are working</font> - <font color=red>// the way we want.</font> - ACE_DEBUG ((LM_INFO, - "<font color=green>%d (%P|%t|%T)\<font color=#008888>tTest_T::svc</font>() received message #%d (%s)\n</font>", - my_number, - mcount, - message->rd_ptr ())); - - <font color=red>// Pretend that the work takes some time to complete. Remember,</font> - <font color=red>// we're holding that lock during this time!</font> - <font color=#008888>ACE_OS::sleep</font> (1); - - <font color=red>// No leaks...</font> - message->release (); - } - - <font color=red>// Send a hangup to the other threads in the pool. If we don't do</font> - <font color=red>// this then wait() will never exit since all of the other threads</font> - <font color=red>// are still blocked on getq().</font> - this->send (); - - return 0; -}; - -<font color=blue>#endif</font> <font color=red>/* TEST_T_C */</font> -</PRE> -<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/018/page05.html b/docs/tutorials/018/page05.html deleted file mode 100644 index 5c669aa3155..00000000000 --- a/docs/tutorials/018/page05.html +++ /dev/null @@ -1,66 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 018</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 018</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>The FIFO Nature of ACE_Token</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -Here we create simple derivatives of our Test templated class. Each -is parameterized with our mutex of choice and "named". Using the Test -template we're able to reuse all of the code with practially no -retyping and certainly much less chance of error! -<HR> -<HR width=50%><P><center>Token_i.h</center><HR width=50%> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>TOKEN_I_H</font> -<font color=blue>#define</font> <font color=purple>TOKEN_I_H</font> - -<font color=blue>#include</font> "<font color=green>Test_T.h</font>" - -<font color=red>// Go get ace/Token.h so that we know what an ACE_Token is.</font> -<font color=blue>#include</font> "<A HREF="../../../ace/Token.h">ace/Token.h</A>" - -<font color=red>/* Create a very simple derivative of our Test template. All we have - to do is provide our mutex choice and a name. - */</font> -class Token : public Test_T<ACE_Token> -{ -public: - Token (void): Test_T<ACE_Token> ("<font color=green>Token</font>") {} -}; - -<font color=blue>#endif</font> <font color=red>/* TOKEN_I_H */</font> -</PRE> -<HR width=50%><P><center>Mutex_i.h</center><HR width=50%> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>MUTEX_I_H</font> -<font color=blue>#define</font> <font color=purple>MUTEX_I_H</font> - -<font color=blue>#include</font> "<font color=green>Test_T.h</font>" - -<font color=red>/* Create a very simple derivative of our Test template. All we have - to do is provide our mutex choice and a name. - */</font> -class Mutex : public Test_T<ACE_Mutex> -{ -public: - Mutex (void) : Test_T<ACE_Mutex> ("<font color=green>Mutex</font>") {} -}; - -<font color=blue>#endif</font> <font color=red>/* MUTEX_I_H */</font> -</PRE> -<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/018/page06.html b/docs/tutorials/018/page06.html deleted file mode 100644 index 8d348b2289e..00000000000 --- a/docs/tutorials/018/page06.html +++ /dev/null @@ -1,81 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 018</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 018</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>The FIFO Nature of ACE_Token</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -That's it for the code, now let's take a quick look at some output. -The first set of output is from the Token test, the second is Mutex -test. Notice how the threads are evenly utilized in the Token test. -Each thread gets to see exactly two messages. There's also an -interesting side-effect that the messages are processed in order. (You -can't rely on that, it just happend in this particular run.) -<P> -With the Mutex test, however, we see that the first thread gets no -less than 1/2 of all messages. In fact, if we didn't have the -governor in svc() it might have gotten them all! -<P> -Why does this happen? -<P> -Primarily because of time slicing. Even though each thread takes time -to do work (1 second in our test), it can still own the timeslice when -it gets back to the mutex acquire. Since the other threads are still -switched out, the current thread regets the lock and continues. On -the other hand, the ACE_Token is very careful about the order in which -the acquisition is allowed and more evenly distributes the work. -<P> -Play around with the sleep() call in svc(). You'll find that as you -decrease it, there is more chance that even the Token test will do -most of its work in one thread. You're still at the mercy of the OS -time slicing. In reality, though, it will take a moment or two for -work to be done. The end goal isn't necessarily to distribute the -work evenly over all threads but, rather, to distribute it evenly -among <i>available</i> threads. The distinction is subtle but important. -<HR> -<PRE> -(21386|1024|15:26:32.366520) Test (Token) created -1 (21386|1025|15:26:32.390340) <font color=#008888>Test::svc</font>() Entry -2 (21386|2050|15:26:32.408330) <font color=#008888>Test::svc</font>() Entry -3 (21386|3075|15:26:32.427363) <font color=#008888>Test::svc</font>() Entry -4 (21386|4100|15:26:32.447285) <font color=#008888>Test::svc</font>() Entry -5 (21386|5125|15:26:32.482479) <font color=#008888>Test::svc</font>() Entry -1 (21386|1025|15:26:32.498583) <font color=#008888>Test::svc</font>() received message #1 (Message Number 0) -2 (21386|2050|15:26:33.517770) <font color=#008888>Test::svc</font>() received message #1 (Message Number 1) -3 (21386|3075|15:26:34.537701) <font color=#008888>Test::svc</font>() received message #1 (Message Number 2) -4 (21386|4100|15:26:35.557675) <font color=#008888>Test::svc</font>() received message #1 (Message Number 3) -5 (21386|5125|15:26:36.577650) <font color=#008888>Test::svc</font>() received message #1 (Message Number 4) -1 (21386|1025|15:26:37.597689) <font color=#008888>Test::svc</font>() received message #2 (Message Number 5) -2 (21386|2050|15:26:38.607689) <font color=#008888>Test::svc</font>() received message #2 (Message Number 6) -3 (21386|3075|15:26:39.617675) <font color=#008888>Test::svc</font>() received message #2 (Message Number 7) -4 (21386|4100|15:26:40.637653) <font color=#008888>Test::svc</font>() received message #2 (Message Number 8) -5 (21386|5125|15:26:41.657637) <font color=#008888>Test::svc</font>() received message #2 (Message Number 9) - -(21386|1024|15:26:42.679919) Test (Mutex) created -1 (21386|6150|15:26:42.700301) <font color=#008888>Test::svc</font>() Entry -2 (21386|7175|15:26:42.737413) <font color=#008888>Test::svc</font>() Entry -3 (21386|8200|15:26:42.754241) <font color=#008888>Test::svc</font>() Entry -4 (21386|9225|15:26:42.772122) <font color=#008888>Test::svc</font>() Entry -5 (21386|10250|15:26:42.788867) <font color=#008888>Test::svc</font>() Entry -1 (21386|6150|15:26:42.806260) <font color=#008888>Test::svc</font>() received message #1 (Message Number 0) -1 (21386|6150|15:26:43.807539) <font color=#008888>Test::svc</font>() received message #2 (Message Number 5) -1 (21386|6150|15:26:44.817569) <font color=#008888>Test::svc</font>() received message #3 (Message Number 6) -1 (21386|6150|15:26:45.827571) <font color=#008888>Test::svc</font>() received message #4 (Message Number 7) -1 (21386|6150|15:26:46.837581) <font color=#008888>Test::svc</font>() received message #5 (Message Number 8) -2 (21386|7175|15:26:47.847908) <font color=#008888>Test::svc</font>() received message #1 (Message Number 1) -2 (21386|7175|15:26:48.857555) <font color=#008888>Test::svc</font>() received message #2 (Message Number 9) -4 (21386|9225|15:26:49.867991) <font color=#008888>Test::svc</font>() received message #1 (Message Number 3) -3 (21386|8200|15:26:50.887559) <font color=#008888>Test::svc</font>() received message #1 (Message Number 2) -5 (21386|10250|15:26:51.898275) <font color=#008888>Test::svc</font>() received message #1 (Message Number 4) -</PRE> -<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/018/page07.html b/docs/tutorials/018/page07.html deleted file mode 100644 index 28586aea1cf..00000000000 --- a/docs/tutorials/018/page07.html +++ /dev/null @@ -1,32 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 018</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 018</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>The FIFO Nature of ACE_Token</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -And now we're at the end of another Tutorial. As always, feel free to -send in questions and comments. There are certainly more -implementation possibilites and I'll gladly integrate yours into these -Tutorials. -<P> -<UL> -<LI><A HREF="Makefile">Makefile</A> -<LI><A HREF="token.cpp">token.cpp</A> -<LI><A HREF="Test.h">Test.h</A> -<LI><A HREF="Test.cpp">Test.cpp</A> -<LI><A HREF="Token_i.h">Token_i.h</A> -<LI><A HREF="Mutex_i.h">Mutex_i.h</A> -<LI><A HREF="output">output</A> -</UL> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/018/token.cpp b/docs/tutorials/018/token.cpp deleted file mode 100644 index 040a6ead6c6..00000000000 --- a/docs/tutorials/018/token.cpp +++ /dev/null @@ -1,32 +0,0 @@ - -// $Id$ - -// Get our two Test derivatives... -#include "Token_i.h" -#include "Mutex_i.h" - -int main(int,char**) -{ - // See what an ACE_Token does for us. - Token token; - token.run(); - - // And now the ACE_Mutex. - Mutex mutex; - mutex.run(); - - return(0); -} -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class Test_T <ACE_Mutex>; -template class Test_T <ACE_Token>; -template class ACE_Atomic_Op <ACE_Mutex, int>; -#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate Test_T <ACE_Mutex> -#pragma instantiate Test_T <ACE_Token> -#pragma instantiate ACE_Atomic_Op <ACE_Mutex, int> -#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ - - - - diff --git a/docs/tutorials/019/019-client.dsp b/docs/tutorials/019/019-client.dsp deleted file mode 100644 index aae33177cd5..00000000000 --- a/docs/tutorials/019/019-client.dsp +++ /dev/null @@ -1,105 +0,0 @@ -# Microsoft Developer Studio Project File - Name="019 client" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=019 client - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "019 client.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "019 client.mak" CFG="019 client - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "019 client - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "019 client - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "019 client - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "019 client - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "019 client - Win32 Release"
-# Name "019 client - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\client.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\shmem.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\shmem.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/019/019-client2.dsp b/docs/tutorials/019/019-client2.dsp deleted file mode 100644 index d1f6e685c92..00000000000 --- a/docs/tutorials/019/019-client2.dsp +++ /dev/null @@ -1,105 +0,0 @@ -# Microsoft Developer Studio Project File - Name="019 client2" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=019 client2 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "019 client2.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "019 client2.mak" CFG="019 client2 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "019 client2 - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "019 client2 - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "019 client2 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "019 client2 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "019 client2 - Win32 Release"
-# Name "019 client2 - Win32 Debug"
-# Begin Group "Header Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\shmem.h
-# End Source File
-# End Group
-# Begin Group "Source Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\client2.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\shmem.cpp
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/019/019-server.dsp b/docs/tutorials/019/019-server.dsp deleted file mode 100644 index 789431e0ba8..00000000000 --- a/docs/tutorials/019/019-server.dsp +++ /dev/null @@ -1,105 +0,0 @@ -# Microsoft Developer Studio Project File - Name="019 server" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=019 server - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "019 server.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "019 server.mak" CFG="019 server - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "019 server - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "019 server - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "019 server - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "019 server - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "019 server - Win32 Release"
-# Name "019 server - Win32 Debug"
-# Begin Group "Header Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\shmem.h
-# End Source File
-# End Group
-# Begin Group "Source Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\server.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\shmem.cpp
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/019/019-server2.dsp b/docs/tutorials/019/019-server2.dsp deleted file mode 100644 index f3b72b718a6..00000000000 --- a/docs/tutorials/019/019-server2.dsp +++ /dev/null @@ -1,105 +0,0 @@ -# Microsoft Developer Studio Project File - Name="019 server2" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=019 server2 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "019 server2.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "019 server2.mak" CFG="019 server2 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "019 server2 - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "019 server2 - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "019 server2 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "019 server2 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "019 server2 - Win32 Release"
-# Name "019 server2 - Win32 Debug"
-# Begin Group "Header Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\shmem.h
-# End Source File
-# End Group
-# Begin Group "Source Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\server2.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\shmem.cpp
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/019/Makefile b/docs/tutorials/019/Makefile deleted file mode 100644 index 897c0f8d9ac..00000000000 --- a/docs/tutorials/019/Makefile +++ /dev/null @@ -1,79 +0,0 @@ - -# $Id$ - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = client server client2 server2 - -FILES = shmem - -BUILD = $(VBIN) - -BSRC = $(addsuffix .cpp,$(BIN)) - -SRC += $(addsuffix .cpp,$(FILES)) - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -rename : # - for i in *.cxx ; do \ - n=`expr "$$i" : "\(.*\).cxx"` ;\ - mv $$i $$n.cpp ;\ - done - -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb -ts2 -bl -bli0 < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - -e 's/ / /g' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - -Depend : # - $(MAKE) SRC="$(SRC) $(BSRC)" depend - perl ../fix.Makefile - -.depend : # - touch .depend - -HTML : # - [ -f hdr ] || $(MAKE) UNSHAR - perl ../combine *.pre - -SHAR : # - [ ! -f combine.shar ] || exit 1 - shar -T hdr bodies *.pre > combine.shar && $(RM) hdr bodies *.pre - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - -include .depend diff --git a/docs/tutorials/019/client.cpp b/docs/tutorials/019/client.cpp deleted file mode 100644 index 55b99b52667..00000000000 --- a/docs/tutorials/019/client.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// $Id$ - -// Again, the common stuff -#include "shmem.h" - -#include "ace/Log_Msg.h" - -#if defined(ACE_LACKS_SYSV_SHMEM) -int -main (int, char *[]) -{ - ACE_ERROR_RETURN ((LM_ERROR, - "System V Shared Memory not available on this platform\n"), - 100); -} -#else // ACE_LACKS_SYSV_SHMEM -int -main (int, char *[]) -{ - /* - Attach ourselves to the shared memory segment. - */ - ACE_Shared_Memory_SV shm_client (SHM_KEY, SHMSZ); - - /* - Get our reference to the segment... - */ - char *shm = (char *) shm_client.malloc (); - - /* - If the segment identified by SHM_KEY didn't exist then we'll - get back a 0 from malloc(). You should do this check even - if you include the CREATE flag 'cause you never know when it - might fail. - */ - if (shm == 0) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) Could not get the segment!\n"), - 100); - - /* - Does this match what your server said? - */ - ACE_DEBUG ((LM_INFO, - "(%P|%t) Shared Memory is at 0x%x\n", - shm )); - - /* - Show the shared data to the user and convert it all to - uppper-case along the way. - */ - for (char *s = shm; *s != '\0'; s++) - { - putchar (*s); - *s = toupper(*s); - } - - putchar ('\n'); - - /* - Flag the server that we're done. - */ - *shm = '*'; - - /* - Here, we use close() instead of remove(). Remember, that - will just remove our attachment to the segment. Look - closely at the 'nattch' column of the ipcs output & you'll - see that this decrements it by one. - */ - shm_client.close(); - - return 0; -} - -#endif /* ACE_LACKS_SYSV_SHMEM */ diff --git a/docs/tutorials/019/client2.cpp b/docs/tutorials/019/client2.cpp deleted file mode 100644 index 6ef80ad2454..00000000000 --- a/docs/tutorials/019/client2.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// $Id$ - -#include "shmem.h" - -#include "ace/Log_Msg.h" - -#if defined(ACE_LACKS_SYSV_SHMEM) -int -main (int, char *[]) -{ - ACE_ERROR_RETURN ((LM_ERROR, - "System V Shared Memory not available on this platform\n"), - 100); -} -#else // ACE_LACKS_SYSV_SHMEM -int -main (int, char *[]) -{ - ACE_Shared_Memory_SV shm_client (SHM_KEY, - sizeof (SharedData)); - - char *shm = (char *) shm_client.malloc (); - - ACE_DEBUG ((LM_INFO, - "(%P|%t) Shared Memory is at 0x%x\n", - shm)); - - /* - More placement new. The constructor parameter prevents - clobbering what the server may have written with it's show() - method. - */ - SharedData *sd = new (shm) SharedData (0); - - // Show it - sd->show (); - - // Change it - sd->set (); - - // Advertise it - sd->available (1); - - shm_client.close (); - - return 0; -} - -#endif /* ACE_LACKS_SYSV_SHMEM */ diff --git a/docs/tutorials/019/combine.shar b/docs/tutorials/019/combine.shar deleted file mode 100644 index 260a7f8a7b8..00000000000 --- a/docs/tutorials/019/combine.shar +++ /dev/null @@ -1,358 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/019'. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 409 -rw-rw-r-- hdr -# 71 -rw-rw-r-- bodies -# 2006 -rw-rw-r-- page01.pre -# 562 -rw-rw-r-- page02.pre -# 217 -rw-rw-r-- page03.pre -# 674 -rw-rw-r-- page04.pre -# 178 -rw-rw-r-- page05.pre -# 401 -rw-rw-r-- page06.pre -# -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 _sh00389; 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 019</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> -X -<CENTER><B><FONT SIZE=+2>ACE Tutorial 019</FONT></B></CENTER> -X -<CENTER><B><FONT SIZE=+2>Sharing your Memories</FONT></B></CENTER> -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -3b7d0df272c309b4b8d67d872956bae3 hdr -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`" - test 409 -eq "$shar_count" || - $echo 'hdr:' 'original size' '409,' '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.cpp -server2.cpp client2.cpp -shmem.h shmem.cpp -SHAR_EOF - $shar_touch -am 1228162198 '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' -7eebfcd7b463404b494b4c97107f9d14 bodies -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`" - test 71 -eq "$shar_count" || - $echo 'bodies:' 'original size' '71,' '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 Did you ever wish you could read someone's mind? Or that they could -X read yours? -X <p> -X Well, we won't be doing that here but we'll try to get close by -X letting your code do something similar: Shared Memory. -X <p> -X What we're going to do is ask the operating system to set -X aside a part of RAM that we can share with another process. By -X doing this, we can allow our applications to swap data very -X efficiently. -X <p> -X Along the way, we'll have to come up with some sort of -X coordination betweent the processes. That is the most -X difficult part of a shared memory system. In the tutorial we're -X just going to take a simplistic approach (eg -- busy loop) but -X real-world applications will need to take a serious look at -X process-level synch mechanisms such as ACE_*_Semaphore. -X <P> -X Caveat: I've barely begun to use shared memory -X myself. This tutorial and the next are very simple-minded and -X primitive. Anyone who wants to provide more realistic -X replacements is encouraged to drop me a note -X (<A HREF="mailto:jcej@lads.com">jcej@lads.com</A>). -<P> -A tutorial wouldn't be complete without Kirthika's abstract: -<UL> -This tutorial shows how to use memory as a shared resource between the -client and server processes. ACE_Shared_Memory_SV has been used for -creating -the shared memory segment. Two different approaches have been used. One -uses the malloc () method to allocate memory while the other uses the -placement new expression (C++) of allocating a memory chunk in advance -and using it on demand. -<P> -The server has a string of alphabets from a-z which are converted to -uppercase -by the client proving that the same memory locations are being shared -between -the two processes. The syncronisation between the server and client is -done -using the ACE_OS::sleep () instead of a semaphore/mutexes with the aim -of keeping our first dive into shared memory usage simple and easy to -fathom. -</UL> -SHAR_EOF - $shar_touch -am 03191459100 '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' -a039d9160f8f35867c38c73ced65aaef page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 2006 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '2006,' '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 first take a look at the server side. As usual with -co-operating applications, you need the server up and running first. -In the case of shared memory applications, the server will create the -shared memory segment. In this example, it will also remove the -segment when done. It is important to realize though that the segment -can be created external to your application and can persist beyond -it's lifetime. In fact, you can use shared memory to create a layer -of persistence between application instances (at least, until the -machine comes down.) -<HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -c879cf850b3141d673c5c56e98a80e16 page02.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`" - test 562 -eq "$shar_count" || - $echo 'page02.pre:' 'original size' '562,' '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' && -The client app looks much like the server. We could have included the -CREATE flag with no ill effects but note the use of close() instead of -remove(). Picking the correct detachment method is rather important! -<HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -a244be660bba913fe08d218180cefca5 page03.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`" - test 217 -eq "$shar_count" || - $echo 'page03.pre:' 'original size' '217,' '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 move on to shmem.h, I want to show a different approach. In -X this new client/server pair, I use placement new to stuff an object -X (instead of a blob of bytes) into the shared memory segment. -X <P> -X There are a few caveats to putting objects into shared memory. The -X most important ones all deal with pointers: -X <ul> -X <li>Be sure your pointers point into the shared memory and not -X local process memory. -X <li>Only in very special cases will objects with virtual methods -X work (because of the VTable pointers). -X </ul> -<P> -That's not to say you shouldn't try... Just try carefully and test a lot! -X <HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -721c4a100d908d9d62c9d98950ace482 page04.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`" - test 674 -eq "$shar_count" || - $echo 'page04.pre:' 'original size' '674,' '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 Here's the mysterious shmem.h. I wanted to show it after the -X placement-new client and server so that the SharedData object -X would have some relevance. -X <HR> -SHAR_EOF - $shar_touch -am 03191459100 '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' -42f4ddae6f0ce1583d1dc03d5e485cba page05.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`" - test 178 -eq "$shar_count" || - $echo 'page05.pre:' 'original size' '178,' '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 That's it! I warned you that this one was pretty primitive. -X -X <ul> -X <li><A HREF="server.cpp">server.cpp</A> -X <li><A HREF="client.cpp">client.cpp</A> -X <li><A HREF="server2.cpp">server2.cpp</A> -X <li><A HREF="client2.cpp">client2.cpp</A> -X <li><A HREF="shmem.h">shmem.h</A> -X <li><A HREF="shmem.cpp">shmem.cpp</A> -X <li><A HREF="Makefile">Makefile</A> -X </ul> -SHAR_EOF - $shar_touch -am 03191459100 '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' -6e3002889733f5e80e7f9cc945965955 page06.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page06.pre'`" - test 401 -eq "$shar_count" || - $echo 'page06.pre:' 'original size' '401,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh00389 -exit 0 diff --git a/docs/tutorials/019/page01.html b/docs/tutorials/019/page01.html deleted file mode 100644 index 8a6d09e5ab0..00000000000 --- a/docs/tutorials/019/page01.html +++ /dev/null @@ -1,62 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 019</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 019</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sharing your Memories</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> - Did you ever wish you could read someone's mind? Or that they could - read yours? - <p> - Well, we won't be doing that here but we'll try to get close by - letting your code do something similar: Shared Memory. - <p> - What we're going to do is ask the operating system to set - aside a part of RAM that we can share with another process. By - doing this, we can allow our applications to swap data very - efficiently. - <p> - Along the way, we'll have to come up with some sort of - coordination betweent the processes. That is the most - difficult part of a shared memory system. In the tutorial we're - just going to take a simplistic approach (eg -- busy loop) but - real-world applications will need to take a serious look at - process-level synch mechanisms such as ACE_*_Semaphore. - <P> - Caveat: I've barely begun to use shared memory - myself. This tutorial and the next are very simple-minded and - primitive. Anyone who wants to provide more realistic - replacements is encouraged to drop me a note - (<A HREF="mailto:jcej@lads.com">jcej@lads.com</A>). -<P> -A tutorial wouldn't be complete without Kirthika's abstract: -<UL> -This tutorial shows how to use memory as a shared resource between the -client and server processes. ACE_Shared_Memory_SV has been used for -creating -the shared memory segment. Two different approaches have been used. One -uses the malloc () method to allocate memory while the other uses the -placement new expression (C++) of allocating a memory chunk in advance -and using it on demand. -<P> -The server has a string of alphabets from a-z which are converted to -uppercase -by the client proving that the same memory locations are being shared -between -the two processes. The syncronisation between the server and client is -done -using the ACE_OS::sleep () instead of a semaphore/mutexes with the aim -of keeping our first dive into shared memory usage simple and easy to -fathom. -</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/019/page02.html b/docs/tutorials/019/page02.html deleted file mode 100644 index b769313915f..00000000000 --- a/docs/tutorials/019/page02.html +++ /dev/null @@ -1,158 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 019</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 019</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sharing your Memories</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -We'll first take a look at the server side. As usual with -co-operating applications, you need the server up and running first. -In the case of shared memory applications, the server will create the -shared memory segment. In this example, it will also remove the -segment when done. It is important to realize though that the segment -can be created external to your application and can persist beyond -it's lifetime. In fact, you can use shared memory to create a layer -of persistence between application instances (at least, until the -machine comes down.) -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=red>/* - The client and server both need to know the shared memory key and - size. To prevent headaches, I've put those into a header they both - can share. - */</font> -<font color=blue>#include</font> "<font color=green>shmem.h</font>" - -<font color=blue>#include</font> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" - -<font color=blue>#if defined</font> (<font color=purple>ACE_LACKS_SYSV_SHMEM</font>) -int -main (int, char *[]) -{ - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>System V Shared Memory not available on this platform\n</font>"), - 100); -} -#else <font color=red>// ACE_LACKS_SYSV_SHMEM</font> -int -main (int, char *argv[]) -{ - <font color=red>/* - You can use the ACE_Malloc template to create memory pools - from various shared memory strategies. It's really cool. - We're not going to use it. - - Instead, I want to get to the roots of it all and directly - use ACE_Shared_Memory_SV. Like many ACE objects, this is a - wrapper around OS services. - - With this constructor we create a shared memory area to - use. The ACE_CREATE flag will cause it to be created if it - doesn't already exist. The SHM_KEY value (from shmem.h) - uniquely identifies the segment and allows other apps to - attach to the same segment. Execute 'ipcs -m' before and - after starting this app to see that the segment is created. - (I can't for the life of me correlate the SHM_KEY value back - to the key/id reported by ipcs though.) - */</font> - ACE_Shared_Memory_SV shm_server (SHM_KEY, SHMSZ, - <font color=#008888>ACE_Shared_Memory_SV::ACE_CREATE</font>); - - <font color=red>/* - The constructor created the segment for us but we still need - to map the segment into our address space. (Note that you - can pass a value to malloc() but it will be silently - igored.) The void* (cast to char*) that is returned will - point to the beginning of the shared segment. - */</font> - char *shm = (char *) shm_server.malloc (); - - <font color=red>/* - Since we're asking to create the segment, we will fail if it - already exists. We could fall back and simply attach to it - like the client but I'd rather not assume it was a previous - instance of this app that left the segment around. - */</font> - if (shm == 0) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n\t(%P|%t) Cannot create shared memory segment.\n</font>" - "<font color=green>\tUse 'ipcs' to see if it already exists\n</font>", - argv[0]), - 100); - - <font color=red>/* - This second pointer will be used to walk through the block - of memory... - */</font> - char *s = shm; - - <font color=red>/* - Out of curiosity, I added this output message. The tests - I've done so far show me the same address for client and - server. What does your OS tell you? - */</font> - ACE_DEBUG ((LM_INFO, - "<font color=green>(%P|%t) Shared Memory is at 0x%x\n</font>", - shm )); - - <font color=red>/* - At this point, our application can use the pointer just like - any other given to us by new or malloc. For our purposes, - we'll copy in the alpabet as a null-terminated string. - */</font> - for (char c = 'a'; c <= 'z'; c++) - *s++ = c; - - *s = '\0'; - - <font color=red>/* - Using a simple not-too-busy loop, we'll wait for the client - (or anyone else) to change the first byte in the shared area - to a '*' character. This is where you would rather use - semaphores or some similar "<font color=green>resource light</font>" approach. - */</font> - while (*shm != '*') - <font color=#008888>ACE_OS::sleep</font> (1); - - <font color=red>/* - Let's see what the client did to the segment... - */</font> - for (s = shm; *s != '\0'; s++) - putchar (*s); - - putchar ('\n'); - - <font color=red>/* - If you're done with the segment and ready for it to be - removed from the system, use the remove() method. Once the - program exits, do 'ipcs -m' again and you'll see that the - segment is gone. If you just want to terminate your use of - the segment but leave it around for other apps, use the - close() method instead. - - The free() method may be tempting but it doesn't actually do - anything. If your app is *really* done with the shared - memory then use either close() or remove(). - */</font> - if (shm_server.remove () < 0) - ACE_ERROR ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>remove</font>")); - return 0; -} - -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_SYSV_SHMEM */</font> -</PRE> -<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/019/page03.html b/docs/tutorials/019/page03.html deleted file mode 100644 index dd9d82eb5ee..00000000000 --- a/docs/tutorials/019/page03.html +++ /dev/null @@ -1,100 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 019</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 019</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sharing your Memories</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The client app looks much like the server. We could have included the -CREATE flag with no ill effects but note the use of close() instead of -remove(). Picking the correct detachment method is rather important! -<HR> -<PRE> -<font color=red>// $Id$</font> - -<font color=red>// Again, the common stuff</font> -<font color=blue>#include</font> "<font color=green>shmem.h</font>" - -<font color=blue>#include</font> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" - -<font color=blue>#if defined</font>(<font color=purple>ACE_LACKS_SYSV_SHMEM</font>) -int -main (int, char *[]) -{ - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>System V Shared Memory not available on this platform\n</font>"), - 100); -} -#else <font color=red>// ACE_LACKS_SYSV_SHMEM</font> -int -main (int, char *[]) -{ - <font color=red>/* - Attach ourselves to the shared memory segment. - */</font> - ACE_Shared_Memory_SV shm_client (SHM_KEY, SHMSZ); - - <font color=red>/* - Get our reference to the segment... - */</font> - char *shm = (char *) shm_client.malloc (); - - <font color=red>/* - If the segment identified by SHM_KEY didn't exist then we'll - get back a 0 from malloc(). You should do this check even - if you include the CREATE flag 'cause you never know when it - might fail. - */</font> - if (shm == 0) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>(%P|%t) Could not get the segment!\n</font>"), - 100); - - <font color=red>/* - Does this match what your server said? - */</font> - ACE_DEBUG ((LM_INFO, - "<font color=green>(%P|%t) Shared Memory is at 0x%x\n</font>", - shm )); - - <font color=red>/* - Show the shared data to the user and convert it all to - uppper-case along the way. - */</font> - for (char *s = shm; *s != '\0'; s++) - { - putchar (*s); - *s = toupper(*s); - } - - putchar ('\n'); - - <font color=red>/* - Flag the server that we're done. - */</font> - *shm = '*'; - - <font color=red>/* - Here, we use close() instead of remove(). Remember, that - will just remove our attachment to the segment. Look - closely at the 'nattch' column of the ipcs output & you'll - see that this decrements it by one. - */</font> - shm_client.close(); - - return 0; -} - -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_SYSV_SHMEM */</font> -</PRE> -<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/019/page04.html b/docs/tutorials/019/page04.html deleted file mode 100644 index 898ed89e107..00000000000 --- a/docs/tutorials/019/page04.html +++ /dev/null @@ -1,156 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 019</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 019</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sharing your Memories</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> - Before we move on to shmem.h, I want to show a different approach. In - this new client/server pair, I use placement new to stuff an object - (instead of a blob of bytes) into the shared memory segment. - <P> - There are a few caveats to putting objects into shared memory. The - most important ones all deal with pointers: - <ul> - <li>Be sure your pointers point into the shared memory and not - local process memory. - <li>Only in very special cases will objects with virtual methods - work (because of the VTable pointers). - </ul> -<P> -That's not to say you shouldn't try... Just try carefully and test a lot! - <HR> -<HR width=50%><P><center>server2.cpp</center><HR width=50%> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>shmem.h</font>" - -<font color=blue>#include</font> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" - -<font color=blue>#if defined</font> (<font color=purple>ACE_LACKS_SYSV_SHMEM</font>) -int -main (int, char *[]) -{ - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>System V Shared Memory not available on this platform\n</font>"), - 100); -} -#else <font color=red>// ACE_LACKS_SYSV_SHMEM</font> -int -main (int, char *argv[]) -{ - <font color=red>// Be sure the segment is sized to hold our object.</font> - ACE_Shared_Memory_SV shm_server (SHM_KEY, - sizeof (SharedData), - <font color=#008888>ACE_Shared_Memory_SV::ACE_CREATE</font>); - char *shm = (char *) shm_server.malloc (); - - if (shm == 0) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>%p\n\t(%P|%t) Cannot create shared memory segment.\n</font>" - "<font color=green>\tUse 'ipcs' to see if it already exists\n</font>", - argv[0]), - 100); - - ACE_DEBUG ((LM_INFO, - "<font color=green>(%P|%t) Shared Memory is at 0x%x\n</font>", - shm )); - - <font color=red>/* - Use the placement new syntax to stuff the object into the - correct location. I think they generally reserve this for - the advanced class... - */</font> - SharedData *sd = new (shm) SharedData; - - <font color=red>// Use the set() method to put some data into the object</font> - sd->set (); - - <font color=red>// Set the 'available' flag to zero so that we can wait on it</font> - sd->available (0); - - <font color=red>/* - Another cheesy busy loop while we wait for the object to - become available. The cool way would be to hide a semaphore - or two behind this method call & eliminate the sleep. - */</font> - while (sd->available () == 0) - <font color=#008888>ACE_OS::sleep</font> (1); - - <font color=red>// Show the user what's in the segment</font> - sd->show (); - - <font color=red>// All done.</font> - if (shm_server.remove () < 0) - ACE_ERROR ((LM_ERROR, - "<font color=green>%p\n</font>", - "<font color=green>remove</font>")); - return 0; -} - -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_SYSV_SHMEM */</font> -</PRE> -<HR width=50%><P><center>client2.cpp</center><HR width=50%> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>shmem.h</font>" - -<font color=blue>#include</font> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" - -<font color=blue>#if defined</font>(<font color=purple>ACE_LACKS_SYSV_SHMEM</font>) -int -main (int, char *[]) -{ - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>System V Shared Memory not available on this platform\n</font>"), - 100); -} -#else <font color=red>// ACE_LACKS_SYSV_SHMEM</font> -int -main (int, char *[]) -{ - ACE_Shared_Memory_SV shm_client (SHM_KEY, - sizeof (SharedData)); - - char *shm = (char *) shm_client.malloc (); - - ACE_DEBUG ((LM_INFO, - "<font color=green>(%P|%t) Shared Memory is at 0x%x\n</font>", - shm)); - - <font color=red>/* - More placement new. The constructor parameter prevents - clobbering what the server may have written with it's show() - method. - */</font> - SharedData *sd = new (shm) SharedData (0); - - <font color=red>// Show it</font> - sd->show (); - - <font color=red>// Change it</font> - sd->set (); - - <font color=red>// Advertise it</font> - sd->available (1); - - shm_client.close (); - - return 0; -} - -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_SYSV_SHMEM */</font> -</PRE> -<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/019/page05.html b/docs/tutorials/019/page05.html deleted file mode 100644 index 4f81f90b7d9..00000000000 --- a/docs/tutorials/019/page05.html +++ /dev/null @@ -1,127 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 019</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 019</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sharing your Memories</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> - Here's the mysterious shmem.h. I wanted to show it after the - placement-new client and server so that the SharedData object - would have some relevance. - <HR> -<HR width=50%><P><center>shmem.h</center><HR width=50%> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>SHMEM_H</font> -<font color=blue>#define</font> <font color=purple>SHMEM_H</font> - -<font color=red>// This is where you'll find the ACE_Shared_Memory_SV object</font> -<font color=blue>#include</font> "<A HREF="../../../ace/Shared_Memory_SV.h">ace/Shared_Memory_SV.h</A>" - -<font color=red>// SHMSZ is just enough for the alphabet and a null terminator</font> -<font color=blue>#define</font> <font color=purple>SHMSZ</font> 27 - -<font color=red>// Play with this, pick a value you like that isn't used by something else.</font> -<font color=blue>#define</font> <font color=purple>SHM_KEY</font> 4200 - -<font color=red>/* - This is what we stuff into shared memory via placement new in the - second client/server pair. Notice that it is a very basic object - with no virtual methods and only concrete data. - */</font> -class SharedData -{ -public: - <font color=red>// Construct the object and optionally initialize buf_.</font> - SharedData (int initialized = 1); - - <font color=red>// Put some data into buf_</font> - void set (void); - - <font color=red>// Show the data in buf_</font> - void show (void); - - <font color=red>// What is the value of available_</font> - int available (void); - - <font color=red>// Set the value of available_</font> - void available (int not_in_use); - -protected: - <font color=red>// Big enough for a simple message</font> - char buf_[128]; - <font color=red>// A cheap mutex</font> - int available_; -}; - -<font color=blue>#endif</font> <font color=red>/* SHMEM_H */</font> -</PRE> -<HR width=50%><P><center>shmem.cpp</center><HR width=50%> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>shmem.h</font>" - -<font color=blue>#include</font> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" - -#if ! defined (ACE_LACKS_SYSV_SHMEM) - -<font color=red>/* - Set the available_ flag to zero & optionally initialize the buf_ - area. -*/</font> - -<font color=#008888>SharedData::SharedData</font> (int initialize) - : available_ (0) -{ - if (initialize) - <font color=#008888>ACE_OS::sprintf</font> (buf_, "<font color=green>UNSET\n</font>"); -} - -<font color=red>/* - Write the process ID into the buffer. This will prove to us that - the data really is shared between the client and server. -*/</font> -void <font color=#008888>SharedData::set</font> (void) -{ - <font color=#008888>ACE_OS::sprintf</font> (buf_, - "<font color=green>My PID is (%d)\n</font>", - <font color=#008888>ACE_OS::getpid</font> ()); -} - -<font color=red>/* - Display the buffer to the user -*/</font> -void <font color=#008888>SharedData::show</font>(void) -{ - ACE_DEBUG ((LM_INFO, - "<font color=green>(%P|%t) Shared Data text is (%s)\n</font>", - buf_)); -} - -<font color=red>// Show flag</font> -int <font color=#008888>SharedData::available</font>(void) -{ - return available_; -} - -<font color=red>// Set flag</font> -void <font color=#008888>SharedData::available</font>(int a) -{ - available_ = a; -} - -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_SYSV_SHMEM */</font> -</PRE> -<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/019/page06.html b/docs/tutorials/019/page06.html deleted file mode 100644 index 88b263a0400..00000000000 --- a/docs/tutorials/019/page06.html +++ /dev/null @@ -1,29 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 019</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 019</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sharing your Memories</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> - That's it! I warned you that this one was pretty primitive. - - <ul> - <li><A HREF="server.cpp">server.cpp</A> - <li><A HREF="client.cpp">client.cpp</A> - <li><A HREF="server2.cpp">server2.cpp</A> - <li><A HREF="client2.cpp">client2.cpp</A> - <li><A HREF="shmem.h">shmem.h</A> - <li><A HREF="shmem.cpp">shmem.cpp</A> - <li><A HREF="Makefile">Makefile</A> - </ul> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/019/server.cpp b/docs/tutorials/019/server.cpp deleted file mode 100644 index ec65de3bfb5..00000000000 --- a/docs/tutorials/019/server.cpp +++ /dev/null @@ -1,128 +0,0 @@ -// $Id$ - -/* - The client and server both need to know the shared memory key and - size. To prevent headaches, I've put those into a header they both - can share. - */ -#include "shmem.h" - -#include "ace/Log_Msg.h" - -#if defined (ACE_LACKS_SYSV_SHMEM) -int -main (int, char *[]) -{ - ACE_ERROR_RETURN ((LM_ERROR, - "System V Shared Memory not available on this platform\n"), - 100); -} -#else // ACE_LACKS_SYSV_SHMEM -int -main (int, char *argv[]) -{ - /* - You can use the ACE_Malloc template to create memory pools - from various shared memory strategies. It's really cool. - We're not going to use it. - - Instead, I want to get to the roots of it all and directly - use ACE_Shared_Memory_SV. Like many ACE objects, this is a - wrapper around OS services. - - With this constructor we create a shared memory area to - use. The ACE_CREATE flag will cause it to be created if it - doesn't already exist. The SHM_KEY value (from shmem.h) - uniquely identifies the segment and allows other apps to - attach to the same segment. Execute 'ipcs -m' before and - after starting this app to see that the segment is created. - (I can't for the life of me correlate the SHM_KEY value back - to the key/id reported by ipcs though.) - */ - ACE_Shared_Memory_SV shm_server (SHM_KEY, SHMSZ, - ACE_Shared_Memory_SV::ACE_CREATE); - - /* - The constructor created the segment for us but we still need - to map the segment into our address space. (Note that you - can pass a value to malloc() but it will be silently - igored.) The void* (cast to char*) that is returned will - point to the beginning of the shared segment. - */ - char *shm = (char *) shm_server.malloc (); - - /* - Since we're asking to create the segment, we will fail if it - already exists. We could fall back and simply attach to it - like the client but I'd rather not assume it was a previous - instance of this app that left the segment around. - */ - if (shm == 0) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n\t(%P|%t) Cannot create shared memory segment.\n" - "\tUse 'ipcs' to see if it already exists\n", - argv[0]), - 100); - - /* - This second pointer will be used to walk through the block - of memory... - */ - char *s = shm; - - /* - Out of curiosity, I added this output message. The tests - I've done so far show me the same address for client and - server. What does your OS tell you? - */ - ACE_DEBUG ((LM_INFO, - "(%P|%t) Shared Memory is at 0x%x\n", - shm )); - - /* - At this point, our application can use the pointer just like - any other given to us by new or malloc. For our purposes, - we'll copy in the alpabet as a null-terminated string. - */ - for (char c = 'a'; c <= 'z'; c++) - *s++ = c; - - *s = '\0'; - - /* - Using a simple not-too-busy loop, we'll wait for the client - (or anyone else) to change the first byte in the shared area - to a '*' character. This is where you would rather use - semaphores or some similar "resource light" approach. - */ - while (*shm != '*') - ACE_OS::sleep (1); - - /* - Let's see what the client did to the segment... - */ - for (s = shm; *s != '\0'; s++) - putchar (*s); - - putchar ('\n'); - - /* - If you're done with the segment and ready for it to be - removed from the system, use the remove() method. Once the - program exits, do 'ipcs -m' again and you'll see that the - segment is gone. If you just want to terminate your use of - the segment but leave it around for other apps, use the - close() method instead. - - The free() method may be tempting but it doesn't actually do - anything. If your app is *really* done with the shared - memory then use either close() or remove(). - */ - if (shm_server.remove () < 0) - ACE_ERROR ((LM_ERROR, - "%p\n", - "remove")); - return 0; -} - -#endif /* ACE_LACKS_SYSV_SHMEM */ diff --git a/docs/tutorials/019/server2.cpp b/docs/tutorials/019/server2.cpp deleted file mode 100644 index dca34b15acd..00000000000 --- a/docs/tutorials/019/server2.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// $Id$ - -#include "shmem.h" - -#include "ace/Log_Msg.h" - -#if defined (ACE_LACKS_SYSV_SHMEM) -int -main (int, char *[]) -{ - ACE_ERROR_RETURN ((LM_ERROR, - "System V Shared Memory not available on this platform\n"), - 100); -} -#else // ACE_LACKS_SYSV_SHMEM -int -main (int, char *argv[]) -{ - // Be sure the segment is sized to hold our object. - ACE_Shared_Memory_SV shm_server (SHM_KEY, - sizeof (SharedData), - ACE_Shared_Memory_SV::ACE_CREATE); - char *shm = (char *) shm_server.malloc (); - - if (shm == 0) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n\t(%P|%t) Cannot create shared memory segment.\n" - "\tUse 'ipcs' to see if it already exists\n", - argv[0]), - 100); - - ACE_DEBUG ((LM_INFO, - "(%P|%t) Shared Memory is at 0x%x\n", - shm )); - - /* - Use the placement new syntax to stuff the object into the - correct location. I think they generally reserve this for - the advanced class... - */ - SharedData *sd = new (shm) SharedData; - - // Use the set() method to put some data into the object - sd->set (); - - // Set the 'available' flag to zero so that we can wait on it - sd->available (0); - - /* - Another cheesy busy loop while we wait for the object to - become available. The cool way would be to hide a semaphore - or two behind this method call & eliminate the sleep. - */ - while (sd->available () == 0) - ACE_OS::sleep (1); - - // Show the user what's in the segment - sd->show (); - - // All done. - if (shm_server.remove () < 0) - ACE_ERROR ((LM_ERROR, - "%p\n", - "remove")); - return 0; -} - -#endif /* ACE_LACKS_SYSV_SHMEM */ diff --git a/docs/tutorials/019/shmem.cpp b/docs/tutorials/019/shmem.cpp deleted file mode 100644 index 2f05aa01160..00000000000 --- a/docs/tutorials/019/shmem.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// $Id$ - -#include "shmem.h" - -#include "ace/Log_Msg.h" - -#if ! defined (ACE_LACKS_SYSV_SHMEM) - -/* - Set the available_ flag to zero & optionally initialize the buf_ - area. -*/ - -SharedData::SharedData (int initialize) - : available_ (0) -{ - if (initialize) - ACE_OS::sprintf (buf_, "UNSET\n"); -} - -/* - Write the process ID into the buffer. This will prove to us that - the data really is shared between the client and server. -*/ -void SharedData::set (void) -{ - ACE_OS::sprintf (buf_, - "My PID is (%d)\n", - ACE_OS::getpid ()); -} - -/* - Display the buffer to the user -*/ -void SharedData::show(void) -{ - ACE_DEBUG ((LM_INFO, - "(%P|%t) Shared Data text is (%s)\n", - buf_)); -} - -// Show flag -int SharedData::available(void) -{ - return available_; -} - -// Set flag -void SharedData::available(int a) -{ - available_ = a; -} - -#endif /* ACE_LACKS_SYSV_SHMEM */ diff --git a/docs/tutorials/019/shmem.h b/docs/tutorials/019/shmem.h deleted file mode 100644 index 74d4798b794..00000000000 --- a/docs/tutorials/019/shmem.h +++ /dev/null @@ -1,45 +0,0 @@ -// $Id$ - -#ifndef SHMEM_H -#define SHMEM_H - -// This is where you'll find the ACE_Shared_Memory_SV object -#include "ace/Shared_Memory_SV.h" - -// SHMSZ is just enough for the alphabet and a null terminator -#define SHMSZ 27 - -// Play with this, pick a value you like that isn't used by something else. -#define SHM_KEY 4200 - -/* - This is what we stuff into shared memory via placement new in the - second client/server pair. Notice that it is a very basic object - with no virtual methods and only concrete data. - */ -class SharedData -{ -public: - // Construct the object and optionally initialize buf_. - SharedData (int initialized = 1); - - // Put some data into buf_ - void set (void); - - // Show the data in buf_ - void show (void); - - // What is the value of available_ - int available (void); - - // Set the value of available_ - void available (int not_in_use); - -protected: - // Big enough for a simple message - char buf_[128]; - // A cheap mutex - int available_; -}; - -#endif /* SHMEM_H */ diff --git a/docs/tutorials/020/020-client.dsp b/docs/tutorials/020/020-client.dsp deleted file mode 100644 index 92d8ebe78b0..00000000000 --- a/docs/tutorials/020/020-client.dsp +++ /dev/null @@ -1,105 +0,0 @@ -# Microsoft Developer Studio Project File - Name="020 client" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=020 client - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "020 client.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "020 client.mak" CFG="020 client - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "020 client - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "020 client - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "020 client - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "020 client - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "020 client - Win32 Release"
-# Name "020 client - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\client.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mmap.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\mmap.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/020/020-client2.dsp b/docs/tutorials/020/020-client2.dsp deleted file mode 100644 index 4bd463b95b3..00000000000 --- a/docs/tutorials/020/020-client2.dsp +++ /dev/null @@ -1,105 +0,0 @@ -# Microsoft Developer Studio Project File - Name="020 client2" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=020 client2 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "020 client2.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "020 client2.mak" CFG="020 client2 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "020 client2 - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "020 client2 - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "020 client2 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "020 client2 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "020 client2 - Win32 Release"
-# Name "020 client2 - Win32 Debug"
-# Begin Group "Header Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\mmap.h
-# End Source File
-# End Group
-# Begin Group "Source Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\client2.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mmap.cpp
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/020/020-server.dsp b/docs/tutorials/020/020-server.dsp deleted file mode 100644 index 26eced19e76..00000000000 --- a/docs/tutorials/020/020-server.dsp +++ /dev/null @@ -1,105 +0,0 @@ -# Microsoft Developer Studio Project File - Name="020 server" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=020 server - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "020 server.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "020 server.mak" CFG="020 server - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "020 server - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "020 server - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "020 server - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "020 server - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "020 server - Win32 Release"
-# Name "020 server - Win32 Debug"
-# Begin Group "Header Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\mmap.h
-# End Source File
-# End Group
-# Begin Group "Source Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\mmap.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\server.cpp
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/020/020-server2.dsp b/docs/tutorials/020/020-server2.dsp deleted file mode 100644 index 9011a553e0f..00000000000 --- a/docs/tutorials/020/020-server2.dsp +++ /dev/null @@ -1,105 +0,0 @@ -# Microsoft Developer Studio Project File - Name="020 server2" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=020 server2 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "020 server2.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "020 server2.mak" CFG="020 server2 - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "020 server2 - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "020 server2 - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "020 server2 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "020 server2 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "020 server2 - Win32 Release"
-# Name "020 server2 - Win32 Debug"
-# Begin Group "Header Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\mmap.h
-# End Source File
-# End Group
-# Begin Group "Source Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\mmap.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\server2.cpp
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/020/Makefile b/docs/tutorials/020/Makefile deleted file mode 100644 index f71ec01f963..00000000000 --- a/docs/tutorials/020/Makefile +++ /dev/null @@ -1,79 +0,0 @@ - -# $Id$ - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = client server client2 server2 - -FILES = mmap - -BUILD = $(VBIN) - -BSRC = $(addsuffix .cpp,$(BIN)) - -SRC += $(addsuffix .cpp,$(FILES)) - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -rename : # - for i in *.cxx ; do \ - n=`expr "$$i" : "\(.*\).cxx"` ;\ - mv $$i $$n.cpp ;\ - done - -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb -ts2 -bl -bli0 < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - -e 's/ / /g' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - -Depend : # - $(MAKE) SRC="$(SRC) $(BSRC)" depend - perl ../fix.Makefile - -.depend : # - touch .depend - -HTML : # - [ -f hdr ] || $(MAKE) UNSHAR - perl ../combine *.pre - -SHAR : # - [ ! -f combine.shar ] || exit 1 - shar -T hdr bodies *.pre *.pst > combine.shar && $(RM) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - -include .depend diff --git a/docs/tutorials/020/client.cpp b/docs/tutorials/020/client.cpp deleted file mode 100644 index 2ffb34a7404..00000000000 --- a/docs/tutorials/020/client.cpp +++ /dev/null @@ -1,33 +0,0 @@ - -// $Id$ - -#include "mmap.h" - -#include "ace/Log_Msg.h" - -int main (int, char *[]) -{ - ACE_Shared_Memory_MM shm_client (SHM_KEY, SHMSZ); - char *shm = (char *) shm_client.malloc (); - - ACE_DEBUG ((LM_INFO, "(%P|%t) Memory Mapped file is at 0x%x\n", - shm )); - - if( ! shm ) - { - ACE_ERROR_RETURN ((LM_ERROR,"(%P|%t) Could not get the mmapped file!\n"),100); - } - - for (char *s = shm; *s != '\0'; s++) - { - putchar (*s); - *s = toupper(*s); - } - - putchar ('\n'); - *shm = '*'; - - shm_client.close(); - - return 0; -} diff --git a/docs/tutorials/020/client2.cpp b/docs/tutorials/020/client2.cpp deleted file mode 100644 index 0bd19359e41..00000000000 --- a/docs/tutorials/020/client2.cpp +++ /dev/null @@ -1,26 +0,0 @@ - -// $Id$ - -#include "mmap.h" - -#include "ace/Log_Msg.h" - -int main (int, char *[]) -{ - ACE_Shared_Memory_MM shm_client (SHM_KEY, sizeof(SharedData)); - - char *shm = (char *) shm_client.malloc (); - - ACE_DEBUG ((LM_INFO, "(%P|%t) Memory Mapped file is at 0x%x\n", - shm )); - - SharedData * sd = new(shm) SharedData(0); - - sd->show(); - sd->set(); - sd->available(1); - - shm_client.close(); - - return 0; -} diff --git a/docs/tutorials/020/combine.shar b/docs/tutorials/020/combine.shar deleted file mode 100644 index 5ea0eebeecd..00000000000 --- a/docs/tutorials/020/combine.shar +++ /dev/null @@ -1,364 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/020'. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 426 -rw-rw-r-- hdr -# 69 -rw-rw-r-- bodies -# 1394 -rw-rw-r-- page01.pre -# 524 -rw-rw-r-- page02.pre -# 115 -rw-rw-r-- page03.pre -# 410 -rw-rw-r-- page04.pre -# 102 -rw-rw-r-- page05.pre -# 371 -rw-rw-r-- page06.pre -# 131 -rw-rw-r-- page02.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 _sh00417; 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 020</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> -X -<CENTER><B><FONT SIZE=+2>ACE Tutorial 020</FONT></B></CENTER> -X -<CENTER><B><FONT SIZE=+2>Sharing your Memories with persistence</FONT></B></CENTER> -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -edd6dc67f13434391cf73b7604485b80 hdr -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`" - test 426 -eq "$shar_count" || - $echo 'hdr:' 'original size' '426,' '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.cpp -server2.cpp client2.cpp -mmap.h mmap.cpp -SHAR_EOF - $shar_touch -am 1228174898 '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' -a5d087bf1c11cf431c082ba146f3c6aa bodies -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`" - test 69 -eq "$shar_count" || - $echo 'bodies:' 'original size' '69,' '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 This tutorial mirrors the previous. Instead of using shared memory, -X this time we'll be using a memory-mapped file. -X <p> -X The cool thing about doing it this way is that we gain -X persistence of memory even across reboots. I wonder if you -X could memory map a file that's mounted via NFS? -X <p> -X Like the shared memory tutorial, this one is also very basic and -X primitive. I'm assuming you've read that one, so I'll just hit -X the high points this time through.. -<P> -Kirthika's abstract: -<UL> -Here, the ACE_Shared_Memory_MM class has been used to provide -persistence of the contents of the shared memory resource used by -the server and client. A memory_map which is really a file mapped onto -memory appears like an array which can be -easily manipulated while actually the data is stored in a file thus -making the contents permanent. In the previous tutorial, this wasnt -possible as we were dealing with shared memory allocated from the RAM. -<P> -Again, here too, the example consists of a server and a client sharing -memory -(the mem_map) and the server writing a a-z string to it which will -be successfully converted to uppercase by the client. -<P> -Notice that, similarities in usage abound between the previous and the -current tutorial which will prove to be a force for templatisation. -For that we need to go ahead -- to the next tutorial! -X -</UL> -SHAR_EOF - $shar_touch -am 03191459100 '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' -abcb95607715bae0a3e648672ec2c2bd page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 1394 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '1394,' '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 Here's our new server using a memory mapped file instead of Unix -X System V shared memory. Print out both servers and hold 'em up -X to a strong light. I think you'll see there isn't much -X difference. -X <p> -X The filename is defined in mmap.h as <i>mmapfile</i>. You can -X <i>cat</i> it any time to see what's in there. If you're -X feeling brave, try writting some data into it. On my system it -X causes unpleasant things to happen. I'd recommend that you -X don't do that! -<hr> -SHAR_EOF - $shar_touch -am 03191459100 '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' -94e75b2122d4d4c57e6f2f75c8d09b18 page02.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`" - test 524 -eq "$shar_count" || - $echo 'page02.pre:' 'original size' '524,' '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' && -There's no important difference between this and the SV client. Is -X everybody thinking "template" here? -<hr> -SHAR_EOF - $shar_touch -am 03191459100 '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' -4ecbc37dd434a7f7ac6d17967625cfcb page03.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`" - test 115 -eq "$shar_count" || - $echo 'page03.pre:' 'original size' '115,' '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' && -I wanted to show placement new again & prove that you can use it with -X a memory mapped file just as easily as with a shared memory -X segment. -X <p> -Imagine if you had an object that contained an image & then you mapped -X that to a file... Instead of a bunch of jpg files laying -X around, you would actually have objects instead. Save the -X image? No problem, it's already there! -<hr> -SHAR_EOF - $shar_touch -am 03191459100 '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' -e774cae1bab0348030a224b6d2836d50 page04.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`" - test 410 -eq "$shar_count" || - $echo 'page04.pre:' 'original size' '410,' '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' && -The mmap.h where we define stuff that needs to be shared between the -X apps at compile-time. -<hr> -SHAR_EOF - $shar_touch -am 03191459100 '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' -4dd4610ed79583de6edd62eeb02bf7fe page05.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`" - test 102 -eq "$shar_count" || - $echo 'page05.pre:' 'original size' '102,' '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' && -This one was even shorter than the last! -X -X <ul> -X <li><A HREF="server.cpp">server.cpp</A> -X <li><A HREF="client.cpp">client.cpp</A> -X <li><A HREF="server2.cpp">server2.cpp</A> -X <li><A HREF="client2.cpp">client2.cpp</A> -X <li><A HREF="mmap.h">mmap.h</A> -X <li><A HREF="mmap.cpp">mmap.cpp</A> -X <li><A HREF="Makefile">Makefile</A> -X </ul> -SHAR_EOF - $shar_touch -am 03191459100 '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' -8c515447a6b2a9c39a25915248260602 page06.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page06.pre'`" - test 371 -eq "$shar_count" || - $echo 'page06.pre:' 'original size' '371,' '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> -BTW: In ACE 4.6.7 and prior there is a bug that prevents the remove() -X method from actually removing the physical file. -SHAR_EOF - $shar_touch -am 03191459100 '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' -6c619eb19adbe3a79b5e6d2bf8b0e6d0 page02.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pst'`" - test 131 -eq "$shar_count" || - $echo 'page02.pst:' 'original size' '131,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh00417 -exit 0 diff --git a/docs/tutorials/020/mmap.cpp b/docs/tutorials/020/mmap.cpp deleted file mode 100644 index b99811aa0d4..00000000000 --- a/docs/tutorials/020/mmap.cpp +++ /dev/null @@ -1,36 +0,0 @@ - -// $Id$ - -#include "mmap.h" - -#include "ace/Log_Msg.h" - -SharedData::SharedData(int _initialize) - : available_(0) -{ - if( _initialize ) - { - ACE_OS::sprintf(buf_,"UNSET\n"); - } -} - -void SharedData::set(void) -{ - ACE_OS::sprintf(buf_,"My PID is (%d)\n",ACE_OS::getpid()); -} - -void SharedData::show(void) -{ - ACE_DEBUG ((LM_INFO, "(%P|%t) Shared Data text is (%s)\n", - buf_ )); -} - -int SharedData::available(void) -{ - return available_; -} - -void SharedData::available(int _available) -{ - available_ = _available; -} diff --git a/docs/tutorials/020/mmap.h b/docs/tutorials/020/mmap.h deleted file mode 100644 index 1604b678ccb..00000000000 --- a/docs/tutorials/020/mmap.h +++ /dev/null @@ -1,38 +0,0 @@ -// $Id$ - -#ifndef MMAP_H -#define MMAP_H - -// The expected filename for ACE_Shared_Memory_MM.h -#include "ace/Shared_Memory_MM.h" - -// Just enough for the alphabet... -#define SHMSZ 27 - -/* - Here we use a real filename instead of an arbitrary number. This - actually will exist in the filesystem. You can 'cat' it and - everything! -*/ -#define SHM_KEY "mmapfile" - -/* - The SV Shared Memory SharedData object returns. It is identical to - the one we used in that tutorial. I didn't even change the name. - */ -class SharedData -{ -public: - SharedData (int initialize = 1); - - void set (void); - void show (void); - int available (void); - void available (int not_in_use); - -protected: - char buf_[128]; - int available_; -}; - -#endif /* MMAP_H */ diff --git a/docs/tutorials/020/mmapfile b/docs/tutorials/020/mmapfile deleted file mode 100644 index 7ea5caf832b..00000000000 --- a/docs/tutorials/020/mmapfile +++ /dev/null @@ -1,8 +0,0 @@ -root tty2 Dec 13 19:43 -jcej tty5 Dec 14 20:36 -dialout modem Dec 28 15:51 (/usr/sbin/diald -daemon -f /etc/diald.lads) -jcej ttyp1 Dec 22 00:31 (:0.0) -jcej ttyp2 Dec 22 11:22 (:0.0) -jcej ttyp7 Dec 22 18:22 (:0.0) -jcej ttyp9 Dec 24 00:04 (:0.0) -jcej ttyp8 Dec 22 18:47 (:0.0) diff --git a/docs/tutorials/020/page01.html b/docs/tutorials/020/page01.html deleted file mode 100644 index 61646622780..00000000000 --- a/docs/tutorials/020/page01.html +++ /dev/null @@ -1,49 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 020</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 020</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sharing your Memories with persistence</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> - This tutorial mirrors the previous. Instead of using shared memory, - this time we'll be using a memory-mapped file. - <p> - The cool thing about doing it this way is that we gain - persistence of memory even across reboots. I wonder if you - could memory map a file that's mounted via NFS? - <p> - Like the shared memory tutorial, this one is also very basic and - primitive. I'm assuming you've read that one, so I'll just hit - the high points this time through.. -<P> -Kirthika's abstract: -<UL> -Here, the ACE_Shared_Memory_MM class has been used to provide -persistence of the contents of the shared memory resource used by -the server and client. A memory_map which is really a file mapped onto -memory appears like an array which can be -easily manipulated while actually the data is stored in a file thus -making the contents permanent. In the previous tutorial, this wasnt -possible as we were dealing with shared memory allocated from the RAM. -<P> -Again, here too, the example consists of a server and a client sharing -memory -(the mem_map) and the server writing a a-z string to it which will -be successfully converted to uppercase by the client. -<P> -Notice that, similarities in usage abound between the previous and the -current tutorial which will prove to be a force for templatisation. -For that we need to go ahead -- to the next tutorial! - -</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/020/page02.html b/docs/tutorials/020/page02.html deleted file mode 100644 index 38d27404fa8..00000000000 --- a/docs/tutorials/020/page02.html +++ /dev/null @@ -1,77 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 020</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 020</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sharing your Memories with persistence</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> - Here's our new server using a memory mapped file instead of Unix - System V shared memory. Print out both servers and hold 'em up - to a strong light. I think you'll see there isn't much - difference. - <p> - The filename is defined in mmap.h as <i>mmapfile</i>. You can - <i>cat</i> it any time to see what's in there. If you're - feeling brave, try writting some data into it. On my system it - causes unpleasant things to happen. I'd recommend that you - don't do that! -<hr> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>mmap.h</font>" - -<font color=blue>#include</font> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" - -int -main (int, char *[]) -{ - <font color=red>/* - The default behavior of the memory map wrapper is to create - the file if it doesn't exist. This is a minor change from - the SV shared memory wrapper. - */</font> - ACE_Shared_Memory_MM shm_server (SHM_KEY, SHMSZ); - char *shm = (char *) shm_server.malloc (); - char *s = shm; - - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) Memory Mapped file is at 0x%x\n</font>", - shm )); - - for (char c = 'a'; c <= 'z'; c++) - *s++ = c; - - *s = '\0'; - - while (*shm != '*') - <font color=#008888>ACE_OS::sleep</font> (1); - - for (s = shm; *s != '\0'; s++) - { - putchar (*s); - } - - putchar ('\n'); - - if (shm_server.remove () < 0) - ACE_ERROR ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>remove</font>")); - - return 0; -} - -</PRE> -<HR> -BTW: In ACE 4.6.7 and prior there is a bug that prevents the remove() - method from actually removing the physical file. -<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/020/page03.html b/docs/tutorials/020/page03.html deleted file mode 100644 index 69782913b5d..00000000000 --- a/docs/tutorials/020/page03.html +++ /dev/null @@ -1,56 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 020</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 020</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sharing your Memories with persistence</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -There's no important difference between this and the SV client. Is - everybody thinking "template" here? -<hr> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>mmap.h</font>" - -<font color=blue>#include</font> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" - -int main (int, char *[]) -{ - ACE_Shared_Memory_MM shm_client (SHM_KEY, SHMSZ); - char *shm = (char *) shm_client.malloc (); - - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) Memory Mapped file is at 0x%x\n</font>", - shm )); - - if( ! shm ) - { - ACE_ERROR_RETURN ((LM_ERROR,"<font color=green>(%P|%t) Could not get the mmapped file!\n</font>"),100); - } - - for (char *s = shm; *s != '\0'; s++) - { - putchar (*s); - *s = toupper(*s); - } - - putchar ('\n'); - *shm = '*'; - - shm_client.close(); - - return 0; -} -</PRE> -<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/020/page04.html b/docs/tutorials/020/page04.html deleted file mode 100644 index 573ddaa23f0..00000000000 --- a/docs/tutorials/020/page04.html +++ /dev/null @@ -1,93 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 020</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 020</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sharing your Memories with persistence</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -I wanted to show placement new again & prove that you can use it with - a memory mapped file just as easily as with a shared memory - segment. - <p> -Imagine if you had an object that contained an image & then you mapped - that to a file... Instead of a bunch of jpg files laying - around, you would actually have objects instead. Save the - image? No problem, it's already there! -<hr> -<HR width=50%><P><center>server2.cpp</center><HR width=50%> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>mmap.h</font>" - -<font color=blue>#include</font> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" - -int -main (int, char *[]) -{ - ACE_Shared_Memory_MM shm_server (SHM_KEY, sizeof(SharedData) ); - - char *shm = (char *) shm_server.malloc (); - - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) Memory Mapped file is at 0x%x\n</font>", - shm )); - - SharedData * sd = new(shm) SharedData; - - sd->set(); - sd->available(0); - - while ( ! sd->available() ) - <font color=#008888>ACE_OS::sleep</font> (1); - - sd->show(); - - if (shm_server.remove () < 0) - ACE_ERROR ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green>remove</font>")); - - return 0; -} - -</PRE> -<HR width=50%><P><center>client2.cpp</center><HR width=50%> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>mmap.h</font>" - -<font color=blue>#include</font> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" - -int main (int, char *[]) -{ - ACE_Shared_Memory_MM shm_client (SHM_KEY, sizeof(SharedData)); - - char *shm = (char *) shm_client.malloc (); - - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) Memory Mapped file is at 0x%x\n</font>", - shm )); - - SharedData * sd = new(shm) SharedData(0); - - sd->show(); - sd->set(); - sd->available(1); - - shm_client.close(); - - return 0; -} - -</PRE> -<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/020/page05.html b/docs/tutorials/020/page05.html deleted file mode 100644 index 4113c64151b..00000000000 --- a/docs/tutorials/020/page05.html +++ /dev/null @@ -1,101 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 020</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 020</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sharing your Memories with persistence</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -The mmap.h where we define stuff that needs to be shared between the - apps at compile-time. -<hr> -<HR width=50%><P><center>mmap.h</center><HR width=50%> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>MMAP_H</font> -<font color=blue>#define</font> <font color=purple>MMAP_H</font> - -<font color=red>// The expected filename for ACE_Shared_Memory_MM.h</font> -<font color=blue>#include</font> "<A HREF="../../../ace/Shared_Memory_MM.h">ace/Shared_Memory_MM.h</A>" - -<font color=red>// Just enough for the alphabet...</font> -<font color=blue>#define</font> <font color=purple>SHMSZ</font> 27 - -<font color=red>/* - Here we use a real filename instead of an arbitrary number. This - actually will exist in the filesystem. You can 'cat' it and - everything! -*/</font> -<font color=blue>#define</font> <font color=purple>SHM_KEY</font> "<font color=green>mmapfile</font>" - -<font color=red>/* - The SV Shared Memory SharedData object returns. It is identical to - the one we used in that tutorial. I didn't even change the name. - */</font> -class SharedData -{ -public: - SharedData (int initialize = 1); - - void set (void); - void show (void); - int available (void); - void available (int not_in_use); - -protected: - char buf_[128]; - int available_; -}; - -<font color=blue>#endif</font> <font color=red>/* MMAP_H */</font> -</PRE> -<HR width=50%><P><center>mmap.cpp</center><HR width=50%> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>mmap.h</font>" - -<font color=blue>#include</font> "<A HREF="../../../ace/Log_Msg.h">ace/Log_Msg.h</A>" - -<font color=#008888>SharedData::SharedData</font>(int _initialize) - : available_(0) -{ - if( _initialize ) - { - <font color=#008888>ACE_OS::sprintf</font>(buf_,"<font color=green>UNSET\n</font>"); - } -} - -void <font color=#008888>SharedData::set</font>(void) -{ - <font color=#008888>ACE_OS::sprintf</font>(buf_,"<font color=green>My PID is (%d)\n</font>",ACE_OS::getpid()); -} - -void <font color=#008888>SharedData::show</font>(void) -{ - ACE_DEBUG ((LM_INFO, "<font color=green>(%P|%t) Shared Data text is (%s)\n</font>", - buf_ )); -} - -int <font color=#008888>SharedData::available</font>(void) -{ - return available_; -} - -void <font color=#008888>SharedData::available</font>(int _available) -{ - available_ = _available; -} -</PRE> -<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/020/page06.html b/docs/tutorials/020/page06.html deleted file mode 100644 index 2e4b7b91fa7..00000000000 --- a/docs/tutorials/020/page06.html +++ /dev/null @@ -1,29 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 020</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 020</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Sharing your Memories with persistence</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -This one was even shorter than the last! - - <ul> - <li><A HREF="server.cpp">server.cpp</A> - <li><A HREF="client.cpp">client.cpp</A> - <li><A HREF="server2.cpp">server2.cpp</A> - <li><A HREF="client2.cpp">client2.cpp</A> - <li><A HREF="mmap.h">mmap.h</A> - <li><A HREF="mmap.cpp">mmap.cpp</A> - <li><A HREF="Makefile">Makefile</A> - </ul> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/020/server.cpp b/docs/tutorials/020/server.cpp deleted file mode 100644 index 549189ae2b1..00000000000 --- a/docs/tutorials/020/server.cpp +++ /dev/null @@ -1,42 +0,0 @@ - -// $Id$ - -#include "mmap.h" - -#include "ace/Log_Msg.h" - -int -main (int, char *[]) -{ - /* - The default behavior of the memory map wrapper is to create - the file if it doesn't exist. This is a minor change from - the SV shared memory wrapper. - */ - ACE_Shared_Memory_MM shm_server (SHM_KEY, SHMSZ); - char *shm = (char *) shm_server.malloc (); - char *s = shm; - - ACE_DEBUG ((LM_INFO, "(%P|%t) Memory Mapped file is at 0x%x\n", - shm )); - - for (char c = 'a'; c <= 'z'; c++) - *s++ = c; - - *s = '\0'; - - while (*shm != '*') - ACE_OS::sleep (1); - - for (s = shm; *s != '\0'; s++) - { - putchar (*s); - } - - putchar ('\n'); - - if (shm_server.remove () < 0) - ACE_ERROR ((LM_ERROR, "%p\n", "remove")); - - return 0; -} diff --git a/docs/tutorials/020/server2.cpp b/docs/tutorials/020/server2.cpp deleted file mode 100644 index abbe2f5b68b..00000000000 --- a/docs/tutorials/020/server2.cpp +++ /dev/null @@ -1,32 +0,0 @@ - -// $Id$ - -#include "mmap.h" - -#include "ace/Log_Msg.h" - -int -main (int, char *[]) -{ - ACE_Shared_Memory_MM shm_server (SHM_KEY, sizeof(SharedData) ); - - char *shm = (char *) shm_server.malloc (); - - ACE_DEBUG ((LM_INFO, "(%P|%t) Memory Mapped file is at 0x%x\n", - shm )); - - SharedData * sd = new(shm) SharedData; - - sd->set(); - sd->available(0); - - while ( ! sd->available() ) - ACE_OS::sleep (1); - - sd->show(); - - if (shm_server.remove () < 0) - ACE_ERROR ((LM_ERROR, "%p\n", "remove")); - - return 0; -} diff --git a/docs/tutorials/021/021-client.dsp b/docs/tutorials/021/021-client.dsp deleted file mode 100644 index 052ba50237a..00000000000 --- a/docs/tutorials/021/021-client.dsp +++ /dev/null @@ -1,105 +0,0 @@ -# Microsoft Developer Studio Project File - Name="021 client" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=021 client - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "021 client.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "021 client.mak" CFG="021 client - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "021 client - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "021 client - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "021 client - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "021 client - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "021 client - Win32 Release"
-# Name "021 client - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\client.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mpool.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\mpool.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/021/021-server.dsp b/docs/tutorials/021/021-server.dsp deleted file mode 100644 index 3667e52aa5f..00000000000 --- a/docs/tutorials/021/021-server.dsp +++ /dev/null @@ -1,105 +0,0 @@ -# Microsoft Developer Studio Project File - Name="021 server" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=021 server - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "021 server.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "021 server.mak" CFG="021 server - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "021 server - Win32 Release" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE "021 server - Win32 Debug" (based on\
- "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "021 server - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\.." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ace.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\ace"
-
-!ELSEIF "$(CFG)" == "021 server - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\ace"
-
-!ENDIF
-
-# Begin Target
-
-# Name "021 server - Win32 Release"
-# Name "021 server - Win32 Debug"
-# Begin Group "Header Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\mpool.h
-# End Source File
-# End Group
-# Begin Group "Source Files"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=.\mpool.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\server.cpp
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/docs/tutorials/021/Makefile b/docs/tutorials/021/Makefile deleted file mode 100644 index 9df7f7c3a25..00000000000 --- a/docs/tutorials/021/Makefile +++ /dev/null @@ -1,79 +0,0 @@ - -# $Id$ - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = client server - -FILES = mpool - -BUILD = $(VBIN) - -BSRC = $(addsuffix .cpp,$(BIN)) - -SRC += $(addsuffix .cpp,$(FILES)) - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - -rename : # - for i in *.cxx ; do \ - n=`expr "$$i" : "\(.*\).cxx"` ;\ - mv $$i $$n.cpp ;\ - done - -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb -ts2 -bl -bli0 < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - -e 's/ / /g' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - -Depend : # - $(MAKE) SRC="$(SRC) $(BSRC)" depend - perl ../fix.Makefile - -.depend : # - touch .depend - -HTML : # - [ -f hdr ] || $(MAKE) UNSHAR - perl ../combine *.pre - -SHAR : # - [ ! -f combine.shar ] || exit 1 - shar -T hdr bodies *.pre *.pst > combine.shar && $(RM) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - -include .depend diff --git a/docs/tutorials/021/client.cpp b/docs/tutorials/021/client.cpp deleted file mode 100644 index 544f72b49fe..00000000000 --- a/docs/tutorials/021/client.cpp +++ /dev/null @@ -1,123 +0,0 @@ - -// $Id$ - -#include "mpool.h" - -#if defined(ACE_LACKS_SYSV_SHMEM) -int -main (int, char *[]) -{ - ACE_ERROR_RETURN ((LM_ERROR, - "System V Semaphores not available on this platform.\n"),100); -} -#else // ACE_LACKS_SYSV_SHMEM -int -main (int, char *[]) -{ - /* - Use the same pool name used by the server when we create our - Allocator. This assures us that we don't create a whole new - pool. - */ - Allocator allocator (Constants::PoolName); - - /* - You can put anything in the memory pool. Not just the - character array we want. The find() method till, therefore, - return a void* that we will have to cast. - */ - void *region; - - /* - We use find() to locate a named region in the pool. This is - the counterpart to bind() used in the server. - Here, we go try to find the region that the server has created - and filled with data. If there was a problem getting the pool - or finding the region, we'll get back -1 from find(). - */ - if (allocator.pool ().find (Constants::RegionName,region) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "Cannot find the name '%s'\n", - Constants::RegionName), - 100); - - /* - Since find() returns us a void*, we cast it here to the char* - that we want. - */ - char *shm = (char *) region; - - ACE_DEBUG ((LM_INFO, - "Shared memory is at 0x%x\n", - shm)); - - /* - The same pair of semaphores as used by the server are created - here. We probably don't need the CREATE flag since the server - should have already done that. There may be some very small - windows, however, where the server would have created the - memory pool but not yet gotten to the semaphores. - */ - ACE_SV_Semaphore_Complex mutex; - ACE_ASSERT (mutex.open (Constants::SEM_KEY_1, - ACE_SV_Semaphore_Complex::ACE_CREATE, - 0) != -1); - - ACE_SV_Semaphore_Complex synch; - ACE_ASSERT (synch.open (Constants::SEM_KEY_2, - ACE_SV_Semaphore_Complex::ACE_CREATE, - 0) != -1); - - /* - It doesn't matter if we created 'mutex' or if the server did. - In either case, it was created in a locked state and we will - block here until somebody unlocks it. In our scenario, that - will have to be the server. - */ - if (mutex.acquire () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P) client mutex.acquire"), - 1); - - /* - Now that we know it is safe to access the data, we'll run - through and make sure that it contains what we think the server - supplied. - */ - for (int i = 0; i < Constants::SHMSZ; i++) - ACE_ASSERT (Constants::SHMDATA[i] == shm[i]); - - /* - Look back at the server. After filling the region, it will - attempt to acquire the lock on 'synch'. It will wait there - until we release() the semaphore. That will allow it to remove - the pool and cleanup. We can simply exit once we perform the - release. (Ok, a free() of the region would probably be polite...) - */ - if (synch.release () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P) client synch.release"), - 1); - - return 0; -} - -/* - Again, we have the necessary explicit template instantiations - because I based this on an ACE example instead of creating it from scratch. - */ -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Malloc<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple>; -template class ACE_Malloc_T<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple, ACE_Control_Block>; -template class ACE_Guard<ACE_SV_Semaphore_Simple>; -template class ACE_Write_Guard<ACE_SV_Semaphore_Simple>; -template class ACE_Read_Guard<ACE_SV_Semaphore_Simple>; -#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate ACE_Malloc<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple> -#pragma instantiate ACE_Malloc_T<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple, ACE_Control_Block> -#pragma instantiate ACE_Guard<ACE_SV_Semaphore_Simple> -#pragma instantiate ACE_Write_Guard<ACE_SV_Semaphore_Simple> -#pragma instantiate ACE_Read_Guard<ACE_SV_Semaphore_Simple> -#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ - -#endif /* ACE_LACKS_SYSV_SHMEM */ diff --git a/docs/tutorials/021/combine.shar b/docs/tutorials/021/combine.shar deleted file mode 100644 index 1c720b3abfa..00000000000 --- a/docs/tutorials/021/combine.shar +++ /dev/null @@ -1,398 +0,0 @@ -#!/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 2000-03-19 15:00 EST by <jcej@chiroptera.tragus.org>. -# Source directory was `/home/jcej/projects/ACE_wrappers/docs/tutorials/021'. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 409 -rw-rw-r-- hdr -# 47 -rw-rw-r-- bodies -# 2293 -rw-rw-r-- page01.pre -# 282 -rw-rw-r-- page02.pre -# 207 -rw-rw-r-- page03.pre -# 295 -rw-rw-r-- page04.pre -# 61 -rw-rw-r-- page05.pre -# 616 -rw-rw-r-- page06.pre -# 785 -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 _sh00446; 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 021</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> -X -<CENTER><B><FONT SIZE=+2>ACE Tutorial 021</FONT></B></CENTER> -X -<CENTER><B><FONT SIZE=+2>Pooling your memories</FONT></B></CENTER> -X -<P> -<HR WIDTH="100%"> -SHAR_EOF - $shar_touch -am 03191459100 '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' -9ffa6eb1308f4872f390b30f74a6de3b hdr -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'hdr'`" - test 409 -eq "$shar_count" || - $echo 'hdr:' 'original size' '409,' '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.cpp -mpool.h -mpool.cpp -SHAR_EOF - $shar_touch -am 0106135399 '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' -470abefc6e5e401ad9ffdfa76e3ca143 bodies -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`" - test 47 -eq "$shar_count" || - $echo 'bodies:' 'original size' '47,' '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 The previous two tutorials were very primitive & basic. They -X showed very simple uses of shared memory and memory mapped -X files. -X <p> -X If we move the level of abstraction up just a bit, the next -X thing we encounter is memory pools. ACE_Malloc<> provides -X this to us. -X <p> -X In this tutorial, we'll use ACE_Malloc<> to create a -X memory pool that is sharable between a client and server. We'll -X use a memory mapped file to provide the physical storage but -X shared memory works just as well. -<P> -Kirthika's abstract: -<UL> -The ACE_Malloc class is templatised by the type of memory pool -and the lock for it. The name of the memory pool provided can be used -in the "bind" call made by the server. This helps the other party -wanting to access it do so by a "find" call. The ACE_Malloc will -allocate -memory and on a "malloc" will return memory chunks from its reserve. -When the memory chunk is freed by the user, it will be appended to the -free list maintained by the class. Unless a "remove" is done explicitly, -the memory wont be returned to the OS. Various memory pool types can be -used, -X ACE_MMap_Memory_Pool,ACE_Sbrk_Memory_Pool to name a few. -For further details: <A HREF="../../ace/Memory_Pool.h">ace/Memory_Pool.h</A>. -<P> -In this tutorial, a ACE_Malloc class with ACE_MMAP_MEMORY_POOL -and a semophore for syncronisation has been used. This is locked by -the server initially and released after it writes into it so that -the client waiting for it can go ahead and do its job. There is yet -another semaphore used by the server to exit only after the client -has finished its task, which is locked by the client at the start -and released when its done. -<P> -Some more information regarding memory management: -ACE also provides the ACE_Allocator class which uses -dynamic binding and is flexible, though at a cost of using -virtual pointer tables. Also, there is an ACE_Allocator_Adapter class -which has an ACE_Allocator interface but ACE_Malloc functionality. -<P> -Bottomline: Memory can be managed either using the ACE_Allocator -set of classes which uses polymorphism and is thus flexible but not as -efficient as the templatised version which is the ACE_Malloc set of -classes which are more efficient but not as felxible. -X -</UL> -SHAR_EOF - $shar_touch -am 03191459100 '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' -24cacb4803303b37ae4871ff0aae141b page01.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`" - test 2293 -eq "$shar_count" || - $echo 'page01.pre:' 'original size' '2293,' '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 The key components for creating the memory pool are: -X <ul> -X <li>Create and name the pool -X <li>Allocate a chunk (region) of memory from the pool -X <li>Name the allocated region -X </ul> -X The rest of it is just critical sections and data manipulation. -<hr> -SHAR_EOF - $shar_touch -am 03191459100 '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' -6742359e1f990299bdab5992d0629d96 page02.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`" - test 282 -eq "$shar_count" || - $echo 'page02.pre:' 'original size' '282,' '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 The client side is a little simpler than the server. Mainly -X because we don't try to delete the pool: -X <ul> -X <li>Create an Allocator to access the pool -X <li>Find the named region -X </ul> -<hr> -SHAR_EOF - $shar_touch -am 03191459100 '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' -9929e87d376461c200ea8d6ad819c2b0 page03.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page03.pre'`" - test 207 -eq "$shar_count" || - $echo 'page03.pre:' 'original size' '207,' '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 Everything common the server & client is kept here. In -X particular, the Constants class where we keep the names & -X semaphore keys. -X <p> -X The Allocator class is just a thin wrapper around -X ACE_Malloc<> that moves some of the details out of the -X application logic. -<hr> -SHAR_EOF - $shar_touch -am 03191459100 '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' -82e8c15a608311faae46c4a2c6b0a5e1 page04.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`" - test 295 -eq "$shar_count" || - $echo 'page04.pre:' 'original size' '295,' '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' && -And here we have the implementation of the Allocator... -<hr> -SHAR_EOF - $shar_touch -am 03191459100 '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' -eef6d56514a448ce6cd962b7d34dd50f page05.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`" - test 61 -eq "$shar_count" || - $echo 'page05.pre:' 'original size' '61,' '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 As you can see, using a memory pool is really rather easy. The -X most difficult part, as always, is with the synch mechanisms. -X <P> -X The other nice thing about ACE_Malloc<> is that you can swap -X between System V shared memory and memory mapped files just by -X changing the template parameters. The truly adventurous will -X likely find a runtime way of doing this. -X <p> -X -X <ul> -X <li><A HREF="Makefile">Makefile</A> -X <li><A HREF="server.cpp">server.cpp</A> -X <li><A HREF="client.cpp">client.cpp</A> -X <li><A HREF="mpool.h">mpool.h</A> -X <li><A HREF="mpool.cpp">mpool.cpp</A> -X </ul> -SHAR_EOF - $shar_touch -am 03191459100 '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' -0814cb31bbfbb6ff19abba9087cb6c6c page06.pre -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page06.pre'`" - test 616 -eq "$shar_count" || - $echo 'page06.pre:' 'original size' '616,' '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> -X The really hard stuff is done by the ACE_Malloc<> template. This -X template takes two parameters.<sup>*</sup> The first is a -X memory pool class to use. ACE has several, I've choosen one -X that uses a memory-mapped file. The second parameter is a lock -X class of some sort. This is needed so that the ACE_Malloc<> can -X protect its internal data. Note that you still have to -X provide your own mutex around the data you put into the -X malloc'd area. -X -<P> -X * Actually, some implementations may require a different -X number of parameters. -X That's why ACE uses those funky macros. ACE_MMAP_MEMORY_POOL -X for instance turns into ACE_MMAP_Memory_Pool on Linux but may -X do other things on your platform. -SHAR_EOF - $shar_touch -am 03191459100 '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' -e2274ca81b8b99472c556ff05a090737 page04.pst -SHAR_EOF - else - shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pst'`" - test 785 -eq "$shar_count" || - $echo 'page04.pst:' 'original size' '785,' 'current size' "$shar_count!" - fi -fi -rm -fr _sh00446 -exit 0 diff --git a/docs/tutorials/021/mpool.cpp b/docs/tutorials/021/mpool.cpp deleted file mode 100644 index 7e55555e5bb..00000000000 --- a/docs/tutorials/021/mpool.cpp +++ /dev/null @@ -1,66 +0,0 @@ - -// $Id$ - -#include "mpool.h" - -#if !defined (ACE_LACKS_SYSV_SHMEM) - -/* - Set the values of all of the constants. This guarantees that client - and server don't get confused. - */ -const int Constants::SEM_KEY_1 = ACE_DEFAULT_SEM_KEY + 1; -const int Constants::SEM_KEY_2 = ACE_DEFAULT_SEM_KEY + 2; - -const int Constants::SHMSZ = 27; -const char * Constants::SHMDATA = "abcdefghijklmnopqrstuvwxyz"; - -const char * Constants::PoolName = "SharedMemoryPool"; -const char * Constants::RegionName = "Alphabet"; - -/* - We have to create a copy of the _name parameter in case the caller - has dynamically allocated it. The pool_ is set to NULL & will be - allocated by the accessor. - */ -Allocator::Allocator (const char *_name) - : name_ (ACE_OS::strdup (_name)), - pool_ (0) -{ - if (name_ == 0) - ACE_ERROR ((LM_ERROR, "(%P) %p", - "Allocator::Allocator cannot strdup pool name")); -} - -Allocator::~Allocator (void) -{ - /* - strdup() uses malloc(), so we must use free() to clean up. - */ - if (name_) - ACE_OS::free (name_); - - // delete doesn't really care if you give it a NULL pointer. - delete pool_; -} - -/* - Allocate the pool. Since we return a reference, we'll be in really - bad shape if the new fails. This is a great place to throw an - exception! - The other concern is thread safety. If two threads call here at - about the same time, we may create the pool twice. We can't use a - Singleton because we want to have multiple Allocator instances. The - Singleton techniques can be used though. - */ - -Allocator::pool_t & -Allocator::pool (void) -{ - if (pool_ == 0) - pool_ = new pool_t (name_); - - return *pool_; -} - -#endif /* ACE_LACKS_SYSV_SHMEM */ diff --git a/docs/tutorials/021/mpool.h b/docs/tutorials/021/mpool.h deleted file mode 100644 index fbb18e21e57..00000000000 --- a/docs/tutorials/021/mpool.h +++ /dev/null @@ -1,67 +0,0 @@ - -// $Id$ - -#ifndef MPOOL_H -#define MPOOL_H - -// Everything else we need is in this one header -#include "ace/Malloc.h" - -#if !defined (ACE_LACKS_SYSV_SHMEM) - -/* - With this we will abstract away some of the details of the memory - pool. Note that we don't treat this as a singleton because an - application may need more than one pool. Each would have a - different name and be used for different purposes. - */ - -class Allocator -{ -public: - // The pool name will be used to create a unique semaphore to - // keep this pool separate from others. - Allocator (const char * _name = "MemoryPool"); - ~Allocator (void); - - typedef ACE_Malloc<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple> pool_t; - - // Provide an accessor to the pool. This will also allocate the - // pool when first invoked. - pool_t &pool (void); - -protected: - - // The name we gave to the pool - char *name_; - - pool_t *pool_; -}; - -/* - The client and server need to agree on a certain set of values. By - placing them in the Constants class we can eliminate a bit of confusion. - */ -class Constants -{ -public: - // The semaphore keys are needed for the two semaphores that - // synch access to the shared memory area. - static const int SEM_KEY_1; - static const int SEM_KEY_2; - - // How big the pool will be and what we'll put into it. A real - // app wouldn't need SHMDATA of course. - static const int SHMSZ; - static const char *SHMDATA; - - // The name assigned to the memory pool by the server is needed - // by the client. Without it, the pool cannot be found. - // Likewise, the name the server will bind() to the region of the - // pool must be available to the client. - static const char *PoolName; - static const char *RegionName; -}; - -#endif /* ACE_LACKS_SYSV_SHMEM */ -#endif /* MPOOL_H */ diff --git a/docs/tutorials/021/page01.html b/docs/tutorials/021/page01.html deleted file mode 100644 index 93d2d2ad407..00000000000 --- a/docs/tutorials/021/page01.html +++ /dev/null @@ -1,66 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 021</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 021</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Pooling your memories</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> - The previous two tutorials were very primitive & basic. They - showed very simple uses of shared memory and memory mapped - files. - <p> - If we move the level of abstraction up just a bit, the next - thing we encounter is memory pools. ACE_Malloc<> provides - this to us. - <p> - In this tutorial, we'll use ACE_Malloc<> to create a - memory pool that is sharable between a client and server. We'll - use a memory mapped file to provide the physical storage but - shared memory works just as well. -<P> -Kirthika's abstract: -<UL> -The ACE_Malloc class is templatised by the type of memory pool -and the lock for it. The name of the memory pool provided can be used -in the "bind" call made by the server. This helps the other party -wanting to access it do so by a "find" call. The ACE_Malloc will -allocate -memory and on a "malloc" will return memory chunks from its reserve. -When the memory chunk is freed by the user, it will be appended to the -free list maintained by the class. Unless a "remove" is done explicitly, -the memory wont be returned to the OS. Various memory pool types can be -used, - ACE_MMap_Memory_Pool,ACE_Sbrk_Memory_Pool to name a few. -For further details: <A HREF="../../../ace/Memory_Pool.h">ace/Memory_Pool.h</A>. -<P> -In this tutorial, a ACE_Malloc class with ACE_MMAP_MEMORY_POOL -and a semophore for syncronisation has been used. This is locked by -the server initially and released after it writes into it so that -the client waiting for it can go ahead and do its job. There is yet -another semaphore used by the server to exit only after the client -has finished its task, which is locked by the client at the start -and released when its done. -<P> -Some more information regarding memory management: -ACE also provides the ACE_Allocator class which uses -dynamic binding and is flexible, though at a cost of using -virtual pointer tables. Also, there is an ACE_Allocator_Adapter class -which has an ACE_Allocator interface but ACE_Malloc functionality. -<P> -Bottomline: Memory can be managed either using the ACE_Allocator -set of classes which uses polymorphism and is thus flexible but not as -efficient as the templatised version which is the ACE_Malloc set of -classes which are more efficient but not as felxible. - -</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/021/page02.html b/docs/tutorials/021/page02.html deleted file mode 100644 index 1310357d60d..00000000000 --- a/docs/tutorials/021/page02.html +++ /dev/null @@ -1,186 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 021</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 021</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Pooling your memories</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> - The key components for creating the memory pool are: - <ul> - <li>Create and name the pool - <li>Allocate a chunk (region) of memory from the pool - <li>Name the allocated region - </ul> - The rest of it is just critical sections and data manipulation. -<hr> -<PRE> - -<font color=red>// $Id$</font> - -<font color=red>/* - I've hidden the details in an Allocator class declared in mpool.h - We'll come to that a little later. -*/</font> -<font color=blue>#include</font> "<font color=green>mpool.h</font>" - -<font color=blue>#if defined</font>(<font color=purple>ACE_LACKS_SYSV_SHMEM</font>) -int -main (int, char *[]) -{ - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>System V Semaphores not available on this platform.\n</font>"),100); -} -#else <font color=red>// ACE_LACKS_SYSV_SHMEM</font> -int -main (int, char *[]) -{ - <font color=red>/* - Construction of an Allocator will create the memory pool and - provide it with a name. The Constants class is also - declared in mpool.h to keep server and client on the same - page. The name is used to generate a unique semaphore which - prevents simultaneous access to the pools housekeeping - information. (Note that you still have to provide your own - synch mechanisms for the data *you* put in the poo.) - */</font> - Allocator allocator (<font color=#008888>Constants::PoolName</font>); - - <font color=red>/* - The Allocator class provides the pool() member so that you - have access to the actual memory pool. A more robust - implementation would behave more as a bridge class but this - is good enough for what we're doing here. - Once you have a reference to the pool, the malloc() method - can be used to get some bytes. If successful, shm will - point to the data. Otherwise, it will be zero. - */</font> - char *shm = (char *) allocator.pool ().malloc (27); - - ACE_ASSERT (shm != 0); - - <font color=red>/// FYI</font> - ACE_DEBUG ((LM_INFO, - "<font color=green>Shared memory is at 0x%x\n</font>", - shm)); - - <font color=red>/* - Something that we can do with a memory pool is map a name to - a region provided by malloc. By doing this, we can - communicate that name to the client as a rendezvous - location. Again, a member of Constants is used to keep the - client and server coordinated. - */</font> - if (allocator.pool ().bind(<font color=#008888>Constants::RegionName</font>,shm) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>Cannot bind the name '%s' to the pointer 0x%x\n</font>", - <font color=#008888>Constants::RegionName</font>, - shm), - 100); - - <font color=red>/* - One of the best ways to synch between different processes is - through the use of semaphores. ACE_SV_Semaphore_Complex - hides the gory details and lets us use them rather easily. - - Here, we'll create two semaphores: mutex and synch. mutex - will be used to provide mutually exclusive access to the - shared region for writting/reading. synch will be used to - prevent the server from removing the memory pool before the - client is done with it. - - Both semaphores are created in an initially locked state. - */</font> - - ACE_SV_Semaphore_Complex mutex; - ACE_ASSERT (mutex.open (<font color=#008888>Constants::SEM_KEY_1</font>, - <font color=#008888>ACE_SV_Semaphore_Complex::ACE_CREATE</font>, - 0) != -1); - - ACE_SV_Semaphore_Complex synch; - ACE_ASSERT (synch.open (<font color=#008888>Constants::SEM_KEY_2</font>, - <font color=#008888>ACE_SV_Semaphore_Complex::ACE_CREATE</font>, - 0) != -1); - - <font color=red>/* - We know the mutex is locked because we created it that way. - Take a moment to write some data into the shared region. - */</font> - for (int i = 0; i < <font color=#008888>Constants::SHMSZ</font>; i++) - shm[i] = <font color=#008888>Constants::SHMDATA</font>[i]; - - <font color=red>/* - The client will be blocking on an acquire() of mutex. By - releasing it here, the client can go look at the shared data. - */</font> - if (mutex.release () == -1) - ACE_ERROR ((LM_ERROR, - "<font color=green>(%P) %p</font>", - "<font color=green>server mutex.release</font>")); - <font color=red>/* - Even though we created the synch semaphore in a locked - state, if we attempt to acquire() it, we will block. Our - design requires that the client release() synch when it is - OK for us to remove the shared memory. - */</font> - else if (synch.acquire () == -1) - ACE_ERROR ((LM_ERROR, - "<font color=green>(%P) %p</font>", - "<font color=green>server synch.acquire</font>")); - <font color=red>/* - This will remove all of the memory pool's resources. In the - case where a memory mapped file is used, the physical file - will also be removed. - */</font> - if (allocator.pool ().remove () == -1) - ACE_ERROR ((LM_ERROR, - "<font color=green>(%P) %p\n</font>", - "<font color=green>server allocator.remove</font>")); - <font color=red>/* - We now have to cleanup the semaphores we created. Use the - ipcs command to see that they did, indeed, go away after the - server exits. - */</font> - - if (mutex.remove () == -1) - ACE_ERROR ((LM_ERROR, - "<font color=green>(%P) %p\n</font>", - "<font color=green>server mutex.remove</font>")); - else if (synch.remove () == -1) - ACE_ERROR ((LM_ERROR, - "<font color=green>(%P) %p\n</font>", - "<font color=green>server synch.remove</font>")); - return 0; -} - -<font color=red>/* - This tutorial was created by shamelessly modifying one of the ACE - examples. Someone there had already created the necessary explicit - template instantiations & I don't want them to go to waste... - */</font> -<font color=blue>#if defined</font> (<font color=purple>ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION</font>) -template class ACE_Malloc<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple>; -template class ACE_Malloc_T<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple, ACE_Control_Block>; -template class ACE_Guard<ACE_SV_Semaphore_Simple>; -template class ACE_Write_Guard<ACE_SV_Semaphore_Simple>; -template class ACE_Read_Guard<ACE_SV_Semaphore_Simple>; -<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_Malloc<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Malloc_T<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple, ACE_Control_Block> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Guard<ACE_SV_Semaphore_Simple> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Write_Guard<ACE_SV_Semaphore_Simple> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Read_Guard<ACE_SV_Semaphore_Simple> -<font color=blue>#endif</font> <font color=red>/* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */</font> - -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_SYSV_SHMEM */</font> -</PRE> -<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/021/page03.html b/docs/tutorials/021/page03.html deleted file mode 100644 index 03347b633c0..00000000000 --- a/docs/tutorials/021/page03.html +++ /dev/null @@ -1,150 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 021</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 021</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Pooling your memories</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> - The client side is a little simpler than the server. Mainly - because we don't try to delete the pool: - <ul> - <li>Create an Allocator to access the pool - <li>Find the named region - </ul> -<hr> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>mpool.h</font>" - -<font color=blue>#if defined</font>(<font color=purple>ACE_LACKS_SYSV_SHMEM</font>) -int -main (int, char *[]) -{ - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>System V Semaphores not available on this platform.\n</font>"),100); -} -#else <font color=red>// ACE_LACKS_SYSV_SHMEM</font> -int -main (int, char *[]) -{ - <font color=red>/* - Use the same pool name used by the server when we create our - Allocator. This assures us that we don't create a whole new - pool. - */</font> - Allocator allocator (<font color=#008888>Constants::PoolName</font>); - - <font color=red>/* - You can put anything in the memory pool. Not just the - character array we want. The find() method till, therefore, - return a void* that we will have to cast. - */</font> - void *region; - - <font color=red>/* - We use find() to locate a named region in the pool. This is - the counterpart to bind() used in the server. - Here, we go try to find the region that the server has created - and filled with data. If there was a problem getting the pool - or finding the region, we'll get back -1 from find(). - */</font> - if (allocator.pool ().find (<font color=#008888>Constants::RegionName</font>,region) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>Cannot find the name '%s'\n</font>", - <font color=#008888>Constants::RegionName</font>), - 100); - - <font color=red>/* - Since find() returns us a void*, we cast it here to the char* - that we want. - */</font> - char *shm = (char *) region; - - ACE_DEBUG ((LM_INFO, - "<font color=green>Shared memory is at 0x%x\n</font>", - shm)); - - <font color=red>/* - The same pair of semaphores as used by the server are created - here. We probably don't need the CREATE flag since the server - should have already done that. There may be some very small - windows, however, where the server would have created the - memory pool but not yet gotten to the semaphores. - */</font> - ACE_SV_Semaphore_Complex mutex; - ACE_ASSERT (mutex.open (<font color=#008888>Constants::SEM_KEY_1</font>, - <font color=#008888>ACE_SV_Semaphore_Complex::ACE_CREATE</font>, - 0) != -1); - - ACE_SV_Semaphore_Complex synch; - ACE_ASSERT (synch.open (<font color=#008888>Constants::SEM_KEY_2</font>, - <font color=#008888>ACE_SV_Semaphore_Complex::ACE_CREATE</font>, - 0) != -1); - - <font color=red>/* - It doesn't matter if we created 'mutex' or if the server did. - In either case, it was created in a locked state and we will - block here until somebody unlocks it. In our scenario, that - will have to be the server. - */</font> - if (mutex.acquire () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>(%P) client mutex.acquire</font>"), - 1); - - <font color=red>/* - Now that we know it is safe to access the data, we'll run - through and make sure that it contains what we think the server - supplied. - */</font> - for (int i = 0; i < <font color=#008888>Constants::SHMSZ</font>; i++) - ACE_ASSERT (<font color=#008888>Constants::SHMDATA</font>[i] == shm[i]); - - <font color=red>/* - Look back at the server. After filling the region, it will - attempt to acquire the lock on 'synch'. It will wait there - until we release() the semaphore. That will allow it to remove - the pool and cleanup. We can simply exit once we perform the - release. (Ok, a free() of the region would probably be polite...) - */</font> - if (synch.release () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "<font color=green>(%P) client synch.release</font>"), - 1); - - return 0; -} - -<font color=red>/* - Again, we have the necessary explicit template instantiations - because I based this on an ACE example instead of creating it from scratch. - */</font> -<font color=blue>#if defined</font> (<font color=purple>ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION</font>) -template class ACE_Malloc<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple>; -template class ACE_Malloc_T<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple, ACE_Control_Block>; -template class ACE_Guard<ACE_SV_Semaphore_Simple>; -template class ACE_Write_Guard<ACE_SV_Semaphore_Simple>; -template class ACE_Read_Guard<ACE_SV_Semaphore_Simple>; -<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_Malloc<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Malloc_T<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple, ACE_Control_Block> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Guard<ACE_SV_Semaphore_Simple> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Write_Guard<ACE_SV_Semaphore_Simple> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Read_Guard<ACE_SV_Semaphore_Simple> -<font color=blue>#endif</font> <font color=red>/* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */</font> - -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_SYSV_SHMEM */</font> -</PRE> -<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/021/page04.html b/docs/tutorials/021/page04.html deleted file mode 100644 index 2886b87e19e..00000000000 --- a/docs/tutorials/021/page04.html +++ /dev/null @@ -1,111 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 021</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 021</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Pooling your memories</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> - Everything common the server & client is kept here. In - particular, the Constants class where we keep the names & - semaphore keys. - <p> - The Allocator class is just a thin wrapper around - ACE_Malloc<> that moves some of the details out of the - application logic. -<hr> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>MPOOL_H</font> -<font color=blue>#define</font> <font color=purple>MPOOL_H</font> - -<font color=red>// Everything else we need is in this one header</font> -<font color=blue>#include</font> "<A HREF="../../../ace/Malloc.h">ace/Malloc.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_SYSV_SHMEM</font>) - -<font color=red>/* - With this we will abstract away some of the details of the memory - pool. Note that we don't treat this as a singleton because an - application may need more than one pool. Each would have a - different name and be used for different purposes. - */</font> - -class Allocator -{ -public: - <font color=red>// The pool name will be used to create a unique semaphore to</font> - <font color=red>// keep this pool separate from others.</font> - Allocator (const char * _name = "<font color=green>MemoryPool</font>"); - ~Allocator (void); - - typedef ACE_Malloc<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple> pool_t; - - <font color=red>// Provide an accessor to the pool. This will also allocate the</font> - <font color=red>// pool when first invoked.</font> - pool_t &pool (void); - -protected: - - <font color=red>// The name we gave to the pool</font> - char *name_; - - pool_t *pool_; -}; - -<font color=red>/* - The client and server need to agree on a certain set of values. By - placing them in the Constants class we can eliminate a bit of confusion. - */</font> -class Constants -{ -public: - <font color=red>// The semaphore keys are needed for the two semaphores that</font> - <font color=red>// synch access to the shared memory area.</font> - static const int SEM_KEY_1; - static const int SEM_KEY_2; - - <font color=red>// How big the pool will be and what we'll put into it. A real</font> - <font color=red>// app wouldn't need SHMDATA of course.</font> - static const int SHMSZ; - static const char *SHMDATA; - - <font color=red>// The name assigned to the memory pool by the server is needed</font> - <font color=red>// by the client. Without it, the pool cannot be found.</font> - <font color=red>// Likewise, the name the server will bind() to the region of the</font> - <font color=red>// pool must be available to the client.</font> - static const char *PoolName; - static const char *RegionName; -}; - -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_SYSV_SHMEM */</font> -<font color=blue>#endif</font> <font color=red>/* MPOOL_H */</font> -</PRE> -<HR> - The really hard stuff is done by the ACE_Malloc<> template. This - template takes two parameters.<sup>*</sup> The first is a - memory pool class to use. ACE has several, I've choosen one - that uses a memory-mapped file. The second parameter is a lock - class of some sort. This is needed so that the ACE_Malloc<> can - protect its internal data. Note that you still have to - provide your own mutex around the data you put into the - malloc'd area. - -<P> - * Actually, some implementations may require a different - number of parameters. - That's why ACE uses those funky macros. ACE_MMAP_MEMORY_POOL - for instance turns into ACE_MMAP_Memory_Pool on Linux but may - do other things on your platform. -<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/021/page05.html b/docs/tutorials/021/page05.html deleted file mode 100644 index c72b87ac570..00000000000 --- a/docs/tutorials/021/page05.html +++ /dev/null @@ -1,88 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 021</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 021</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Pooling your memories</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> -And here we have the implementation of the Allocator... -<hr> -<PRE> - -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>mpool.h</font>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_SYSV_SHMEM</font>) - -<font color=red>/* - Set the values of all of the constants. This guarantees that client - and server don't get confused. - */</font> -const int <font color=#008888>Constants::SEM_KEY_1</font> = ACE_DEFAULT_SEM_KEY + 1; -const int <font color=#008888>Constants::SEM_KEY_2</font> = ACE_DEFAULT_SEM_KEY + 2; - -const int <font color=#008888>Constants::SHMSZ</font> = 27; -const char * <font color=#008888>Constants::SHMDATA</font> = "<font color=green>abcdefghijklmnopqrstuvwxyz</font>"; - -const char * <font color=#008888>Constants::PoolName</font> = "<font color=green>SharedMemoryPool</font>"; -const char * <font color=#008888>Constants::RegionName</font> = "<font color=green>Alphabet</font>"; - -<font color=red>/* - We have to create a copy of the _name parameter in case the caller - has dynamically allocated it. The pool_ is set to NULL & will be - allocated by the accessor. - */</font> -<font color=#008888>Allocator::Allocator</font> (const char *_name) - : name_ (<font color=#008888>ACE_OS::strdup</font> (_name)), - pool_ (0) -{ - if (name_ == 0) - ACE_ERROR ((LM_ERROR, "<font color=green>(%P) %p</font>", - "<font color=green><font color=#008888>Allocator::Allocator</font> cannot strdup pool name</font>")); -} - -<font color=#008888>Allocator::~Allocator</font> (void) -{ - <font color=red>/* - strdup() uses malloc(), so we must use free() to clean up. - */</font> - if (name_) - <font color=#008888>ACE_OS::free</font> (name_); - - <font color=red>// delete doesn't really care if you give it a NULL pointer.</font> - delete pool_; -} - -<font color=red>/* - Allocate the pool. Since we return a reference, we'll be in really - bad shape if the new fails. This is a great place to throw an - exception! - The other concern is thread safety. If two threads call here at - about the same time, we may create the pool twice. We can't use a - Singleton because we want to have multiple Allocator instances. The - Singleton techniques can be used though. - */</font> - -<font color=#008888>Allocator::pool_t</font> & -<font color=#008888>Allocator::pool</font> (void) -{ - if (pool_ == 0) - pool_ = new pool_t (name_); - - return *pool_; -} - -<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_SYSV_SHMEM */</font> -</PRE> -<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/021/page06.html b/docs/tutorials/021/page06.html deleted file mode 100644 index 6fef55a7bbf..00000000000 --- a/docs/tutorials/021/page06.html +++ /dev/null @@ -1,34 +0,0 @@ -<!-- $Id$ --> -<HTML> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>ACE Tutorial 021</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 021</FONT></B></CENTER> - -<CENTER><B><FONT SIZE=+2>Pooling your memories</FONT></B></CENTER> - -<P> -<HR WIDTH="100%"> - As you can see, using a memory pool is really rather easy. The - most difficult part, as always, is with the synch mechanisms. - <P> - The other nice thing about ACE_Malloc<> is that you can swap - between System V shared memory and memory mapped files just by - changing the template parameters. The truly adventurous will - likely find a runtime way of doing this. - <p> - - <ul> - <li><A HREF="Makefile">Makefile</A> - <li><A HREF="server.cpp">server.cpp</A> - <li><A HREF="client.cpp">client.cpp</A> - <li><A HREF="mpool.h">mpool.h</A> - <li><A HREF="mpool.cpp">mpool.cpp</A> - </ul> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] </CENTER> - diff --git a/docs/tutorials/021/server.cpp b/docs/tutorials/021/server.cpp deleted file mode 100644 index 78e9e161171..00000000000 --- a/docs/tutorials/021/server.cpp +++ /dev/null @@ -1,158 +0,0 @@ - -// $Id$ - -/* - I've hidden the details in an Allocator class declared in mpool.h - We'll come to that a little later. -*/ -#include "mpool.h" - -#if defined(ACE_LACKS_SYSV_SHMEM) -int -main (int, char *[]) -{ - ACE_ERROR_RETURN ((LM_ERROR, - "System V Semaphores not available on this platform.\n"),100); -} -#else // ACE_LACKS_SYSV_SHMEM -int -main (int, char *[]) -{ - /* - Construction of an Allocator will create the memory pool and - provide it with a name. The Constants class is also - declared in mpool.h to keep server and client on the same - page. The name is used to generate a unique semaphore which - prevents simultaneous access to the pools housekeeping - information. (Note that you still have to provide your own - synch mechanisms for the data *you* put in the poo.) - */ - Allocator allocator (Constants::PoolName); - - /* - The Allocator class provides the pool() member so that you - have access to the actual memory pool. A more robust - implementation would behave more as a bridge class but this - is good enough for what we're doing here. - Once you have a reference to the pool, the malloc() method - can be used to get some bytes. If successful, shm will - point to the data. Otherwise, it will be zero. - */ - char *shm = (char *) allocator.pool ().malloc (27); - - ACE_ASSERT (shm != 0); - - /// FYI - ACE_DEBUG ((LM_INFO, - "Shared memory is at 0x%x\n", - shm)); - - /* - Something that we can do with a memory pool is map a name to - a region provided by malloc. By doing this, we can - communicate that name to the client as a rendezvous - location. Again, a member of Constants is used to keep the - client and server coordinated. - */ - if (allocator.pool ().bind(Constants::RegionName,shm) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "Cannot bind the name '%s' to the pointer 0x%x\n", - Constants::RegionName, - shm), - 100); - - /* - One of the best ways to synch between different processes is - through the use of semaphores. ACE_SV_Semaphore_Complex - hides the gory details and lets us use them rather easily. - - Here, we'll create two semaphores: mutex and synch. mutex - will be used to provide mutually exclusive access to the - shared region for writting/reading. synch will be used to - prevent the server from removing the memory pool before the - client is done with it. - - Both semaphores are created in an initially locked state. - */ - - ACE_SV_Semaphore_Complex mutex; - ACE_ASSERT (mutex.open (Constants::SEM_KEY_1, - ACE_SV_Semaphore_Complex::ACE_CREATE, - 0) != -1); - - ACE_SV_Semaphore_Complex synch; - ACE_ASSERT (synch.open (Constants::SEM_KEY_2, - ACE_SV_Semaphore_Complex::ACE_CREATE, - 0) != -1); - - /* - We know the mutex is locked because we created it that way. - Take a moment to write some data into the shared region. - */ - for (int i = 0; i < Constants::SHMSZ; i++) - shm[i] = Constants::SHMDATA[i]; - - /* - The client will be blocking on an acquire() of mutex. By - releasing it here, the client can go look at the shared data. - */ - if (mutex.release () == -1) - ACE_ERROR ((LM_ERROR, - "(%P) %p", - "server mutex.release")); - /* - Even though we created the synch semaphore in a locked - state, if we attempt to acquire() it, we will block. Our - design requires that the client release() synch when it is - OK for us to remove the shared memory. - */ - else if (synch.acquire () == -1) - ACE_ERROR ((LM_ERROR, - "(%P) %p", - "server synch.acquire")); - /* - This will remove all of the memory pool's resources. In the - case where a memory mapped file is used, the physical file - will also be removed. - */ - if (allocator.pool ().remove () == -1) - ACE_ERROR ((LM_ERROR, - "(%P) %p\n", - "server allocator.remove")); - /* - We now have to cleanup the semaphores we created. Use the - ipcs command to see that they did, indeed, go away after the - server exits. - */ - - if (mutex.remove () == -1) - ACE_ERROR ((LM_ERROR, - "(%P) %p\n", - "server mutex.remove")); - else if (synch.remove () == -1) - ACE_ERROR ((LM_ERROR, - "(%P) %p\n", - "server synch.remove")); - return 0; -} - -/* - This tutorial was created by shamelessly modifying one of the ACE - examples. Someone there had already created the necessary explicit - template instantiations & I don't want them to go to waste... - */ -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Malloc<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple>; -template class ACE_Malloc_T<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple, ACE_Control_Block>; -template class ACE_Guard<ACE_SV_Semaphore_Simple>; -template class ACE_Write_Guard<ACE_SV_Semaphore_Simple>; -template class ACE_Read_Guard<ACE_SV_Semaphore_Simple>; -#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate ACE_Malloc<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple> -#pragma instantiate ACE_Malloc_T<ACE_MMAP_MEMORY_POOL, ACE_SV_Semaphore_Simple, ACE_Control_Block> -#pragma instantiate ACE_Guard<ACE_SV_Semaphore_Simple> -#pragma instantiate ACE_Write_Guard<ACE_SV_Semaphore_Simple> -#pragma instantiate ACE_Read_Guard<ACE_SV_Semaphore_Simple> -#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ - -#endif /* ACE_LACKS_SYSV_SHMEM */ diff --git a/docs/tutorials/022/Acceptor_Service.cpp b/docs/tutorials/022/Acceptor_Service.cpp deleted file mode 100644 index aa4976cc228..00000000000 --- a/docs/tutorials/022/Acceptor_Service.cpp +++ /dev/null @@ -1,154 +0,0 @@ -// $Id$ - -#include "Acceptor_Service.h" -#include "ace/Dynamic_Service.h" - -#include "client_handler.h" - -/* 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 not what we want to focus on, - so we're taking the easy way out. */ - -static const u_short PORT = ACE_DEFAULT_SERVER_PORT; - -/* As in all our simple tutorials, our contructor also does nothing */ -Acceptor_Service::Acceptor_Service (void) -{ - // Constructor -} - -/* Same in the destructor case */ -Acceptor_Service::~Acceptor_Service (void) -{ - // Constructor -} - -/* This is the virtual method inherited from ACE_Service_Object. This - method is called to initialize the service. In a generic sense, we - initialize everything that is needed to initialize our service - here. Ofcourse we need to do that only if there are not already - initialized. One important point to note here is that we have to - make sure that everything that is initialized here is actually - removed when the service is shutdown */ -int -Acceptor_Service::init (int argc, char *argv[]) -{ - /* As you will see, we will not be using argc and argv here and - hence declare them to be unused variables. This helps us from the - complaints from the picky compilers about unused variables. */ - ACE_UNUSED_ARG (argc); - ACE_UNUSED_ARG (argv); - - /* Lets have a debug statement so that we can know that our - Acceptor_Service will be initialized soon */ - ACE_DEBUG ((LM_DEBUG, - "Starting the Acceptor_Service\n")); - - /* 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 "well known" addresses. If not, there - must be some mechanism by which the client is informed of the - server's address. */ - if (this->open (ACE_INET_Addr (PORT), - ACE_Reactor::instance ()) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "open"), - -1); - return 0; -} - -/* This virtual method will be invoked when we pass a directive to the - service configurator framework to remove our service. Remember the - threads and anything else that are initialized in the init - method and remove each of them. If we leave anything that we - initialized still running after this method is invoked ...well .. you - know what happens :-) */ -int -Acceptor_Service::fini (void) -{ - /* Lets have another debug statement to inform us the state of the - service. */ - ACE_DEBUG ((LM_DEBUG, - "Closing down the Acceptor_Service\n")); - - /* Now, lets see what did we start or initialize during the - initialization process. The only thing that we did was opening - our Acceptor to start listening for requests. So, lets close it - down. */ - this->close (); - - return 0; -} - -/* Now, lets see how we can suspend the service that we initialized - and is running. By suspension, we mean that the Reactor still knows - about the service and receives the requests. But, it just keeps - quite even if there are any requests. It actually queues the - requests and sends them to the service once it is resumed. */ -int -Acceptor_Service::suspend (void) -{ -/* You must be wondering, as I did, how we can simply suspend this - service without any complex method invocations. Thanks to our - ACE_Reactor class, we can actually suspend the service by just - invoking the following method and passing a pointer to ourself. - This method actually takes care of all the particulars for - suspending the services and keeps us happy. */ - ACE_Reactor::instance ()->suspend_handler (this); - return 0; -} - -int -Acceptor_Service::resume (void) -{ - /* I had the same question again ... how do I do this ?? As before, - our ACE_Reactor class came to a help with this method. ACE - classes do make life simpler .. don't they !! */ - ACE_Reactor::instance ()->resume_handler (this); - - return 0; -} - -/* The macro to be used to define the factory method and destructor - for our dynamically loadable service. */ -ACE_SVC_FACTORY_DEFINE (Acceptor_Service) - -/* This macro helps to register a statically linked service into the - service configurator. It is defined in ace/OS.h. All the parameters - needed by the service configurator to build and control the - statically linked servuce are configured in a single structure. An - instance of this structure is statically initialized using this - macro. The First parameter is SERVICE_CLASS i.e. the name of the - class that implements the service. As we did implicitly, this class - must derive from ACE_Service_Configurator. The second parameter is - the NAME of the service. This name is used by the service - configurator to match the configuration options provided in the - svc.conf file. The third parameter is the type of the object which - could be either streams or service objects. The next parameter is - the name of the factory function which we defined in our header - file and above using the macros ACE_FACTORY_DECLARE and - ACE_FACTORY_DEFINE. The fifth parameter are a set of options or - flags which are used to control the ownership and life cycle of the - object. The final argument helps us to choose if we want a new - thread for this service. If the argument is not 0, a thread will be - dedicated to this service. .. lots of parameters .. Huh !! */ -ACE_STATIC_SVC_DEFINE (Acceptor_Service, - ACE_TEXT ("Acceptor_Service"), - ACE_SVC_OBJ_T, - &ACE_SVC_NAME (Acceptor_Service), - ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ, - 0) - -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR>; -template class ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>; -#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> -#pragma instantiate ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> -#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/docs/tutorials/022/Acceptor_Service.h b/docs/tutorials/022/Acceptor_Service.h deleted file mode 100644 index a5512970746..00000000000 --- a/docs/tutorials/022/Acceptor_Service.h +++ /dev/null @@ -1,101 +0,0 @@ -//$Id$ - -#ifndef ACCEPTOR_SERVICE_H -#define ACCEPTOR_SERVICE_H -#include "ace/pre.h" - -/* The ACE_Acceptor<> template lives in the ace/Acceptor.h header - file. */ -#include "ace/Acceptor.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -/* Since we want to work with sockets, we'll need a SOCK_Acceptor to - allow the clients to connect to us. */ -#include "ace/SOCK_Acceptor.h" - -/* Pull in definition for ACE_Svc_Export. On Win32 platforms - this macro is used to export symbols from libraries. */ -#include "ace/svc_export.h" - -/* The Client_Handler object we develop will be used to handle clients - once they're connected. The ACE_Acceptor<> 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. */ -#include "client_handler.h" - -/* In our original simple server, we instantiated a - ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> object. We can - make it much simpler and efficient by inheriting our - Acceptor_Service from ACE_Acceptor itself. - - Our Acceptor_Service class also needs to inherit from - ACE_Service_Object. ACE_Service_Object is an abstract class which - includes methods called by the Service Configurator framework to - start, remove, suspend or resume our service. - - You might have noticed that we didnt explicitly inherit from - ACE_Service_Object here. That is because, ACE_Acceptor derives from - ACE_Service_Object and hence there is no need to specify it again. */ - -/* ACE_Svc_Export is a macro which on Win32 platforms exports from the - generated library the symbols for the following class. This allows - you to link to the library, and get the symbol definitions for the class. -*/ - - -class ACE_Svc_Export Acceptor_Service : public ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> -{ - public: - // Constructor - Acceptor_Service (void); - - // Destructor - ~Acceptor_Service (void); - - /* This method is the one which is called by the Service - Configurator Framework to initialize or start the service. */ - virtual int init (int argc, char *argv[]); - - /* Called by the Service Configurator framework to remove this - Service. */ - virtual int fini (void); - - /* You could easily guess that this method is called to suspend the - service by the same Service Configurator Framework. When in the - suspend mode, the service is not removed completely and is *still - there*. The difference is that the service is not in a active - state and doesnot accept requests.*/ - virtual int suspend (void); - - /* And your guess that this method is called to resume the service - is also not wrong. This call brings the service back to the - active state and the service is all ready to accept requests */ - virtual int resume (void); - -}; - -/* The following macros and similar macros which we will use in the - implementation file later are used to define helper functions for - the Service Configurator. As we can easily guess, these macros are - intended to dynamically load ancd configure services using the - svc.conf file. These macros will also help to dynamically configure - even the statically linked services. */ - -/* This macro is used to declare a data structure required to register a - statically linked service into the service configurator. As you can - see it has only one argument which is the name of the class that - implements this service... so Acceptor_Service in our case. */ -ACE_STATIC_SVC_DECLARE (Acceptor_Service) - -/* Once the service implementation is dynamically loaded, the Service - Configurator uses a factory method to create the object. This - macro declares such a factory function with the proper interface - and export macros. */ -ACE_SVC_FACTORY_DECLARE (Acceptor_Service) - -#include "ace/post.h" -#endif /* ACCEPTOR_SERVICE_H */ diff --git a/docs/tutorials/022/Makefile b/docs/tutorials/022/Makefile deleted file mode 100644 index c164a653cac..00000000000 --- a/docs/tutorials/022/Makefile +++ /dev/null @@ -1,105 +0,0 @@ -#---------------------------------------------------------------------------- -# $Id$ -#---------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -# You can generally find a Makefile in the ACE examples, tests or the library -# itself that will satisfy our application needs. This one was taken from -# one of the examples. - - # Define the name of the binary we want to create. There has to be - # a CPP file $(BIN).cpp but it doesn't necessarily have to have your - # main() in it. Most of the time, though, it will. -MAKEFILE = Makefile -BIN = server -LIBNAME = libAcceptor_Server -LIB = $(LIBNAME).a -SHLIB = $(LIBNAME).$(SOEXT) - # Few applications will have a single source file. We use the FILES - # macro to build up a list of additional files to compile. Notice - # that we leave off the extension just as with BIN -FILES = -FILES += Acceptor_Service client_handler - - # Here we use some GNU make extensions to build the SRC macro. Basically, - # we're just adding .cpp to the value of BIN and for each entry of the - # FILES macro. -PSRC = $(addsuffix .cpp,$(BIN)) -LSRC = $(addsuffix .cpp,$(FILES)) - -LDLIBS = - -LIBS += $(ACELIB) - - # The BUILD macro is used by the ACE makefiles. Basically, it tells - # the system what to build. I don't really know what VBIN is other - # than it is constructed from the value of BIN. Just go with it... -BUILD = $(VLIB) $(VSHLIB) $(SHLIBA) $(VBIN) - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - - # This is where the real power lies! These included makefile components - # are similar to the C++ templates in ACE. That is, they do a tremendous - # amount of work for you and all you have to do is include them. - # As a matter of fact, in our project, I created a single file named - # "app.mk" that includes all of these. Our project makefiles then just - # need to include app.mk to get everything they need. - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.lib.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- - - # Sometimes I like to reformat my code to make it more readable. This is - # more useful for the comments than anything else. Unfortunately, the - # "indent" program doesn't quite grok C++ so I have to post-process it's - # output just a bit. -Indent : # - for i in $(SRC) $(HDR) ; do \ - indent -npsl -l80 -fca -fc1 -cli0 -cdb < $$i | \ - sed -e 's/: :/::/g' \ - -e 's/^.*\(public:\)/\1/' \ - -e 's/^.*\(protected:\)/\1/' \ - -e 's/^.*\(private:\)/\1/' \ - -e 's/:\(public\)/ : \1/' \ - -e 's/:\(protected\)/ : \1/' \ - -e 's/:\(private\)/ : \1/' \ - > $$i~ ;\ - mv $$i~ $$i ;\ - done - - # One of the targets in the ACE makefiles is "depend". It will invoke - # your compiler in a way that will generate a list of dependencies for - # you. This is a great thing! Unfortunately, it puts all of that mess - # directly into the Makefile. I prefer my Makefile to stay clean and - # 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 - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Dependencies -#---------------------------------------------------------------------------- - - # Don't put anything below here. Between the "depend" target and fix.Makefile - # it's guaranteed to be lost! diff --git a/docs/tutorials/022/client/Makefile b/docs/tutorials/022/client/Makefile deleted file mode 100644 index 0bfc82e3bd5..00000000000 --- a/docs/tutorials/022/client/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -#---------------------------------------------------------------------------- -# $Id$ -# -# Makefile for client logging applications -#---------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = client - -LSRC = $(addsuffix .cpp,$(BIN)) - -VLDLIBS = $(LDLIBS:%=%$(VAR)) - -BUILD = $(VBIN) - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - - -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) hdr bodies *.pre *.pst - -UNSHAR : # - sh combine.shar - -CLEAN : realclean - $(RM) hdr bodies *.pre *.pst .depend - -#---------------------------------------------------------------------------- -# Local targets -#---------------------------------------------------------------------------- diff --git a/docs/tutorials/022/client/client.cpp b/docs/tutorials/022/client/client.cpp deleted file mode 100644 index 54bcbc04fa0..00000000000 --- a/docs/tutorials/022/client/client.cpp +++ /dev/null @@ -1,216 +0,0 @@ -// $Id$ - -/* We need the connector object & we also bring in a simple string - class. */ -#include "ace/Log_Msg.h" -#include "ace/SOCK_Connector.h" -#include "ace/SString.h" - -/* In this tutorial, we extend SOCK_Stream by adding a few wrappers - around the send_n() method. */ -class Client : public ACE_SOCK_Stream -{ -public: - // Basic constructor - Client (void); - - /* Construct and open() in one call. This isn't generally a good - idea because you don't have a clean way to inform the caller when - open() fails. (Unless you use C++ exceptions.) */ - Client (const char *server, - u_short port); - - /* Open the connection to the server. Notice that this mirrors the - use of ACE_SOCK_Connector. By providing our own open(), we can - hide the connector from our caller & make it's interaction easier. */ - int open (const char *server, - u_short port); - - /* These are necessary if you're going to use the constructor that - invokes open(). */ - int initialized (void) { return initialized_; } - int error (void) { return error_; } - - /* This is where the coolness lies. Most C++ folks are familiar - 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. */ - Client &operator<< (ACE_SString &str); - Client &operator<< (char *str); - Client &operator<< (int n); - -protected: - u_char initialized_; - u_char error_; -}; - -/* The basic constructor just sets our flags to reasonable values. */ -Client::Client(void) -{ - initialized_ = 0; - error_ = 0; -} - -/* This constructor also sets the flags but then calls open(). If the - open() fails, the flags will be set appropriately. Use the two - inline method calls initialized() and error() to check the object - state after using this constructor. */ -Client::Client (const char *server, - u_short port) -{ - initialized_ = 0; - error_ = 0; - this->open (server, port); -} - -/* Open a connection to the server. This hides the use of - ACE_SOCK_Connector from our caller. Since our caller probably - doesn't care *how* we connect, this is a good thing. */ -int -Client::open (const char *server, - u_short port) -{ - /* This is right out of Tutorial 3. The only thing we've added is - to set the initialized_ member variable on success. */ - - ACE_SOCK_Connector connector; - ACE_INET_Addr addr (port, server); - - if (connector.connect (*this, addr) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "open"), - -1); - initialized_ = 1; - return 0; -} - -/* The first of our put operators sends a simple string object to the - peer. */ -Client & -Client::operator<< (ACE_SString &str) -{ - /* We have to be able to allow: server << foo << bar << stuff; - - To accomplish that, every << operator must check that the object - is in a valid state before doing work. */ - - if (initialized () && !error ()) - { - /* Get the actual data held in the string object */ - const char *cp = str.fast_rep (); - - /* Send that data to the peer using send_n() as before. If we - have a problem, we'll set error_ so that subsequent << - operations won't try to use a broken stream. */ - if (this->send_n (cp, - ACE_OS::strlen (cp)) == -1) - error_ = 1; - } - else - /* Be sure that error_ is set if somebody tries to use us when - we're not initialized. */ - error_ = 1; - - /* We have to return a reference to ourselves to allow chaining of - put operations (eg -- "server << foo << bar"). Without the - reference, you would have to do each put operation as a statement. - That's OK but doesn't have the same feel as standard C++ - iostreams. */ - return *this ; -} - -/* How do you put a char*? We'll take an easy way out and construct -an ACE_SString from the char* and then put that. It would have been -more efficient to implement this with the body of the -operator<<(ACE_SString&) method and then express that method in terms -of this one. There's always more than one way to do things! */ - -Client & -Client::operator<< (char *str) -{ - ACE_SString newStr (str); - - *this << newStr; - - return *this ; - - /* Notice that we could have been really clever and done: - - return *this << ACE_SString (str); - - That kind of thing just makes debugging a pain though! */ -} - -/* ACE_SString and char* are both about the same thing. What do you - do about different datatypes though? - - Do the same thing we did with char* and convert it to ACE_SString - where we already have a << operator defined. */ -Client & -Client::operator<< (int n) -{ - /* Create a character buffer large enough for the largest number. - That's a tough call but BUFSIZ should be quite enough. */ - char buf[BUFSIZ]; - - /* Put the number into our buffer... */ - ACE_OS::sprintf (buf, - "(%d)\n", - n); - - /* And create the ACE_SString that we know how to put. */ - ACE_SString newStr (buf); - - /* Send it and... */ - *this << newStr; - - /* return ourselves as usual. */ - return *this; -} - -/* Now we pull it all together. Like Tutorial 3, we'll allow command - line options. */ -int -main (int argc, char *argv[]) -{ - const char *server_host = argc > 1 ? argv[1] : ACE_DEFAULT_SERVER_HOST; - u_short server_port = argc > 2 ? ACE_OS::atoi (argv[2]) : ACE_DEFAULT_SERVER_PORT; - int max_iterations = argc > 3 ? ACE_OS::atoi (argv[3]) : 4; - - /* Use the basic constructor since the other isn't really very safe. */ - 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 (peer.open (server_host, - server_port) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "open"), - -1); - - for (int i = 0; i < max_iterations; i++) - { - /* Tell the server which iteration we're on. No more mucking - aroudn with sprintf at this level! It's all hidden from us. */ - peer << "message = " << i+1; - - /* Everything OK? */ - if (peer.error ()) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "send"), - -1); - else - ACE_OS::sleep (1); - } - - if (peer.close () == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "close"), - -1); - return 0; -} diff --git a/docs/tutorials/022/client_handler.cpp b/docs/tutorials/022/client_handler.cpp deleted file mode 100644 index d1e51f0833c..00000000000 --- a/docs/tutorials/022/client_handler.cpp +++ /dev/null @@ -1,225 +0,0 @@ -// $Id$ - -/* 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. - - We know that including client_handler.h is redundant because - client_acceptor.h includes it. Still, the sentry prevents - double-inclusion from causing problems and it's sometimes good to - be explicit about what 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" - -/* 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) -{ -} - -/* 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) -{ - // Make sure that our peer closes when we're deleted. This - // will probably happened when the peer is deleted but it - // doesn't hurt to be explicit. - this->peer ().close (); -} - -/* 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) -{ - /* 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! */ - this->reactor ()->remove_handler (this, - ACE_Event_Handler:: READ_MASK | ACE_Event_Handler::DONT_CALL); - - /* 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. */ - delete this; -} - -/* 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) -{ - /* Convert the void* to a Client_Acceptor*. You should probably use - those fancy ACE_*_cast macros 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. */ - Client_Acceptor *acceptor = (Client_Acceptor *) _acceptor; - - /* Our reactor reference will be set when we register ourselves but - I decided to go ahead and set it here. No good reason really... */ - this->reactor (acceptor->reactor ()); - - /* 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. */ - ACE_INET_Addr addr; - - /* 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 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 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. */ - if (this->peer ().get_remote_addr (addr) == -1) - return -1; - - /* 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 any case, the test above should - always be done to ensure that the connection is worth keeping. - - 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 correct thing to do. */ - if (this->reactor ()->register_handler (this, - ACE_Event_Handler::READ_MASK) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "(%P|%t) can't register with reactor\n"), - -1); - - /* 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 ())); - - /* Always return zero on success. */ - return 0; -} - -/* 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) -{ - /* Some compilers don't like it when you fail to use a parameter. - This macro will keep 'em quiet for you. */ - ACE_UNUSED_ARG (handle); - - /* 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. */ - char buf[BUFSIZ]; - - /* 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. */ - return this->process (buf, sizeof (buf)); -} - -/* 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) -{ - ACE_UNUSED_ARG (handle); - ACE_UNUSED_ARG (mask); - - delete this; - return 0; -} - -/* 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) -{ - ssize_t bytes_read = -1; - - /* 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 something wrong has happened. The - reactor wouldn't have called us if there wasn't some kind of read - activity but there wouldn't be activity if there were no bytes to - read... - - On the other hand, if we got some data then we can display it in - a debug message for everyone to see. */ - switch ( (bytes_read = 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 - // NULL-terminate the string before printing it. - rdbuf[bytes_read] = 0; - ACE_DEBUG ((LM_DEBUG, - "(%P|%t) from client: %s", - rdbuf)); - } - - /* It's also worth mentioning that recv() has a cousin: recv_n(). - recv_n() will receive exactly the number of bytes you provide it. - This is very good when you know exactly how much you expect to - receive. For the application here, unfortunately, we don't have - any idea how much the client will be sending. recv() will read - up-to-but-not-more-than the number of bytes we specify (e.g. -- - _rdbuf_len). That works well when we don't know how much the - client will provide. */ - - return 0; -} diff --git a/docs/tutorials/022/client_handler.h b/docs/tutorials/022/client_handler.h deleted file mode 100644 index 03d3b1a8e10..00000000000 --- a/docs/tutorials/022/client_handler.h +++ /dev/null @@ -1,100 +0,0 @@ -// $Id$ - -#ifndef CLIENT_HANDLER_H -#define CLIENT_HANDLER_H - -/* 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 derive our Client_Handler directly from - ACE_Event_Handler but you still have to have an ACE_SOCK_Stream for - the actual connection. With a direct derivative of - ACE_Event_Handler, you'll have to contain and maintain an - 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. */ - -#include "ace/Svc_Handler.h" - -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ - -#include "ace/SOCK_Stream.h" - -/* Another feature of ACE_Svc_Handler is it's ability to present the - ACE_Task<> interface as well. That's what the ACE_NULL_SYNCH - parameter below is all about. That's beyond our scope here but - we'll come back to it in the next tutorial when we start looking at - concurrency options. */ -class Client_Handler : public ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> -{ -public: - // Constructor... - Client_Handler (void); - - /* 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. */ - void destroy (void); - - /* 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 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 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 definition of open() - you'll see how we get around that. */ - int open (void *acceptor); - - /* 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 clean itself - up. Since an event handler can be registered for more than one - type of callback, the callback mask is provided to inform - handle_close() exactly which method failed. That way, you don't - have to maintain state information between your handle_* method - calls. The <handle> parameter is explained below... 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); - -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 _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 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 <handle> would - be important to us for reading the client's data. */ - int handle_input (ACE_HANDLE handle); - - /* 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 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. */ - int process (char *rdbuf, int rdbuf_len); - - /* 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. */ - ~Client_Handler (void); -}; - -#endif /* CLIENT_HANDLER_H */ diff --git a/docs/tutorials/022/page01.html b/docs/tutorials/022/page01.html deleted file mode 100644 index 4bbb6ff8c40..00000000000 --- a/docs/tutorials/022/page01.html +++ /dev/null @@ -1,40 +0,0 @@ -<!-- $Id$ --> -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> -<html> - <head> - <title>ACE Tutorial 022</title> - </head> - - <BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 022</FONT></B></CENTER> -<CENTER> <h1>Using Service Configurator Framework</h1> </CENTER> - - <P>When building distributed systems, there will almost certainly - be multiple processes or services running at all - times. It is helpful if these services can (re)configured and - control at installation-time or run-time. In this tutorial, we - illustrate how to configure services in a fine-grained manner, - rather than having to stop and restart all services in an application. </P> - - <P>The examples we show are based on the <A HREF="http://www.cs.wustl.edu/~schmidt/POSA/">Component Configurator</A> pattern, - which enables a service to be started, removed, suspended or resumed - dynamically. This pattern decouples the implementation of a - service from its (re)configuration. Thus, new services can be added or unnecessary services - can be suspended or removed.</P> - - <P>In this tutorial, we will use the simple server and client - which we developed and used in our tutorial 005 as the base and - modify it as needed.</P> - <P> - <P><HR WIDTH="100%"> - <CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page02.html">Continue This Tutorial</A>]</CENTER> - - <hr> - <address><a href="mailto:pgontla@ece.uci.edu">Priyanka Gontla</a></address> -<!-- Created: Thu Dec 28 14:19:26 PST 2000 --> -<!-- hhmts start --> -Last modified: Sat Jan 20 10:18:42 CST 2001 -<!-- hhmts end --> - </body> -</html> diff --git a/docs/tutorials/022/page02.html b/docs/tutorials/022/page02.html deleted file mode 100644 index 144a28112fd..00000000000 --- a/docs/tutorials/022/page02.html +++ /dev/null @@ -1,98 +0,0 @@ -<!-- $Id$ --> -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> -<html> - <head> - <title>ACE Tutorial 022</title> - </head> - - <BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 022</FONT></B></CENTER> - We begin with <a href="server.cpp">server.cpp</a> - <UL> - <P>Abstract: - - We begin with the server and the acceptor which we developed in - our ACE Tutorial 005. We modify these and add new - implementation files so as to make the acceptor service dynamically - (un)loadable. What we want to do is separate the implementation - of the service from its configuration. So, our server will - now just act as a daemon waiting for requests. - We again enroll the services of the ACE_Reactor to handle - events. Everything occurs in a single thread. <P> - - This tutorial helps us learn apply the service configurator - pattern and make services dynamically configurable. In that - process, we are trying to make the acceptor we have developed - previously as a dynamically configurable service. - </UL> - <P> - <HR WIDTH="100%"> - <P> - <PRE> - <font color=red>/* We try to keep the server much simpler than before and - remove any thing related to the acceptor from the main (). - This lets keep the server running irrespective of the - state of the acceptor service. */ - </font> - <font color=red>/* As always, we would need the - ACE_Service_Config to help run the server as a daemon. */ </font> - <font color=blue>#include </font><font color=green>"ace/Service_Config.h"</font> - - <font color=red>/* Since we are seperating the acceptor service class from the - server, we need to declare our Acceptor_Service */ </font> - <font color=blue>#include </font><font color=green>"Acceptor_Service.h"</font> - - int - main (int argc, char *argv []) - { - <font color=red> - /* Perform daemon services update ... this opens the svc.conf - file and reads the entries present in the svc.conf - file. We will later learn the syntax of making an entry - into a svc.conf file. But for now, remember that this is a - file which has the entries to load or unload a service - dynamically or statically. */ - - In case, the function call returns a (-1), which is - indicative of an error, we print out a debug statement - and return (-1) to indicate an failure.</font> - if (ACE_Service_Config::open (argc, - argv, - ACE_DEFAULT_LOGGER_KEY, - 0) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "ACE_Service_Config::open"), - -1); - - <font color=red> - /* Install our signal handler. As we already know, you can actually - register signal handlers with the reactor. You might do that - when the signal handler is responsible for performing "real" - 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, SIGHUP); - - <font color=red> - /* Start running the event loop so that it - listens for events and acts accordingly. This event loop will run - either the event loop is ended explicitly or an error - occurs. */ </font> - ACE_Reactor::run_event_loop (); - - <font color=red>/* NOT REACHED */</font> - } -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page03.html">Continue This Tutorial</A>]</CENTER> - - <hr> - <address><a href="mailto:pgontla@ece.uci.edu">Priyanka Gontla</a></address> -<!-- Created: Thu Dec 28 15:17:34 PST 2000 --> -<!-- hhmts start --> -Last modified: Sat Jan 20 10:19:22 CST 2001 -<!-- hhmts end --> - </body> -</html> diff --git a/docs/tutorials/022/page03.html b/docs/tutorials/022/page03.html deleted file mode 100644 index 4a095ae9a8f..00000000000 --- a/docs/tutorials/022/page03.html +++ /dev/null @@ -1,123 +0,0 @@ -<!-- $Id$ --> -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> -<html> - <head> - <title>ACE Tutorial 022</title> - </head> - - <BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 022</FONT></B></CENTER> - Now, lets implement the Acceptor Service. As the first step, let - us take a look at <I><A HREF="Acceptor_Service.h">Acceptor_Service.h</A></I>. - -<P> -<HR WIDTH="100%"> -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#ifndef</font> <font color=purple>ACCEPTOR_SERVICE_H</font> -<font color=blue>#define</font> <font color=purple>ACCEPTOR_SERVICE_H</font> - -<font color=red>/* The ACE_Acceptor<> template lives in the ace/Acceptor.h header - file. */</font> - -<font color=blue>#include</font> "<A HREF="../../../ace/Acceptor.h">ace/Acceptor.h</A>" - -<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) -<font color=blue># pragma</font> <font color=purple>once</font> -<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> "<A HREF="../../../ace/SOCK_Acceptor.h">ace/SOCK_Acceptor.h</A>" - -<font color=red>/* The Client_Handler object we develop will be used to handle clients - once they're connected. The ACE_Acceptor<> 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>/* In our original simple server, we instantiated a - ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> object. We can - make it much simpler and efficient by inheriting our - Acceptor_Service from ACE_Acceptor itself. - - Our Acceptor_Service class also needs to inherit from - ACE_Service_Object. ACE_Service_Object is an abstract class which - includes methods called by the Service Configurator framework to - start, remove, suspend or resume our service. - - You might have noticed that we didnt explicitly inherit from - ACE_Service_Object here. That is because, ACE_Acceptor derives from - ACE_Service_Object and hence there is no explicitly specify it. */ - - /* TO Do: Describe what/why ACE_Svc_Export */ - We use the ACE_Svc_Export macro to export the symbols from the -library on Win.</font> -class ACE_Svc_Export Acceptor_Service : public ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> -{ - public: - <font color=red> // Constructor </font> - Acceptor_Service (void); - - <font color=red> // Destructor </font> - ~Acceptor_Service (void); - - <font color=red>/* This method is the one which is called by the Service - Configurator Framework to initialize or start the service. */ </font> - virtual int init (int argc, char *argv[]); - - <font color=red>/* Called by the Service Configurator framework to remove this - Service. */ </font> - virtual int fini (void); - - <font color=red>/* You could easily guess that this method is called to suspend the - service by the same Service Configurator Framework. When in the - suspend mode, the service is not removed completely and is *still - there*. The difference is that the service is not in a active - state and doesnot accept requests.*/ </font> - virtual int suspend (void); - - <font color=red> /* And your guess that this method is called to resume the service - is also right. This call brings the service back to the - active state and the service is all ready to accept requests */ </font> - virtual int resume (void); - -}; - -<font color=red>/* The following macros and similar macros which we - will use in the implementation file later are used to define helper - functions for the Service Configurator. As we can easily guess, these - macros are intended to dynamically load ancd configure services using - the svc.conf file. These macros will also help to dynamically configure - even the statically linked services. */</font> - -<font color=red>/* This macro is used to declare a data structure - required to register a statically linked service into the service - configurator. As you can see it has only one argument which is the - name of the class that implements this service... so - Acceptor_Service in our case. */</font> -ACE_STATIC_SVC_DECLARE (Acceptor_Service) - -<font color=red>/* Once the service implementation is dynamically loaded, the Service - Configurator uses a factory method to create the object. This - macro declares such a factory function with the proper interface - and export macros. */</font> -ACE_SVC_FACTORY_DECLARE (Acceptor_Service) - -#include "ace/post.h" -<font color=blue>#endif</font> <<font color=red> /* ACCEPTOR_SERVICE_H */</font> -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page04.html">Continue This Tutorial</A>]</CENTER> - - <hr> - <address><a href="mailto:pgontla@ece.uci.edu">Priyanka Gontla</a></address> -<!-- Created: Thu Jan 18 17:46:58 PST 2001 --> -<!-- hhmts start --> -Last modified: Fri Jan 19 11:38:39 PST 2001 -<!-- hhmts end --> - </body> -</html> diff --git a/docs/tutorials/022/page04.html b/docs/tutorials/022/page04.html deleted file mode 100644 index eae9d24fef4..00000000000 --- a/docs/tutorials/022/page04.html +++ /dev/null @@ -1,177 +0,0 @@ -<!-- $Id$ --> -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> -<html> - <head> - <title>ACE Tutorial 022</title> - </head> - - <BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 022</FONT></B></CENTER> -<pre> -<font color=red>/* Now that we know the interface, lets proceed to its - implementation. We obviosuly want to include the corresponding header - file. */</font> -<font color=blue>#include</font> "<A - HREF="Acceptor_Service.h">Acceptor_Service.h</A>" - -<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 not 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>/* As in all our simple tutorials, our contructor also does nothing */</font> -Acceptor_Service::Acceptor_Service (void) -{ - <font color=red>// Constructor</font> -} - -<font color=red>/* Same in the destructor case */</font> -Acceptor_Service::~Acceptor_Service (void) -{ - <font color=red>// Destructor</font> -} - -<font color=red>/* This is the virtual method inherited from ACE_Service_Object. This - method is called to initialize the service. In a generic sense, we - initialize everything that is needed to initialize our service - here. Ofcourse we need to do that only if there are not already - initialized. One important point to note here is that we have to - make sure that everything that is initialized here is actually - removed when the service is shutdown */</font> -int -Acceptor_Service::init (int argc, char *argv[]) -{ - <font color=red>/* As you will see, we will not be using argc and - argv here and hence declare them to be unused variables. This - helps us from the complaints from the picky compilers about - unused variables. */</font> - ACE_UNUSED_ARG (argc); - ACE_UNUSED_ARG (argv); - - <font color=red>/* Lets have a debug statement so that we can know that our - Acceptor_Service will be initialized soon */</font> - ACE_DEBUG ((LM_DEBUG, - "Starting the Acceptor_Service\n")); - - <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 "well known" addresses. If not, there - must be some mechanism by which the client is informed of the - server's address. */</font> - if (this->open (ACE_INET_Addr (PORT), - ACE_Reactor::instance ()) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "open"), - -1); - return 0; -} - -<font color=red>/* This virtual method will be invoked when we pass - a directive to the service configurator framework to remove - our service. Remember the threads and anything else that are - initialized in the init method and remove each of them. If we - leave anything that we initialized still running after this - method is invoked ...well .. you know what happens :-) */ </font> -int -Acceptor_Service::fini (void) -{ - <font color=red> /* Lets have another debug statement to inform us the state of the - service. */</font> - ACE_DEBUG ((LM_DEBUG, - "Closing down the Acceptor_Service\n")); - - <font color=red> /* Now, lets see what did we start or initialize during the - initialization process. The only thing that we did was opening - our Acceptor to start listening for requests. So, lets close it - down. */</font> - this->close (); - - return 0; -} - - <font color=red>/* Now, lets see how we can suspend the service that we initialized - and is running. By suspension, we mean that the Reactor still knows - about the service and receives the requests. But, it just keeps - quite even if there are any requests. It actually queues the - requests and sends them to the service once it is resumed.*/</font> -int -Acceptor_Service::suspend (void) -{ - <font color=red>/* You must be wondering, as I did, how we can simply suspend this - service without any complex method invocations. Thanks to our - ACE_Reactor class, we can actually suspend the service by just - invoking the following method and passing a pointer to ourself. - This method actually takes care of all the particulars for - suspending the services and keeps us happy. */</font> - ACE_Reactor::instance ()->suspend_handler (this); - return 0; -} - -int -Acceptor_Service::resume (void) -{ - <font color=red> /* I had the same question again ... how do I do this ?? As before, - our ACE_Reactor class came to a help with this method. ACE - classes do make life simpler .. don't they !! */</font> - ACE_Reactor::instance ()->resume_handler (this); - - return 0; -} - -<font color=red>/* The macro to be used to define the factory method - and destructor for our dynamically loadable service. */ </font> -ACE_SVC_FACTORY_DEFINE (Acceptor_Service) - -<font color=red>/* This macro helps to register a statically linked - service into the service configurator. It is defined in ace/OS.h. All - the parameters needed by the service configurator to build and control the - statically linked servuce are configured in a single structure. An - instance of this structure is statically initialized using this - macro. The First parameter is SERVICE_CLASS i.e. the name of the - class that implements the service. As we did implicitly, this class - must derive from ACE_Service_Configurator. The second parameter is - the NAME of the service. This name is used by the service - configurator to match the configuration options provided in the - svc.conf file. The third parameter is the type of the object which - could be either streams or service objects. The next parameter is - the name of the factory function which we defined in our header - file and above using the macros ACE_FACTORY_DECLARE and - ACE_FACTORY_DEFINE. The fifth parameter are a set of options or - flags which are used to control the ownership and life cycle of the - object. The final argument helps us to choose if we want a new - thread for this service. If the argument is not 0, a thread will be - dedicated to this service. .. lots of parameters .. Huh !! */ </font> -ACE_STATIC_SVC_DEFINE (Acceptor_Service, - ACE_TEXT ("Acceptor_Service"), - ACE_SVC_OBJ_T, - &ACE_SVC_NAME (Acceptor_Service), - ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ, - 0) - -#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR>; -template class ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>; -#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) -#pragma instantiate ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> -#pragma instantiate ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> -#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ -</PRE> -<P><HR WIDTH="100%"> -<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page05.html">Continue This Tutorial</A>]</CENTER> - <hr> - <address><a href="mailto:pgontla@ece.uci.edu">Priyanka Gontla</a></address> -<!-- Created: Thu Jan 18 18:24:15 PST 2001 --> -<!-- hhmts start --> -Last modified: Fri Jan 19 11:37:49 PST 2001 -<!-- hhmts end --> - </body> -</html> diff --git a/docs/tutorials/022/page05.html b/docs/tutorials/022/page05.html deleted file mode 100644 index 5b14622b2c4..00000000000 --- a/docs/tutorials/022/page05.html +++ /dev/null @@ -1,130 +0,0 @@ -<!-- $Id$ --> -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> -<html> - <head> - <title>ACE Tutorial 022</title> - </head> - - <BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<CENTER><B><FONT SIZE=+2>ACE Tutorial 022</FONT></B></CENTER> - <p>So, by now we have implemented our Acceptor Service: known how to - initialize, remove, suspend and resume our service. We have the - server daemon set up to run to accept requests. The only thing - that is left is the client_handler. We need to declare and define - the Client_Handler object. We will use the same <I><A - HREF="../005/Client_Handler.h">Client_Handler.h</A></I> and - <I><A HREF="../005/Client_Hander.cpp">Client_Handler.cpp</A></I> - that we used in our ACE Tutorial 005.</p> - - <p>With this, we are done with everything that we want to get our - Acceptor Service dynamically configurable in addition to the - actual functionality of the Acceptor.</p> - - <p>To compile, we can use the same <I><A - HREF="../005/Makefile">Makefile</A></I> that we used - previously and make appropriate changes for the new files that - we added. You could use this <I><A HREF="Makefile">Makefile</A></I> - - <p>Now, lets compile it and be all set to configure our Acceptor - Service. Let us run our server to start acting as a daemon and - accept requests.</p> - - <pre>$ ./server </pre> - - <p>Obviously, we will want to load our service dynamically and see - if our Acceptor Service is running as we want it to. For this, - we need to make an entry in the svc.conf file. - - <p>The Service Configurator framework reads the entries in the - svc.conf file in the working directory by default. According to - the entries in the svc.con file, the framework does the - needful. You could use a different name for the file like - server.conf but in that case, we need to explicitly specify to - the application the configuration file that has to be read using - the <I>-ORBSvcconf</I> option. - - <p>Coming back to where we were, now we want to make an entry in - this svc.conf file to load our service. I will show you the - general format for this entry and then we will make our entry.</p> - - A dynamic service could be initialized as: - <pre>dynamic service_name type_of_service * location_of_shared_lib:name_of_object "parameters" </pre> - - and a static service is initialized as: -<pre> static service_name "parameters_sent_to_service_object" </pre> - - <p>Lets start making our entry. The first keyword specifies if this - is a dynamic service or a static one. Since we want our service - to be a dynamically configurable one, the first parameter in our - entry will be <I>dynamic</I>. The next parameter is the name of - the service that we want to be loaded. This is the same name - that we specified in the ACE_STATIC_SVC_DEFINE macro. Since our - service name is Acceptor_Service, that becomes the second - parameter of our entry. The next argument is the type of the - service .. as we know already, there are two options: - Stream or Service_Object. And, we declared our service to be a - <I>Service_Object</I> in the ACE_STATIC_SVC_DEFINE macro. So, that - becomes the next parameter. The next entry is the location of - the shared library which has our service and that is - Acceptor_Server according to our Makefile. The next parameter is - the name of the object and finally the list of parameters that - we want to pass to our service. So, we are now erady to make our - entry in the svc.conf file to initialize our service. - -<pre> dynamic Acceptor_Service Service_Object * ./Acceptor_Server:_make_Acceptor_Service () "" </pre> - - <p>Now, we want to reconfigure so that our service will be - initialized. This could be done by sending a signal which would - be received eventually by the Reactor listening for requests and - it would invoke the ACE_Service::reconfigure () method which - does the reconfiguration of the services. - - <pre>$ kill -1 PID_of_our_server </pre> - - Now, that we know how to initialize our service and actually - initialized the service .. we could check if our service is - working good. Ofcourse, the debug statements we left in the init - method would help .. but to double check !! For this purpose, we - can use the simple client which we used in our ACE Tutorial - 005. Just compile the <I><A - HREF="client/client.cpp">client.cpp</A></I> using this <A - HREF="client/Makefile">Makefile</A> and run it. You can see the - responses from the service. - - <p>Now, we can check if we can suspend and resume and finally - remove the service. The entries for these functionalities are - very simple unlike the initialization entry. - - <pre>$ suspend Acceptor_Service </pre> - <pre>$ resume Acceptor_Service </pre> - <pre>$ remove Acceptor_Service </pre> - - <p>Lets first suspend the service by commenting out the entry for - the initialization and making the new entry for suspension in - the svc.conf file. Now, send a signal as before. The Reactor - will receive this event and suspend the service. Just to double - check, you could run our client again and see the response. </p> - - <p>Now, to resume the service, the procedure is the same. Comment - out other entries and make the entry for the resumption of the - service. And finally, send a signal. Again, you could run the - client and see what is happening. But, even before running the - client, you must have noticed that as soon as you resumed the - service, you saw some response from the Acceptor_Service. This - is because, as I explained before, the Reactor will queue the - request when the service is in suspension mode and send the - service the queued requests as and when it is active again. - - <p>Finally, lets remove our service. - - <p>So, now we know how to implement a dynamically configurable - service and how to dynamically configure the service. </p> - <hr> - <address><a href="mailto:pgontla@ece.uci.edu">Priyanka Gontla</a></address> -<!-- Created: Fri Jan 19 10:19:46 PST 2001 --> -<!-- hhmts start --> -Last modified: Fri Jan 19 11:37:23 PST 2001 -<!-- hhmts end --> - </body> -</html> diff --git a/docs/tutorials/022/server.cpp b/docs/tutorials/022/server.cpp deleted file mode 100644 index 5c3bce4601e..00000000000 --- a/docs/tutorials/022/server.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// $Id$ - -/* We try to keep the server much simpler than before and - remove any thing related to the acceptor or the handler - from the main (). This lets keep the server running irrespective of - the state of the acceptor service, in our case and any service in - the general case. */ - -/* We would need the ACE_Service_Config class as it provides an - application developers interface to the entire Service - Configuration Framework */ -#include "ace/Service_Config.h" - -/* Since we are seperating the acceptor service class from the - server, we need to declare our Acceptor_Service */ -#include "Acceptor_Service.h" - -extern "C" void handler (int) -{ - ACE_Service_Config::reconfig_occurred (1); -} - -int -main (int argc, char *argv[]) -{ - /* Perform daemon services update ... this opens the svc.conf - file and reads the entries present in the svc.conf - file. We will later learn the syntax of making an entry - into a svc.conf file. But for now, remember that this is a - file which has the entries to load or unload a service - dynamically or statically. */ - if (ACE_Service_Config::open (argc, - argv, - ACE_DEFAULT_LOGGER_KEY, - 0) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - "%p\n", - "ACE_Service_Config::open"), - -1); - - /* Install our signal handler. As we already know, you can actually - register signal handlers with the reactor. You might do that - when the signal handler is responsible for performing "real" - work. Our simple flag-setter doesn't justify deriving from - ACE_Event_Handler and providing a callback function though. */ - ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGHUP); - - /* Start running the event loop so that it - listens for events and acts accordingly. This event loop will run - until either the event loop is ended explicitly or an error - occurs. */ - ACE_Reactor::run_event_loop (); - - /* NOT REACHED */ - -} diff --git a/docs/tutorials/022/svc.conf b/docs/tutorials/022/svc.conf deleted file mode 100644 index 1c3ae8eb8ce..00000000000 --- a/docs/tutorials/022/svc.conf +++ /dev/null @@ -1,9 +0,0 @@ -# $Id$ - - -#dynamic Acceptor_Service Service_Object * ./Acceptor_Server:_make_Acceptor_Service () "" - -#remove Acceptor_Service - -#suspend Acceptor_Service -#resume Acceptor_Service diff --git a/docs/tutorials/Chap_2/Chap_2.zip b/docs/tutorials/Chap_2/Chap_2.zip Binary files differdeleted file mode 100644 index fb356b7ee09..00000000000 --- a/docs/tutorials/Chap_2/Chap_2.zip +++ /dev/null diff --git a/docs/tutorials/Chap_2/ex01.html b/docs/tutorials/Chap_2/ex01.html deleted file mode 100644 index e702ee77078..00000000000 --- a/docs/tutorials/Chap_2/ex01.html +++ /dev/null @@ -1,107 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "IPC SAP" (Interprocess Communication -Mechanisms in ACE).</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#FF0000">//Example 1</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/SOCK_Acceptor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/SOCK_Stream.h"</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">SIZE_DATA -18</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">SIZE_BUF -1024</FONT> - -<P>class Server{ - -<P>public: -<BR>Server (int port): -<BR> server_addr_(port),peer_acceptor_(server_addr_){ -<BR> data_buf_= new char[SIZE_BUF]; -<BR> } - -<P><FONT COLOR="#FF0000">//Handle the connection once it has been established.</FONT> -<BR><FONT COLOR="#FF0000">//Here the connection is handled by reading SIZE_DATA -amount of data</FONT> -<BR><FONT COLOR="#FF0000">//from the remote and then closing the connection</FONT> -<BR><FONT COLOR="#FF0000">//stream down.</FONT> -<BR>int handle_connection(){ -<BR> <FONT COLOR="#FF0000"> // Read data from client</FONT> -<BR> if(new_stream_.recv_n (data_buf_, SIZE_DATA, 0)==-1) -<BR> ACE_ERROR ((LM_ERROR, "%p\n", "Error in recv")); -<BR> - -<P> ACE_DEBUG((LM_DEBUG,"Server recieved %s \n",data_buf_)); -<BR> -<BR> <FONT COLOR="#FF0000">// Close new endpoint</FONT> -<BR> if (new_stream_.close () == -1) -<BR> ACE_ERROR ((LM_ERROR, "%p\n", "close")); -<BR> return 0; -<BR>} -<BR><FONT COLOR="#FF0000">//Use the acceptor component peer_acceptor_ to -accept the connection</FONT> -<BR><FONT COLOR="#FF0000">//into the underlying stream new_stream_. After -the connection has been</FONT> -<BR><FONT COLOR="#FF0000">//established call the handle_connenction() method.</FONT> -<BR>int accept_connections (){ -<BR> if (peer_acceptor_.get_local_addr (server_addr_) == -1) -<BR> ACE_ERROR_RETURN ((LM_ERROR,"%p\n","Error in get_local_addr"),1); - -<P> ACE_DEBUG ((LM_DEBUG,"Starting server at port %d\n", -<BR> server_addr_.get_port_number ())); -<BR> - -<P> <FONT COLOR="#FF0000">// Performs the iterative server activities.</FONT> -<BR> while(1){ -<BR> ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT); -<BR> if (peer_acceptor_.accept -<BR> (new_stream_, &client_addr_, &timeout)== --1){ -<BR> ACE_ERROR ((LM_ERROR, "%p\n", "accept")); -<BR> continue; -<BR> } -<BR> else -<BR> ACE_DEBUG((LM_DEBUG, -<BR> "Connection established with remote %s:%d\n", -<BR> client_addr_.get_host_name(),client_addr_.get_port_number())); -<BR> <FONT COLOR="#FF0000">//Handle the connection</FONT> -<BR> handle_connection(); -<BR> } -<BR> } -<BR> -<BR> - -<P>private: -<BR> char *data_buf_; -<BR> ACE_INET_Addr server_addr_; -<BR> ACE_INET_Addr client_addr_; -<BR> ACE_SOCK_Acceptor peer_acceptor_; -<BR> ACE_SOCK_Stream new_stream_; -<BR> ACE_HANDLE newhandle; -<BR>}; - -<P>int main (int argc, char *argv[]){ -<BR> if(argc<2){ -<BR> ACE_ERROR((LM_ERROR,"Usage egX <port_num>")); -<BR> ACE_OS::exit(1); -<BR> } -<BR> Server server(ACE_OS::atoi(argv[1])); -<BR> server.accept_connections(); -<BR>} - -<P> <A HREF="ex02.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_2/ex02.html b/docs/tutorials/Chap_2/ex02.html deleted file mode 100644 index 51d3a6cb624..00000000000 --- a/docs/tutorials/Chap_2/ex02.html +++ /dev/null @@ -1,96 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 2</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "IPC SAP" (Interprocess -Communication Mechanisms in ACE).</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT><FONT COLOR="#FF0000"></FONT> - -<P><FONT COLOR="#FF0000">//</FONT><FONT COLOR="#CC0000">Example 2</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/SOCK_Connector.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/INET_Addr.h"</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">SIZE_BUF -128</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">NO_ITERATIONS -5</FONT> - -<P>class Client{ -<BR>public: -<BR>Client(char *hostname, int port):remote_addr_(hostname){ -<BR> remote_addr_.set_port_number(port); -<BR> data_buf_=new char[SIZE_BUF]; -<BR> } - -<P><FONT COLOR="#FF0000">//Uses a connector component connector_ to connect -to a remote machine</FONT> -<BR><FONT COLOR="#FF0000">//and pass the connection into a stream component -client_stream_</FONT> -<BR>int connect_to_server(){ -<BR> <FONT COLOR="#FF0000">// Initiate blocking connection with server.</FONT> -<BR> ACE_DEBUG ((LM_DEBUG, "(%P|%t) Starting connect to %s:%d\n", -<BR> remote_addr_.get_host_name(),remote_addr_.get_port_number())); -<BR> if (connector_.connect (client_stream_, remote_addr_) == -1) -<BR> ACE_ERROR_RETURN ((LM_ERROR,"(%P|%t) %p\n","connection -failed"),-1); -<BR> else -<BR> ACE_DEBUG ((LM_DEBUG,"(%P|%t) connected to %s\n", -<BR> remote_addr_.get_host_name ())); -<BR> return 0; -<BR> } - -<P><FONT COLOR="#FF0000">//Uses a stream component to send data to the -remote host.</FONT> -<BR>int send_to_server(){ -<BR> <FONT COLOR="#FF0000"> // Send data to server</FONT> -<BR> ACE_OS::sprintf(data_buf_,"Hello from Client"); -<BR> for(int i=0;i<NO_ITERATIONS; i++){ -<BR> if (client_stream_.send_n -<BR> (data_buf_, ACE_OS::strlen(data_buf_), 0) == -1){ -<BR> ACE_ERROR_RETURN ((LM_ERROR,"(%P|%t) %p\n","send_n"),0); -<BR> break; -<BR> } -<BR> } -<BR> <FONT COLOR="#FF0000">//Close down the connection</FONT> -<BR> close(); -<BR>} - -<P><FONT COLOR="#FF0000">//Close down the connection properly.</FONT> -<BR>int close(){ -<BR> if (client_stream_.close () == -1) -<BR> ACE_ERROR_RETURN ((LM_ERROR,"(%P|%t) %p\n","close"),-1); -<BR> else -<BR> return 0; -<BR> } - -<P>private: -<BR> ACE_SOCK_Stream client_stream_; -<BR> ACE_INET_Addr remote_addr_; -<BR> ACE_SOCK_Connector connector_; -<BR> char *data_buf_; -<BR>}; - -<P>int main (int argc, char *argv[]){ -<BR> if(argc<3){ -<BR> ACE_DEBUG((LM_DEBUG,?Usage egX <hostname> <port_number>\n?)); -<BR> ACE_OS::exit(1); -<BR> } -<BR> Client client(argv[1],ACE_OS::atoi(argv[2])); -<BR> client.connect_to_server(); -<BR> client.send_to_server(); -<BR>} - -<P> <A HREF="ex03.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_2/ex03.html b/docs/tutorials/Chap_2/ex03.html deleted file mode 100644 index 69e4a57c3c1..00000000000 --- a/docs/tutorials/Chap_2/ex03.html +++ /dev/null @@ -1,83 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 3</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "IPC SAP" (Interprocess -Communication Mechanisms in ACE).</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT><FONT COLOR="#FF0000"></FONT> - -<P><FONT COLOR="#CC0000">// Example 3</FONT><FONT COLOR="#FF0000"></FONT> - -<P><FONT COLOR="#FF0000">//Server</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/OS.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/SOCK_Dgram.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/INET_Addr.h"</FONT> - -<P><FONT COLOR="#000099">#define </FONT><FONT COLOR="#663366">DATA_BUFFER_SIZE -1024</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">SIZE_DATA -18</FONT> - -<P>class Server{ -<BR>public: -<BR>Server(int local_port) -<BR> :local_addr_(local_port),local_(local_addr_){ -<BR> data_buf = new char[DATA_BUFFER_SIZE]; -<BR> } -<BR><FONT COLOR="#FF0000">//Expect data to arrive from the remote machine. -Accept it and display it.</FONT> -<BR><FONT COLOR="#FF0000">// After recieveing data immediately send some -data back to the remote.</FONT> -<BR>int accept_data(){ -<BR> while(local_.recv(data_buf,DATA_BUFFER_SIZE,remote_addr_)!=-1){ -<BR> ACE_DEBUG((LM_DEBUG, "Data received from remote %s was %s \n" -<BR> ,remote_addr_.get_host_name(), data_buf)); -<BR> ACE_OS::sleep(1); -<BR> if(send_data()==-1) break; -<BR> } -<BR> return -1; -<BR> } -<BR> -<BR> - -<P><FONT COLOR="#FF0000">//Method used to send data to the remote using -the datagram component local_</FONT> -<BR>int send_data(){ -<BR> ACE_DEBUG((LM_DEBUG,"Preparing to send reply to client %s:%d\n", -<BR> remote_addr_.get_host_name(),remote_addr_.get_port_number())); -<BR> ACE_OS::strcpy(data_buf,"Server says hello to you too"); -<BR> if( -<BR> local_.send(data_buf, ACE_OS::strlen(data_buf)+1,remote_addr_)==-1) -<BR> return -1; -<BR> else -<BR> return 0; -<BR> } - -<P>private: -<BR> char *data_buf; -<BR> ACE_INET_Addr remote_addr_; -<BR> ACE_INET_Addr local_addr_; -<BR> ACE_SOCK_Dgram local_; -<BR>}; - -<P>int main(int argc, char *argv[]){ -<BR> Server server(ACE_OS::atoi(argv[1])); -<BR> server.accept_data(); -<BR> return 0; -<BR>} - -<P> <A HREF="ex04.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_2/ex04.html b/docs/tutorials/Chap_2/ex04.html deleted file mode 100644 index 716251de4ec..00000000000 --- a/docs/tutorials/Chap_2/ex04.html +++ /dev/null @@ -1,89 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 4</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "IPC SAP" (Interprocess Communication -Mechanisms in ACE).</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 4</FONT> -<BR><FONT COLOR="#FF0000">//Client</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/OS.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/SOCK_Dgram.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/INET_Addr.h"</FONT> - -<P><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">DATA_BUFFER_SIZE -1024</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">SIZE_DATA -28</FONT> -<BR>class Client{ -<BR>public: -<BR>Client(char * remote_addr,int port) -<BR> :remote_addr_(remote_addr), -<BR> local_addr_((u_short)0),local_(local_addr_){ -<BR> data_buf = new char[DATA_BUFFER_SIZE]; -<BR> remote_addr_.set_port_number(port); -<BR> } -<BR> -<BR><FONT COLOR="#FF0000">//Accept data from the remote host using the -datgram component local_</FONT> -<BR>int accept_data(){ -<BR> if(local_.recv(data_buf,DATA_BUFFER_SIZE,remote_addr_)!=-1){ -<BR> ACE_DEBUG((LM_DEBUG, "Data received from remote server %s -<BR> was: %s \n" ,remote_addr_.get_host_name(), -data_buf)); -<BR> return 0; -<BR> } -<BR> else -<BR> return -1; -<BR> } - -<P><FONT COLOR="#FF0000">//Send data to the remote. Once data has been -sent wait for a reply from</FONT> -<BR><FONT COLOR="#FF0000">//the server.</FONT> -<BR>int send_data(){ -<BR> ACE_DEBUG((LM_DEBUG,"Preparing to send data to server %s:%d\n", -<BR> remote_addr_.get_host_name(),remote_addr_.get_port_number())); -<BR> ACE_OS::strcpy(data_buf,"Client says hello"); -<BR> -<BR> while(local_.send -<BR> (data_buf,ACE_OS::strlen(data_buf)+1,remote_addr_)!=-1){ -<BR> ACE_OS::sleep(1); -<BR> if(accept_data()==-1) -<BR> break; -<BR> } -<BR> return -1; -<BR> } - -<P>private: -<BR> char *data_buf; -<BR> ACE_INET_Addr remote_addr_; -<BR> ACE_INET_Addr local_addr_; -<BR> ACE_SOCK_Dgram local_; -<BR>}; - -<P>int main(int argc, char *argv[]){ -<BR>if(argc<3){ -<BR> ACE_OS::printf("Usage: Client hostname port_number \n"); -<BR> ACE_OS::exit(1); -<BR> } -<BR>Client client(argv[1],ACE_OS::atoi(argv[2])); -<BR>client.send_data(); -<BR>return 0; -<BR>} -<BR> -<BR> <A HREF="ex05.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_2/ex05.htm b/docs/tutorials/Chap_2/ex05.htm deleted file mode 100644 index ad61833b686..00000000000 --- a/docs/tutorials/Chap_2/ex05.htm +++ /dev/null @@ -1,88 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 5</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "IPC SAP" (Interprocess Communication -Mechanisms in ACE).</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 5</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/SOCK_Dgram_Mcast.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/OS.h"</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">DEFAULT_MULTICAST_ADDR -"224.9.9.2"</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">TIMEOUT -5</FONT> - -<P>class Reciever_Multicast{ - -<P>public: -<BR>Reciever_Multicast(int port): -<BR> mcast_addr_(port,DEFAULT_MULTICAST_ADDR),remote_addr_((u_short)0){ -<BR> <FONT COLOR="#FF0000"> // Subscribe to multicast address.</FONT> -<BR> if (mcast_dgram_.subscribe (mcast_addr_) == -1){ -<BR> ACE_DEBUG((LM_DEBUG,"Error in subscribing to Multicast address -\n")); -<BR> exit(-1); -<BR> } -<BR>} - -<P>~Reciever_Multicast(){ -<BR> if(mcast_dgram_.unsubscribe()==-1) -<BR> ACE_DEBUG((LM_ERROR,?Error in unsubscribing from Mcast group\n?)); -<BR> } -<BR> -<BR> -<BR> - -<P><FONT COLOR="#FF0000">//Receive data from someone who is sending data -on the multicast group</FONT> -<BR><FONT COLOR="#FF0000">//address to do so it must use the multicast -datagram component</FONT> -<BR><FONT COLOR="#FF0000">//mcast_dgram_.</FONT> -<BR>int recv_multicast(){ -<BR><FONT COLOR="#FF0000"> //get ready to recieve data from the sender.</FONT> -<BR> if(mcast_dgram_.recv -<BR> (&mcast_info,sizeof (mcast_info),remote_addr_)==-1) -<BR> return -1; -<BR> ACE_DEBUG ((LM_DEBUG, "(%P|%t) Received multicast from %s:%d.\n", -<BR> remote_addr_.get_host_name(), remote_addr_.get_port_number())); -<BR> ACE_DEBUG((LM_DEBUG,"Successfully receieved %d\n", mcast_info)); -<BR> return 0; -<BR> } - -<P>private: -<BR> ACE_INET_Addr mcast_addr_; -<BR> ACE_INET_Addr remote_addr_; -<BR> ACE_SOCK_Dgram_Mcast mcast_dgram_; -<BR> int mcast_info; -<BR>}; -<BR> -<BR> -<BR>int main(int argc, char*argv[]){ -<BR> Reciever_Multicast m(2000); -<BR> <FONT COLOR="#FF0000">//Will run forever</FONT> -<BR> while(m.recv_multicast()!=-1) { -<BR> ACE_DEBUG((LM_DEBUG,"Multicaster succesful \n")); -<BR> } -<BR> -<BR> ACE_DEBUG((LM_ERROR,"Multicaster failed \n")); -<BR> exit(-1); -<BR>} - -<P> <A HREF="ex06.html">Next Example</A> -<BR> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_2/ex05.html b/docs/tutorials/Chap_2/ex05.html deleted file mode 100644 index ad61833b686..00000000000 --- a/docs/tutorials/Chap_2/ex05.html +++ /dev/null @@ -1,88 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 5</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "IPC SAP" (Interprocess Communication -Mechanisms in ACE).</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 5</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/SOCK_Dgram_Mcast.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/OS.h"</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">DEFAULT_MULTICAST_ADDR -"224.9.9.2"</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">TIMEOUT -5</FONT> - -<P>class Reciever_Multicast{ - -<P>public: -<BR>Reciever_Multicast(int port): -<BR> mcast_addr_(port,DEFAULT_MULTICAST_ADDR),remote_addr_((u_short)0){ -<BR> <FONT COLOR="#FF0000"> // Subscribe to multicast address.</FONT> -<BR> if (mcast_dgram_.subscribe (mcast_addr_) == -1){ -<BR> ACE_DEBUG((LM_DEBUG,"Error in subscribing to Multicast address -\n")); -<BR> exit(-1); -<BR> } -<BR>} - -<P>~Reciever_Multicast(){ -<BR> if(mcast_dgram_.unsubscribe()==-1) -<BR> ACE_DEBUG((LM_ERROR,?Error in unsubscribing from Mcast group\n?)); -<BR> } -<BR> -<BR> -<BR> - -<P><FONT COLOR="#FF0000">//Receive data from someone who is sending data -on the multicast group</FONT> -<BR><FONT COLOR="#FF0000">//address to do so it must use the multicast -datagram component</FONT> -<BR><FONT COLOR="#FF0000">//mcast_dgram_.</FONT> -<BR>int recv_multicast(){ -<BR><FONT COLOR="#FF0000"> //get ready to recieve data from the sender.</FONT> -<BR> if(mcast_dgram_.recv -<BR> (&mcast_info,sizeof (mcast_info),remote_addr_)==-1) -<BR> return -1; -<BR> ACE_DEBUG ((LM_DEBUG, "(%P|%t) Received multicast from %s:%d.\n", -<BR> remote_addr_.get_host_name(), remote_addr_.get_port_number())); -<BR> ACE_DEBUG((LM_DEBUG,"Successfully receieved %d\n", mcast_info)); -<BR> return 0; -<BR> } - -<P>private: -<BR> ACE_INET_Addr mcast_addr_; -<BR> ACE_INET_Addr remote_addr_; -<BR> ACE_SOCK_Dgram_Mcast mcast_dgram_; -<BR> int mcast_info; -<BR>}; -<BR> -<BR> -<BR>int main(int argc, char*argv[]){ -<BR> Reciever_Multicast m(2000); -<BR> <FONT COLOR="#FF0000">//Will run forever</FONT> -<BR> while(m.recv_multicast()!=-1) { -<BR> ACE_DEBUG((LM_DEBUG,"Multicaster succesful \n")); -<BR> } -<BR> -<BR> ACE_DEBUG((LM_ERROR,"Multicaster failed \n")); -<BR> exit(-1); -<BR>} - -<P> <A HREF="ex06.html">Next Example</A> -<BR> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_2/ex06.html b/docs/tutorials/Chap_2/ex06.html deleted file mode 100644 index b5c1f873e99..00000000000 --- a/docs/tutorials/Chap_2/ex06.html +++ /dev/null @@ -1,77 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 6</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "IPC SAP" (Interprocess Communication -Mechanisms in ACE).</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 6</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">DEFAULT_MULTICAST_ADDR -"224.9.9.2"</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">TIMEOUT -5</FONT> -<BR><FONT COLOR="#000099">#include</FONT><FONT COLOR="#006600"> "ace/SOCK_Dgram_Mcast.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/OS.h"</FONT> - -<P>class Sender_Multicast{ -<BR>public: -<BR>Sender_Multicast(int port): -<BR> local_addr_((u_short)0),dgram_(local_addr_), -<BR> multicast_addr_(port,DEFAULT_MULTICAST_ADDR){} - -<P><FONT COLOR="#FF0000">//Method which uses a simple datagram component -to send data to the multicast group.</FONT> -<BR>int send_to_multicast_group(){ -<BR> <FONT COLOR="#FF0000">//Convert the information we wish -to send into network byte order</FONT> -<BR> mcast_info= htons (1000); - -<P><FONT COLOR="#FF0000"> // Send multicast</FONT> -<BR> if(dgram_.send -<BR> (&mcast_info, sizeof (mcast_info), multicast_addr_)==-1) -<BR> return -1; - -<P> ACE_DEBUG ((LM_DEBUG, -<BR> -"%s; Sent multicast to group. Number sent is %d.\n", -<BR> -__FILE__, -<BR> -mcast_info)); -<BR> return 0; -<BR>} - -<P>private: -<BR> ACE_INET_Addr multicast_addr_; -<BR> ACE_INET_Addr local_addr_; -<BR> ACE_SOCK_Dgram dgram_; -<BR> int mcast_info; -<BR>}; -<BR> - -<P>int main(int argc, char*argv[]){ -<BR>Sender_Multicast m(2000); -<BR>if(m.send_to_multicast_group()==-1) { -<BR> ACE_DEBUG((LM_ERROR,"Send to Multicast group failed \n")); -<BR> exit(-1); -<BR> } -<BR>else -<BR> ACE_DEBUG((LM_DEBUG,"Send to Multicast group succesful \n")); -<BR>} - -<P> <A HREF="../Chap_3/ex01.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_3/Chap_3.zip b/docs/tutorials/Chap_3/Chap_3.zip Binary files differdeleted file mode 100644 index c99463d18d9..00000000000 --- a/docs/tutorials/Chap_3/Chap_3.zip +++ /dev/null diff --git a/docs/tutorials/Chap_3/Makefile b/docs/tutorials/Chap_3/Makefile deleted file mode 100644 index e3f1f3ae1c8..00000000000 --- a/docs/tutorials/Chap_3/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -#---------------------------------------------------------------------------- -# -# $Id$ -# -# Makefile for all the ACE ``one-button' tests -#---------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# Local macros -#---------------------------------------------------------------------------- - -BIN = mm - -PSRC=$(addsuffix .cpp,$(BIN)) - -#---------------------------------------------------------------------------- -# Include macros and targets -#---------------------------------------------------------------------------- - -include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU -include $(ACE_ROOT)/include/makeinclude/macros.GNU -include $(ACE_ROOT)/include/makeinclude/rules.common.GNU -include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU -include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU - -include $(ACE_ROOT)/include/makeinclude/rules.local.GNU - -ex03.html : mm.cpp - ../colorize < mm.cpp > ex03.html diff --git a/docs/tutorials/Chap_3/README b/docs/tutorials/Chap_3/README deleted file mode 100644 index 228579ca4c5..00000000000 --- a/docs/tutorials/Chap_3/README +++ /dev/null @@ -1,14 +0,0 @@ -Note: - -Example 2 (ex02.html) will not compile and work on Win32 because -it relies on SystemV Shared Memory and fork() which are not -available on that platoform. - -Example 3 (ex03.html) is basically the same but uses a memory-mapped -file instead of SYSV Shared Memory. It also takes a single command -line parament 's' to start it in server mode or 'c' to start it -in client mode. (This is to work around the lack of fork()). - -(Thanks to Nanbor Wang for working this out for us.) - -JCEJ - 08/01/1999 diff --git a/docs/tutorials/Chap_3/ex01.html b/docs/tutorials/Chap_3/ex01.html deleted file mode 100644 index 6993d74b3ab..00000000000 --- a/docs/tutorials/Chap_3/ex01.html +++ /dev/null @@ -1,108 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 1</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "Memory Management"</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 1 </FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Malloc.h"</FONT> -<BR><FONT COLOR="#FF0000">//A chunk of size 1K is created</FONT> -<BR><FONT COLOR="#000099">typedef</FONT> <FONT COLOR="#993300">char</FONT><FONT COLOR="#666600"> -MEMORY_BLOCK[1024];</FONT> -<BR> -<BR> - -<P><FONT COLOR="#FF0000">//Create an ACE_Cached_Allocator which is passed -in the type of the</FONT> -<BR><FONT COLOR="#FF0000">//chunk that it must pre-allocate and assign -on the free</FONT> -<BR><FONT COLOR="#FF0000">//list</FONT> -<BR><FONT COLOR="#000000">typedef ACE_Cached_Allocator<MEMORY_BLOCK,ACE_SYNCH_MUTEX> -Allocator;</FONT> -<BR> -<BR>class MessageManager{ -<BR>public: -<BR><FONT COLOR="#FF0000">//The constructor is passed the number of chunks -that the allocator should pre-allocate //and maintain on its free list.</FONT> -<BR>MessageManager(int n_blocks): -<BR> allocator_(n_blocks),message_count_(0){} - -<P><FONT COLOR="#FF0000">//Allocate memory for a message using the Allocator</FONT> -<BR>void allocate_msg(const char *msg){ -<BR> mesg_array_[message_count_]= -<BR> (char*)allocator_.malloc(ACE_OS::strlen(msg)); -<BR> ACE_OS::strcpy(mesg_array_[message_count_],msg); -<BR> message_count_++; -<BR> } - -<P><FONT COLOR="#FF0000">//Free all memory allocated. This will cause the -chunks to be returned</FONT> -<BR><FONT COLOR="#FF0000">//to the allocators internal free list and NOT -to the OS.</FONT> -<BR>void free_all_msg(){ -<BR> for(int i=0;i<message_count_;i++) -<BR> allocator_.free(mesg_array_[i]); -<BR> message_count_=0; -<BR> } -<BR>void display_all_msg(){ -<BR> for(int i=0;i<message_count_;i++) -<BR> ACE_OS::printf("%s\n",mesg_array_[i]); -<BR> } -<BR> -<BR>private: -<BR> char *mesg_array_[20]; -<BR> Allocator allocator_; -<BR> int message_count_; -<BR>}; -<BR> - -<P>int main(int argc, char* argv[]){ - -<P>if(argc<2){ -<BR> ACE_OS::printf("Usage: egXX <Number of blocks>\n"); -<BR> exit(1); -<BR> } -<BR> -<BR><FONT COLOR="#FF0000">//Instatiate the Memory Manager class</FONT> -<BR>int n_blocks=ACE_OS::atoi(argv[1]); -<BR>MessageManager mm(n_blocks); -<BR> - -<P><FONT COLOR="#FF0000">//Use the Memory Manager class to assign messages -and free them.</FONT> <FONT COLOR="#FF0000">Run this in your</FONT> -<BR><FONT COLOR="#FF0000">//debug environment and you will notice that -//the</FONT> <FONT COLOR="#FF0000">amount of memory your program uses</FONT> -<BR><FONT COLOR="#FF0000">//after Memory Manager has been</FONT> <FONT COLOR="#FF0000">instantiated -remains the same. That means the</FONT> -<BR><FONT COLOR="#FF0000">//Cached Allocator</FONT> <FONT COLOR="#FF0000">controls -or manages all the memory for the application.</FONT> - -<P><FONT COLOR="#FF0000">//Do forever.</FONT> -<BR>while(1){ -<BR> <FONT COLOR="#FF0000">//allocate the messages somewhere</FONT> -<BR> for(int i=0; i<n_blocks;i++) -<BR> mm.allocate_msg("Hi there"); -<BR> <FONT COLOR="#FF0000">//show the messages</FONT> -<BR> mm.display_all_msg(); -<BR> -<BR> for( i=0;i<n_blocks;i++) -<BR> mm.free_all_msg(); -<BR> } -<BR>} - -<P> <A HREF="ex02.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_3/ex02.html b/docs/tutorials/Chap_3/ex02.html deleted file mode 100644 index ed5f0caf497..00000000000 --- a/docs/tutorials/Chap_3/ex02.html +++ /dev/null @@ -1,136 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 2</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "Memory Management"</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 2</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Shared_Memory_MM.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Malloc.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Malloc_T.h"</FONT> -<BR><FONT COLOR="#000099">#define </FONT><FONT COLOR="#663366">DATA_SIZE -100</FONT> -<BR><FONT COLOR="#000099">#define</FONT><FONT COLOR="#663366"> MESSAGE1 -"Hiya over there client process"</FONT> -<BR><FONT COLOR="#000099">#define </FONT><FONT COLOR="#663366">MESSAGE2 -"Did you hear me the first time?"</FONT> -<BR>LPCTSTR poolname="My_Pool"; - -<P><FONT COLOR="#000000">typedef ACE_Malloc<ACE_SHARED_MEMORY_POOL,ACE_Null_Mutex> -Malloc_Allocator;</FONT> - -<P>static void -<BR>server (void){ -<BR> <FONT COLOR="#FF0000">//Create the memory allocator passing it -the shared memory</FONT> -<BR> <FONT COLOR="#FF0000">//pool that you want to use</FONT> -<BR> Malloc_Allocator shm_allocator(poolname); - -<P> <FONT COLOR="#FF0000">//Create a message, allocate memory for -it and bind it with</FONT> -<BR><FONT COLOR="#FF0000"> //a name so that the client can the find -it in the memory</FONT> -<BR><FONT COLOR="#FF0000"> //pool</FONT> -<BR> char* Message1=(char*)shm_allocator.malloc(strlen(MESSAGE1)); -<BR> ACE_OS::strcpy(Message1,MESSAGE1); -<BR> shm_allocator.bind("FirstMessage",Message1); -<BR> ACE_DEBUG((LM_DEBUG,"<<%s\n",Message1)); -<BR> -<BR><FONT COLOR="#FF0000"> //How about a second message</FONT> -<BR> char* Message2=(char*)shm_allocator.malloc(strlen(MESSAGE2)); -<BR> ACE_OS::strcpy(Message2,MESSAGE2); -<BR> shm_allocator.bind("SecondMessage",Message2); -<BR> ACE_DEBUG((LM_DEBUG,"<<%s\n",Message2)); -<BR> -<BR> <FONT COLOR="#FF0000">//Set the Server to go to sleep for a while -so that the client has</FONT> -<BR><FONT COLOR="#FF0000"> //a chance to do its stuff</FONT> -<BR> ACE_DEBUG((LM_DEBUG, -<BR> "Server done writing.. going to sleep zzz..\n\n\n")); -<BR> ACE_OS::sleep(2); -<BR> -<BR><FONT COLOR="#FF0000"> //Get rid of all resources allocated by -the server. In other</FONT> -<BR><FONT COLOR="#FF0000"> //words get rid of the shared memory pool -that had been</FONT> -<BR><FONT COLOR="#FF0000"> //previously allocated</FONT> -<BR> shm_allocator.remove(); -<BR> -<BR>} -<BR> - -<P>static void -<BR>client(void){ -<BR> <FONT COLOR="#FF0000">//Create a memory allocator. Be sure that -the client passes</FONT> -<BR><FONT COLOR="#FF0000"> // in the "right" name here so that both -the client and the</FONT> -<BR><FONT COLOR="#FF0000"> //server use the same memory pool. We wouldnt -want them to</FONT> -<BR><FONT COLOR="#FF0000"> // BOTH create different underlying pools.</FONT> -<BR> Malloc_Allocator shm_allocator(poolname); - -<P><FONT COLOR="#FF0000"> //Lets get that first message. Notice that -the find is looking up the</FONT> -<BR><FONT COLOR="#FF0000"> //memory based on the "name" that was bound -to it by the server.</FONT> -<BR> void *Message1; -<BR> if(shm_allocator.find("FirstMessage",Message1)==-1){ -<BR> ACE_ERROR((LM_ERROR, -<BR> "Client: Problem cant find data that server has -sent\n")); -<BR> ACE_OS::exit(1); -<BR> } -<BR> ACE_OS::printf(">>%s\n",(char*) Message1); -<BR> ACE_OS::fflush(stdout); - -<P> <FONT COLOR="#FF0000">//Lets get that second message now.</FONT> -<BR> void *Message2; -<BR> if(shm_allocator.find("SecondMessage",Message2)==-1){ -<BR> ACE_ERROR((LM_ERROR,"Client: Problem cant find data that server -has sent\n")); -<BR> ACE_OS::exit(1); -<BR> } -<BR> ACE_OS::printf(">>%s\n",(char*)Message2); -<BR> ACE_OS::fflush(stdout); - -<P> ACE_DEBUG((LM_DEBUG,"Client done reading! BYE NOW\n")); -<BR> ACE_OS::fflush(stdout); -<BR>} -<BR> - -<P>int main (int, char *[]){ -<BR>switch (ACE_OS::fork ()) -<BR> { -<BR> case -1: -<BR> ACE_ERROR_RETURN ((LM_ERROR, "%p\n", -"fork"), 1); -<BR> case 0: -<BR> <FONT COLOR="#FF0000"> // Make sure the -server starts up first.</FONT> -<BR> ACE_OS::sleep (1); -<BR> client (); -<BR> break; -<BR> default: -<BR> server (); -<BR> break; -<BR> } -<BR> return 0; -<BR>} -<BR> -<BR> <A HREF="../Chap_4/ex01.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_3/ex03.html b/docs/tutorials/Chap_3/ex03.html deleted file mode 100644 index 743f0b395d2..00000000000 --- a/docs/tutorials/Chap_3/ex03.html +++ /dev/null @@ -1,115 +0,0 @@ -<PRE> -<font color=red>// $Id$</font> - -<font color=blue>#include</font> "<font color=green>ace/Memory_Pool.h</font>" -<font color=blue>#include</font> "<font color=green>ace/Shared_Memory_MM.h</font>" -<font color=blue>#include</font> "<font color=green>ace/Malloc.h</font>" -<font color=blue>#include</font> "<font color=green>ace/Malloc_T.h</font>" -<font color=blue>#include</font> "<font color=green>ace/Thread_Manager.h</font>" - -<font color=blue>#define</font> <font color=purple>DATA_SIZE</font> 100 -<font color=blue>#define</font> <font color=purple>MESSAGE1</font> "<font color=green>Hiya over there client process</font>" -<font color=blue>#define</font> <font color=purple>MESSAGE2</font> "<font color=green>Did you hear me the first time?</font>" -LPCTSTR poolname="<font color=green>My_Pool</font>"; - -typedef ACE_Malloc<ACE_MMAP_MEMORY_POOL, ACE_Null_Mutex> Malloc_Allocator; - -static void * -server (void * = 0) -{ - ACE_MMAP_Memory_Pool_Options opt; - - <font color=red>//Create the memory allocator passing it the shared memory</font> - <font color=red>//pool that you want to use</font> - Malloc_Allocator shm_allocator(poolname,poolname,&opt); - - <font color=red>//Create a message, allocate memory for it and bind it with</font> - <font color=red>//a name so that the client can the find it in the memory</font> - <font color=red>//pool</font> - char* Message1=(char*)shm_allocator.malloc(strlen(MESSAGE1)+1); - - <font color=#008888>ACE_OS::strcpy</font>(Message1,MESSAGE1); - shm_allocator.bind("<font color=green>FirstMessage</font>",Message1); - ACE_DEBUG((LM_DEBUG,"<font color=green><<%s\n</font>",Message1)); - - <font color=red>//How about a second message</font> - char* Message2=(char*)shm_allocator.malloc(strlen(MESSAGE2)+1); - <font color=#008888>ACE_OS::strcpy</font>(Message2,MESSAGE2); - shm_allocator.bind("<font color=green>SecondMessage</font>",Message2); - ACE_DEBUG((LM_DEBUG,"<font color=green><<%s\n</font>",Message2)); - - <font color=red>//Set the Server to go to sleep for a while so that the client has</font> - <font color=red>//a chance to do its stuff</font> - ACE_DEBUG((LM_DEBUG, "<font color=green>Server done writing.. going to sleep zzz..\n\n\n</font>")); - <font color=#008888>ACE_OS::sleep</font>(10); - - ACE_DEBUG ((LM_DEBUG, "<font color=green>server exit\n</font>")); - - return 0; -} - -static void * -client (void * = 0) -{ - ACE_MMAP_Memory_Pool_Options opt; - - <font color=red>//Create the memory allocator passing it the shared memory</font> - <font color=red>//pool that you want to use</font> - Malloc_Allocator shm_allocator(poolname,poolname,&opt); - - <font color=red>//Lets get that first message. Notice that the find is looking up the</font> - <font color=red>//memory based on the "<font color=green>name</font>" that was bound to it by the server.</font> - void *Message1 = 0; - if(shm_allocator.find("<font color=green>FirstMessage</font>") == -1 ) - { - ACE_ERROR((LM_ERROR, - "<font color=green>Client ack\n</font>")); - return 0; - } - if(shm_allocator.find("<font color=green>FirstMessage</font>",Message1)==-1) - { - ACE_ERROR((LM_ERROR, - "<font color=green>Client: Problem cant find data that server has sent\n</font>")); - return 0; - } - - <font color=#008888>ACE_OS::printf</font>("<font color=green>>>%s\n</font>",(char*) Message1); - <font color=#008888>ACE_OS::fflush</font>(stdout); - - <font color=red>//Lets get that second message now.</font> - void *Message2; - if(shm_allocator.find("<font color=green>SecondMessage</font>",Message2)==-1) - { - ACE_ERROR((LM_ERROR, - "<font color=green>Client: Problem cant find data that server has sent\n</font>")); - <font color=#008888>ACE_OS::exit</font>(1); - } - <font color=#008888>ACE_OS::printf</font>("<font color=green>>>%s\n</font>",(char*)Message2); - <font color=#008888>ACE_OS::fflush</font>(stdout); - - ACE_DEBUG((LM_DEBUG,"<font color=green>Client done reading! BYE NOW\n</font>")); - <font color=#008888>ACE_OS::fflush</font>(stdout); - - <font color=red>//Get rid of all resources allocated by the server. In other</font> - <font color=red>//words get rid of the shared memory pool that had been</font> - <font color=red>//previously allocated</font> - shm_allocator.remove(); - - return 0; -} - -int main (int, char *argv[]) -{ - switch (*argv[1]) - { - case 's': - server (); - break; - default: - client (); - break; - } - - return 0; -} -</PRE> diff --git a/docs/tutorials/Chap_3/mm.cpp b/docs/tutorials/Chap_3/mm.cpp deleted file mode 100644 index 43188360f66..00000000000 --- a/docs/tutorials/Chap_3/mm.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// $Id$ - -#include "ace/Memory_Pool.h" -#include "ace/Shared_Memory_MM.h" -#include "ace/Malloc.h" -#include "ace/Malloc_T.h" -#include "ace/Thread_Manager.h" - -#define DATA_SIZE 100 -#define MESSAGE1 "Hiya over there client process" -#define MESSAGE2 "Did you hear me the first time?" -const ACE_TCHAR *poolname="My_Pool"; - -typedef ACE_Malloc<ACE_MMAP_MEMORY_POOL, ACE_Null_Mutex> Malloc_Allocator; - -static void * -server (void * = 0) -{ - ACE_MMAP_Memory_Pool_Options opt; - - //Create the memory allocator passing it the shared memory - //pool that you want to use - Malloc_Allocator shm_allocator(poolname,poolname,&opt); - - //Create a message, allocate memory for it and bind it with - //a name so that the client can the find it in the memory - //pool - char* Message1=(char*)shm_allocator.malloc(strlen(MESSAGE1)+1); - - ACE_OS::strcpy(Message1,MESSAGE1); - shm_allocator.bind("FirstMessage",Message1); - ACE_DEBUG((LM_DEBUG,"<<%s\n",Message1)); - - //How about a second message - char* Message2=(char*)shm_allocator.malloc(strlen(MESSAGE2)+1); - ACE_OS::strcpy(Message2,MESSAGE2); - shm_allocator.bind("SecondMessage",Message2); - ACE_DEBUG((LM_DEBUG,"<<%s\n",Message2)); - - //Set the Server to go to sleep for a while so that the client has - //a chance to do its stuff - ACE_DEBUG((LM_DEBUG, "Server done writing.. going to sleep zzz..\n\n\n")); - ACE_OS::sleep(10); - - ACE_DEBUG ((LM_DEBUG, "server exit\n")); - - return 0; -} - -static void * -client (void * = 0) -{ - ACE_MMAP_Memory_Pool_Options opt; - - //Create the memory allocator passing it the shared memory - //pool that you want to use - Malloc_Allocator shm_allocator(poolname,poolname,&opt); - - //Lets get that first message. Notice that the find is looking up the - //memory based on the "name" that was bound to it by the server. - void *Message1 = 0; - if(shm_allocator.find("FirstMessage") == -1 ) - { - ACE_ERROR((LM_ERROR, - "Client ack\n")); - return 0; - } - if(shm_allocator.find("FirstMessage",Message1)==-1) - { - ACE_ERROR((LM_ERROR, - "Client: Problem cant find data that server has sent\n")); - return 0; - } - - ACE_OS::printf(">>%s\n",(char*) Message1); - ACE_OS::fflush(stdout); - - //Lets get that second message now. - void *Message2; - if(shm_allocator.find("SecondMessage",Message2)==-1) - { - ACE_ERROR((LM_ERROR, - "Client: Problem cant find data that server has sent\n")); - ACE_OS::exit(1); - } - ACE_OS::printf(">>%s\n",(char*)Message2); - ACE_OS::fflush(stdout); - - ACE_DEBUG((LM_DEBUG,"Client done reading! BYE NOW\n")); - ACE_OS::fflush(stdout); - - //Get rid of all resources allocated by the server. In other - //words get rid of the shared memory pool that had been - //previously allocated - shm_allocator.remove(); - - return 0; -} - -int main (int, char *argv[]) -{ - switch (*argv[1]) - { - case 's': - server (); - break; - default: - client (); - break; - } - - return 0; -} diff --git a/docs/tutorials/Chap_4/Chap_4.zip b/docs/tutorials/Chap_4/Chap_4.zip Binary files differdeleted file mode 100644 index b29059f1457..00000000000 --- a/docs/tutorials/Chap_4/Chap_4.zip +++ /dev/null diff --git a/docs/tutorials/Chap_4/ex01.html b/docs/tutorials/Chap_4/ex01.html deleted file mode 100644 index 39f479473e8..00000000000 --- a/docs/tutorials/Chap_4/ex01.html +++ /dev/null @@ -1,75 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 1</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "Thread Management"</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 1</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Thread.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/OS.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Synch_T.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT><FONT COLOR="#006600"> "ace/Synch.h"</FONT> -<BR>static int number=0; -<BR>static int seed=0; - -<P>static void* -<BR>worker(void *arg){ -<BR> ACE_UNUSED_ARG(arg); -<BR> ACE_DEBUG((LM_DEBUG,"Thread (%t) Created to do some work")); -<BR> ::number++; -<BR> ACE_DEBUG((LM_DEBUG," and number is %d\n",::number)); -<BR> -<BR> <FONT COLOR="#FF0000">//Let the other guy go while I fall asleep -for a random period of time</FONT> -<BR> ACE_Thread::yield(); -<BR> ACE_OS::sleep(ACE_OS::rand()%2); - -<P><FONT COLOR="#FF0000"> //Exiting now</FONT> -<BR> ACE_DEBUG((LM_DEBUG, -<BR> "\t\t Thread (%t) Done! \t The number is now: %d\n",number)); -<BR> ACE_OS::fflush(stdout); -<BR> return 0; -<BR> } -<BR> - -<P>int main(int argc, char *argv[]){ -<BR>if(argc<2) -<BR> ACE_DEBUG((LM_DEBUG,"Usage: <program_name> <number of threads>\n")); -<BR> -<BR>int n_threads=ACE_OS::atoi(argv[1]); -<BR><FONT COLOR="#FF0000">//Setup the random number generator</FONT> -<BR>ACE_OS::srand(::seed); - -<P><FONT COLOR="#FF0000">//Spawn off n_threads number of threads</FONT> -<BR>for(int i=0; i<n_threads; i++){ -<BR> if(ACE_Thread::spawn((ACE_THR_FUNC)worker)==-1) -<BR> ACE_DEBUG((LM_DEBUG,"Error in spawning thread\n")); -<BR> } - -<P><FONT COLOR="#FF0000">//Wait for all the threads to exit before you -let the main fall through</FONT> -<BR><FONT COLOR="#FF0000">//and have the process exit. This way of using -join is non-portable</FONT> -<BR><FONT COLOR="#FF0000">//and may not work on a system using pthreads.</FONT> -<BR>int check_count=0; -<BR>while(ACE_Thread::join(NULL,NULL,NULL)==0) check_count++; -<BR>ACE_ASSERT(check_count==n_threads); -<BR>} - -<P> <A HREF="ex02.html">Next Example</A> -<BR> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_4/ex02.html b/docs/tutorials/Chap_4/ex02.html deleted file mode 100644 index 6e3a6afeebb..00000000000 --- a/docs/tutorials/Chap_4/ex02.html +++ /dev/null @@ -1,68 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 2</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "Thread Management"</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 2</FONT> -<BR><FONT COLOR="#000099">#include </FONT><FONT COLOR="#006600">"ace/OS.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Synch.h"</FONT> - -<P><FONT COLOR="#FF0000">//Arguments that are to be passed to the worker -thread are passed through this class.</FONT> -<BR>class Args{ -<BR>public: -<BR>Args(int iterations): -<BR> mutex_(),iterations_(iterations){} -<BR>ACE_Thread_Mutex mutex_; -<BR>int iterations_; -<BR>}; - -<P><FONT COLOR="#FF0000">//The starting point for the worker threads</FONT> -<BR>static void* -<BR>worker(void*arguments){ -<BR>Args *arg= (Args*) arguments; -<BR>for(int i=0;i<arg->iterations_;i++){ -<BR> ACE_DEBUG((LM_DEBUG, -<BR> "(%t) Trying to get a hold of this iteration\n")); -<BR><FONT COLOR="#FF0000"> //This is our critical section</FONT> -<BR> arg->mutex_.acquire(); -<BR> ACE_DEBUG((LM_DEBUG,"(%t) This is iteration number %d\n",i)); -<BR><FONT COLOR="#FF0000"> //work</FONT> -<BR> ACE_OS::sleep(2); -<BR> arg->mutex_.release(); -<BR> } -<BR>return 0; -<BR>} - -<P>int main(int argc, char*argv[]){ -<BR>if(argc<2){ -<BR>ACE_OS::printf("Usage: egx <number_of_threads> -<BR> <number_of_iterations>\n"); -<BR> ACE_OS::exit(1); -<BR> } -<BR><FONT COLOR="#FF0000">//Setup the arguments</FONT> -<BR>Args arg(ACE_OS::atoi(argv[2])); - -<P>ACE_Thread::spawn_n -<BR> (ACE_OS::atoi(argv[1]),(ACE_THR_FUNC)worker,(void*)&arg); -<BR><FONT COLOR="#FF0000">//Spawn the worker threads</FONT> -<BR>while(ACE_Thread::join(NULL,NULL,NULL)==0); -<BR>} -<BR> -<BR> <A HREF="ex03.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_4/ex03.html b/docs/tutorials/Chap_4/ex03.html deleted file mode 100644 index 78d5555e17c..00000000000 --- a/docs/tutorials/Chap_4/ex03.html +++ /dev/null @@ -1,79 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 3</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "Thread Management"</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 3</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/OS.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Synch.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Synch_T.h"</FONT> - -<P><FONT COLOR="#FF0000">//Arguments that are to be passed to the worker -thread are passed through this class.</FONT> -<BR>class Args{ -<BR>public: -<BR>Args(ACE_Lock* lock,int iterations): -<BR> mutex_(lock),iterations_(iterations){} -<BR>ACE_Lock* mutex_; -<BR>int iterations_; -<BR>}; - -<P><FONT COLOR="#FF0000">//The starting point for the worker threads</FONT> -<BR>static void* -<BR>worker(void*arguments){ -<BR>Args *arg= (Args*) arguments; -<BR>for(int i=0;i<arg->iterations_;i++){ -<BR> ACE_DEBUG((LM_DEBUG, -<BR> "(%t) Trying to get a hold of this iteration\n")); -<BR><FONT COLOR="#FF0000"> //This is our critical section</FONT> -<BR> arg->mutex_->acquire(); -<BR> ACE_DEBUG((LM_DEBUG,"(%t) This is iteration number %d\n",i)); -<BR><FONT COLOR="#FF0000"> //work</FONT> -<BR> ACE_OS::sleep(2); -<BR> arg->mutex_->release(); -<BR> } -<BR>return 0; -<BR>} - -<P>int main(int argc, char*argv[]){ -<BR>if(argc<4){ -<BR> ACE_OS::printf("Usage: egx <number_of_threads> -<BR> <number_of_iterations> <lock_type>\n"); -<BR> ACE_OS::exit(1); -<BR> } -<BR><FONT COLOR="#FF0000">//Lock used by application</FONT> -<BR>ACE_Lock *lock; - -<P><FONT COLOR="#FF0000">//Decide which lock you want to use at run time. -Possible due to</FONT> -<BR><FONT COLOR="#FF0000">//ACE_Lock.</FONT> -<BR>if(ACE_OS::strcmp(argv[3],"Thread")) -<BR> lock=new ACE_Lock_Adapter<ACE_Thread_Mutex>; -<BR>else -<BR> lock=new ACE_Lock_Adapter<ACE_Mutex> - -<P><FONT COLOR="#FF0000">//Setup the arguments</FONT> -<BR>Args arg(lock,ACE_OS::atoi(argv[2])); -<BR><FONT COLOR="#FF0000">//Spawn the worker threads</FONT> -<BR>ACE_Thread::spawn_n -<BR> (ACE_OS::atoi(argv[1]),(ACE_THR_FUNC)worker,(void*)&arg); -<BR>while(ACE_Thread::join(NULL,NULL,NULL)==0); -<BR>} - -<P> <A HREF="ex04.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_4/ex04.html b/docs/tutorials/Chap_4/ex04.html deleted file mode 100644 index 4d4a753002c..00000000000 --- a/docs/tutorials/Chap_4/ex04.html +++ /dev/null @@ -1,70 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 4</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "Thread Management"</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 4</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/OS.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT><FONT COLOR="#006600"> "ace/Token.h"</FONT> - -<P><FONT COLOR="#FF0000">//Arguments that are to be passed to the worker -thread are passed</FONT> -<BR><FONT COLOR="#FF0000">//through this class.</FONT> -<BR>class Args{ -<BR>public: -<BR>Args(int iterations): -<BR> mutex_(),iterations_(iterations){} -<BR>ACE_Token mutex_; -<BR>int iterations_; -<BR>}; - -<P><FONT COLOR="#FF0000">//The starting point for the worker threads</FONT> -<BR>static void* -<BR>worker(void*arguments){ -<BR>Args *arg= (Args*) arguments; -<BR>for(int i=0;i<arg->iterations_;i++){ -<BR> ACE_DEBUG((LM_DEBUG,"(%t) Trying to get a hold of this iteration\n")); -<BR><FONT COLOR="#FF0000"> //This is our critical section</FONT> -<BR> arg->mutex_.acquire(); -<BR> ACE_DEBUG((LM_DEBUG,"(%t) This is iteration number %d\n",i)); -<BR><FONT COLOR="#FF0000"> //work</FONT> -<BR> ACE_OS::sleep(2); -<BR> arg->mutex_.release(); -<BR> } -<BR>return 0; -<BR>} -<BR> - -<P>int main(int argc, char*argv[]){ -<BR>if(argc<4){ -<BR> ACE_OS::printf("Usage: egx <number_of_threads> -<BR> <number_of_iterations> <lock_type>\n"); -<BR> ACE_OS::exit(1); -<BR> } - -<P><FONT COLOR="#FF0000">//Setup the arguments</FONT> -<BR>Args arg(ACE_OS::atoi(argv[2])); -<BR><FONT COLOR="#FF0000">//Spawn the worker threads</FONT> -<BR>ACE_Thread::spawn_n(ACE_OS::atoi(argv[1]),(ACE_THR_FUNC)worker,(void*)&arg); - -<P>while(ACE_Thread::join(NULL,NULL,NULL)==0); - -<P>} - -<P> <A HREF="ex05.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_4/ex05.html b/docs/tutorials/Chap_4/ex05.html deleted file mode 100644 index 44bd153af25..00000000000 --- a/docs/tutorials/Chap_4/ex05.html +++ /dev/null @@ -1,70 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 5</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "Thread Management"</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 5</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/OS.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Synch.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Synch_T.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT><FONT COLOR="#006600"> "ace/Token.h"</FONT> - -<P><FONT COLOR="#FF0000">//Arguments that are to be passed to the worker -thread are passed through this class.</FONT> -<BR>class Args{ -<BR>public: -<BR>Args(int iterations): -<BR> mutex_(),iterations_(iterations){} -<BR>ACE_Token mutex_; -<BR>int iterations_; -<BR>}; - -<P><FONT COLOR="#FF0000">//The starting point for the worker threads</FONT> -<BR>static void* -<BR>worker(void*arguments){ -<BR>Args *arg= (Args*) arguments; -<BR>for(int i=0;i<arg->iterations_;i++){ -<BR> ACE_DEBUG((LM_DEBUG,"(%t) Trying to get a hold of this iteration\n")); -<BR> {<FONT COLOR="#FF0000">//begin critical section</FONT> -<BR> ACE_Guard<ACE_Token> guard(arg->mutex_); -<BR> <FONT COLOR="#FF0000"> //This is our critical section</FONT> -<BR> ACE_DEBUG((LM_DEBUG,"(%t) This is iteration number %d\n",i)); -<BR><FONT COLOR="#FF0000"> //work</FONT> -<BR> ACE_OS::sleep(2); -<BR> }<FONT COLOR="#FF0000">//end critical section</FONT> -<BR> } -<BR>return 0; -<BR>} -<BR> - -<P>int main(int argc, char*argv[]){ -<BR>if(argc<3){ -<BR> ACE_OS::printf("Usage: egx <number_of_threads> <number_of_iterations> -\n"); -<BR> ACE_OS::exit(1); -<BR> } - -<P><FONT COLOR="#FF0000">//Setup the arguments</FONT> -<BR>Args arg(ACE_OS::atoi(argv[2])); -<BR><FONT COLOR="#FF0000">//Spawn the worker threads</FONT> -<BR>ACE_Thread::spawn_n(ACE_OS::atoi(argv[1]),(ACE_THR_FUNC)worker,(void*)&arg); -<BR>while(ACE_Thread::join(NULL,NULL,NULL)==0); -<BR>} - -<P> <A HREF="ex06.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_4/ex06.html b/docs/tutorials/Chap_4/ex06.html deleted file mode 100644 index d8d96090f18..00000000000 --- a/docs/tutorials/Chap_4/ex06.html +++ /dev/null @@ -1,96 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 6</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "Thread Management"</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 6</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Thread.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/OS.h"</FONT> -<BR><FONT COLOR="#000099">#include </FONT><FONT COLOR="#006600">"ace/Synch_T.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT><FONT COLOR="#006600"> "ace/Synch.h"</FONT> - -<P>static int number=0; -<BR>static int seed=0; - -<P>class Args{ -<BR>public: -<BR>Args(ACE_Condition<ACE_Thread_Mutex> *cond, int threads): -<BR> cond_(cond), threads_(threads){} -<BR>ACE_Condition<ACE_Thread_Mutex> *cond_; -<BR>int threads_; -<BR>}; - -<P>static void* -<BR>worker(void *arguments){ -<BR> Args *arg= (Args*)arguments; -<BR> ACE_DEBUG((LM_DEBUG,"Thread (%t) Created to do some work\n")); -<BR> ::number++; -<BR><FONT COLOR="#FF0000"> //Work</FONT> -<BR> ACE_OS::sleep(ACE_OS::rand()%2); - -<P><FONT COLOR="#FF0000"> //Exiting now</FONT> -<BR> ACE_DEBUG((LM_DEBUG, -<BR> "\tThread (%t) Done! \n\tThe number is now: %d\n",number)); -<BR><FONT COLOR="#FF0000"> //If all threads are done signal main thread -that program can now exit</FONT> -<BR> if(number==arg->threads_){ -<BR> ACE_DEBUG((LM_DEBUG, -<BR> "(%t) Last Thread!\n All threads have done -their job! -<BR> Signal main thread\n")); -<BR> arg->cond_->signal(); -<BR> } -<BR>return 0; -<BR>} -<BR> - -<P>int main(int argc, char *argv[]){ -<BR>if(argc<2){ -<BR> ACE_DEBUG((LM_DEBUG,"Usage: <program_name> <number of threads>\n")); -<BR> ACE_OS::exit(1); -<BR> } -<BR> -<BR>int n_threads=ACE_OS::atoi(argv[1]); - -<P><FONT COLOR="#FF0000">//Setup the random number generator</FONT> -<BR>ACE_OS::srand(::seed); - -<P><FONT COLOR="#FF0000">//Setup arguments for threads</FONT> -<BR>ACE_Thread_Mutex mutex; -<BR>ACE_Condition<ACE_Thread_Mutex> cond(mutex); -<BR>Args arg(&cond,n_threads); - -<P><FONT COLOR="#FF0000">//Spawn off n_threads number of threads</FONT> -<BR>for(int i=0; i<n_threads; i++){ -<BR> if(ACE_Thread::spawn((ACE_THR_FUNC)worker,(void*)&arg, -<BR> THR_DETACHED|THR_NEW_LWP)==-1) -<BR> ACE_DEBUG((LM_DEBUG,"Error in spawning thread\n")); -<BR> } - -<P><FONT COLOR="#FF0000">//Wait for signal indicating that all threads -are done and program can exit</FONT> -<BR>mutex.acquire(); -<BR>if(number!=n_threads) -<BR> cond.wait(); -<BR>ACE_DEBUG((LM_DEBUG,"(%t) Main Thread got signal. Program exiting..\n")); -<BR>mutex.release(); -<BR>ACE_OS::exit(0); -<BR>} - -<P> <A HREF="ex07.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_4/ex07.html b/docs/tutorials/Chap_4/ex07.html deleted file mode 100644 index 680de23b8fd..00000000000 --- a/docs/tutorials/Chap_4/ex07.html +++ /dev/null @@ -1,85 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 7</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "Thread Management"</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 7</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Thread.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/OS.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Synch_T.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Synch.h"</FONT> - -<P>static int number=0; -<BR>static int seed=0; - -<P>class Args{ -<BR>public: -<BR>Args(ACE_Barrier *barrier): -<BR> barrier_(barrier){} -<BR>ACE_Barrier *barrier_; -<BR>}; - -<P>static void* -<BR>worker(void *arguments){ -<BR> Args *arg= (Args*)arguments; -<BR> ACE_DEBUG((LM_DEBUG,"Thread (%t) Created to do some work\n")); -<BR> ::number++; -<BR> -<BR><FONT COLOR="#FF0000"> //Work</FONT> -<BR> ACE_OS::sleep(ACE_OS::rand()%2); - -<P><FONT COLOR="#FF0000"> //Exiting now</FONT> -<BR> ACE_DEBUG((LM_DEBUG, -<BR> "\tThread (%t) Done! \n\tThe number is now: %d\n",number)); -<BR><FONT COLOR="#FF0000"> //Let the barrier know we are done.</FONT> -<BR> arg->barrier_->wait(); -<BR> ACE_DEBUG((LM_DEBUG,"Thread (%t) is exiting \n")); -<BR> return 0; -<BR>} -<BR> - -<P>int main(int argc, char *argv[]){ -<BR>if(argc<2){ -<BR> ACE_DEBUG((LM_DEBUG,"Usage: <program_name> <number of threads>\n")); -<BR> ACE_OS::exit(1); -<BR> } -<BR> -<BR>int n_threads=ACE_OS::atoi(argv[1]); -<BR>ACE_DEBUG((LM_DEBUG,"Preparing to spawn %d threads",n_threads)); -<BR><FONT COLOR="#FF0000">//Setup the random number generator</FONT> -<BR>ACE_OS::srand(::seed); - -<P><FONT COLOR="#FF0000">//Setup arguments for threads</FONT> -<BR>ACE_Barrier barrier(n_threads); -<BR>Args arg(&barrier); - -<P><FONT COLOR="#FF0000">//Spawn off n_threads number of threads</FONT> -<BR>for(int i=0; i<n_threads; i++){ if(ACE_Thread::spawn((ACE_THR_FUNC)worker,(void*)&arg,THR_DETACHED|THR_NEW_LWP)==-1) -<BR> ACE_DEBUG((LM_DEBUG,"Error in spawning thread\n")); -<BR> } - -<P><FONT COLOR="#FF0000">//Wait for all the other threads to let the main -thread</FONT> -<BR><FONT COLOR="#FF0000">// know that they are done using hte barrier</FONT> -<BR>barrier.wait(); -<BR>ACE_DEBUG((LM_DEBUG,"(%t)Other threads are finished. Program exiting..\n")); -<BR>ACE_OS::sleep(2); -<BR>} - -<P> <A HREF="ex08.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_4/ex08.html b/docs/tutorials/Chap_4/ex08.html deleted file mode 100644 index 98333413849..00000000000 --- a/docs/tutorials/Chap_4/ex08.html +++ /dev/null @@ -1,73 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 8</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "Thread Management"</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 8</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Synch_T.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Synch.h"</FONT> - -<P>ACE_Atomic_Op<ACE_Thread_Mutex,int> foo; - -<P>static void* -<BR>worker(void *arg){ -<BR> ACE_UNUSED_ARG(arg); -<BR> foo=5; -<BR> ACE_ASSERT (foo == 5); -<BR> -<BR> ++foo; -<BR> ACE_ASSERT (foo == 6); -<BR> -<BR> --foo; -<BR> ACE_ASSERT (foo == 5); -<BR> -<BR> foo += 10; -<BR> ACE_ASSERT (foo == 15); -<BR> -<BR> foo -= 10; -<BR> ACE_ASSERT (foo == 5); -<BR> -<BR> foo = 5L; -<BR> ACE_ASSERT (foo == 5); -<BR> return 0; -<BR>} - -<P>int main(int argc, char *argv[]){ -<BR>if(argc<2){ -<BR> ACE_DEBUG((LM_DEBUG,"Usage: <program_name> <number of threads>\n")); -<BR> ACE_OS::exit(1); -<BR> } -<BR> -<BR>int n_threads=ACE_OS::atoi(argv[1]); -<BR>ACE_DEBUG((LM_DEBUG,"Preparing to spawn %d threads\n",n_threads)); -<BR> - -<P><FONT COLOR="#FF0000">//Spawn off n_threads number of threads</FONT> -<BR>for(int i=0; i<n_threads; i++){ -<BR> if(ACE_Thread::spawn((ACE_THR_FUNC)worker,0,THR_DETACHED|THR_NEW_LWP)==-1) -<BR> ACE_DEBUG((LM_DEBUG,"Error in spawning thread\n")); -<BR> } - -<P><FONT COLOR="#FF0000">//Wait for all the other threads to let the main -thread know when it is time to exit</FONT> -<BR>while(ACE_Thread::join(NULL,NULL,NULL)==0); -<BR>ACE_DEBUG((LM_DEBUG,"(%t)Other threads are finished. Program exiting..\n")); -<BR>} - -<P> <A HREF="../Chap_5/ex01.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_5/Chap_5.zip b/docs/tutorials/Chap_5/Chap_5.zip Binary files differdeleted file mode 100644 index 5eb2b6646d0..00000000000 --- a/docs/tutorials/Chap_5/Chap_5.zip +++ /dev/null diff --git a/docs/tutorials/Chap_5/ex01.html b/docs/tutorials/Chap_5/ex01.html deleted file mode 100644 index b50a03627ee..00000000000 --- a/docs/tutorials/Chap_5/ex01.html +++ /dev/null @@ -1,76 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 1</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "The Reactor" (Event -Management)</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#FF0000">//Example 1</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600"><signal.h></FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Reactor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Event_Handler.h"</FONT> - -<P><FONT COLOR="#FF0000">//Create our subclass to handle the signal events</FONT> -<BR><FONT COLOR="#FF0000">//that we wish to handle. Since we know that -this particular</FONT> -<BR><FONT COLOR="#FF0000">//event handler is going to be using signals -we only overload the</FONT> -<BR><FONT COLOR="#FF0000">//handle_signal method.</FONT> - -<P>class -<BR>MyEventHandler: public ACE_Event_Handler{ -<BR>int -<BR>handle_signal(int signum, siginfo_t*,ucontext_t*){ -<BR> switch(signum){ -<BR> case SIGWINCH: -<BR> ACE_DEBUG((LM_DEBUG, "You pressed SIGWINCH \n")); -<BR> break; - -<P> case SIGINT: -<BR> ACE_DEBUG((LM_DEBUG, "You pressed SIGINT \n")); -<BR> break; -<BR> } -<BR> return 0; -<BR> } -<BR>}; - -<P>int main(int argc, char *argv[]){ -<BR><FONT COLOR="#FF0000"> //instantiate the handler</FONT> -<BR> MyEventHandler *eh =new MyEventHandler; - -<P><FONT COLOR="#FF0000">//Register the handler asking to call back when -either SIGWINCH</FONT> -<BR><FONT COLOR="#FF0000">//or SIGINT signals occur. Note that in both -the cases we asked the</FONT> -<BR><FONT COLOR="#FF0000">//Reactor to call back the same Event_Handler -i.e., MyEventHandler.</FONT> -<BR><FONT COLOR="#FF0000">//This is the reason why we had to write a switch -statement in the handle_signal()</FONT> -<BR><FONT COLOR="#FF0000">//method above. Also note that the</FONT> -<BR><FONT COLOR="#FF0000">//ACE_Reactor is being used as a Singleton object -(Singleton pattern)</FONT> - -<P> ACE_Reactor::instance()->register_handler(SIGWINCH,eh); -<BR> ACE_Reactor::instance()->register_handler(SIGINT,eh); -<BR> while(1) -<BR> <FONT COLOR="#FF0000"> //Start the reactors event loop</FONT> -<BR> ACE_Reactor::instance()->handle_events(); -<BR>} - -<P> <A HREF="ex02.html">Next Example</A> -<BR> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_5/ex02.html b/docs/tutorials/Chap_5/ex02.html deleted file mode 100644 index 8652d2b806f..00000000000 --- a/docs/tutorials/Chap_5/ex02.html +++ /dev/null @@ -1,149 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 2</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "The Reactor" (Event -Management)</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 2</FONT> -<BR><FONT COLOR="#000099">#include</FONT><FONT COLOR="#006600"> "ace/Reactor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/SOCK_Acceptor.h"</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">PORT_NO -19998</FONT> -<BR>typedef ACE_SOCK_Acceptor Acceptor; -<BR><FONT COLOR="#FF0000">//forward declaration</FONT> -<BR>class My_Accept_Handler; - -<P>class -<BR>My_Input_Handler: public ACE_Event_Handler{ -<BR>public: -<BR><FONT COLOR="#FF0000"> //Constructor</FONT> -<BR> My_Input_Handler(){ -<BR> ACE_DEBUG((LM_DEBUG,?Constructor\n?); -<BR> } -<BR> -<BR><FONT COLOR="#FF0000"> //Called back to handle any input receieved</FONT> -<BR> int -<BR> handle_input(ACE_HANDLE){ -<BR><FONT COLOR="#FF0000"> //receive the data</FONT> -<BR> peer_i().recv_n(data,12); -<BR> ACE_DEBUG((LM_DEBUG,?%s\n?,data)); -<BR> -<BR> <FONT COLOR="#FF0000"> // do something with the input received.</FONT> -<BR><FONT COLOR="#FF0000"> // ...</FONT> - -<P><FONT COLOR="#FF0000"> //keep yourself registered with the reactor</FONT> -<BR> return 0; -<BR> } -<BR> -<BR><FONT COLOR="#FF0000"> //Used by the reactor to determine the -underlying handle</FONT> -<BR> ACE_HANDLE -<BR> get_handle()const { -<BR> return this->peer_i().get_handle(); -<BR> } -<BR> -<BR><FONT COLOR="#FF0000"> //Returns a reference to the underlying -stream.</FONT> -<BR> ACE_SOCK_Stream & -<BR> peer_i(){ -<BR> return this->peer_; -<BR> } - -<P>private: -<BR> ACE_SOCK_Stream peer_; -<BR> char data [12]; -<BR>}; -<BR> - -<P>class -<BR>My_Accept_Handler: public ACE_Event_Handler{ -<BR>public: -<BR><FONT COLOR="#FF0000">//Constructor</FONT> -<BR> My_Accept_Handler(ACE_Addr &addr){ -<BR> this->open(addr); -<BR> } - -<P><FONT COLOR="#FF0000">//Open the peer_acceptor so it starts to ?listen?</FONT> -<BR><FONT COLOR="#FF0000">//for incoming clients.</FONT> -<BR> int -<BR> open(ACE_Addr &addr){ -<BR> peer_acceptor.open(addr); -<BR> return 0; -<BR> } - -<P><FONT COLOR="#FF0000">//Overload the handle input method</FONT> -<BR> int -<BR> handle_input(ACE_HANDLE handle){ -<BR> <FONT COLOR="#FF0000"> //Client has requested connection to server.</FONT> -<BR><FONT COLOR="#FF0000"> //Create a handler to handle the connection</FONT> -<BR> My_Input_Handler *eh= new My_Input_Handler(); - -<P> <FONT COLOR="#FF0000">//Accept the connection ?into? the Event -Handler</FONT> -<BR> if (this->peer_acceptor.accept (eh->peer (), <FONT COLOR="#FF0000">// -stream</FONT> -<BR> 0, <FONT COLOR="#FF0000">// remote address</FONT> -<BR> 0, <FONT COLOR="#FF0000">// timeout</FONT> -<BR> 1) ==-1) <FONT COLOR="#FF0000">//restart -if interrupted</FONT> -<BR> ACE_DEBUG((LM_ERROR,"Error in connection\n")); - -<P> ACE_DEBUG((LM_DEBUG,"Connection established\n")); - -<P><FONT COLOR="#FF0000"> //Register the input event handler for -reading</FONT> -<BR> ACE_Reactor::instance()-> -<BR> register_handler(eh,ACE_Event_Handler::READ_MASK); - -<P><FONT COLOR="#FF0000"> //Unregister as the acceptor is not expecting -new clients</FONT> -<BR> return -1; -<BR> } - -<P><FONT COLOR="#FF6666"> //Used by the reactor to determine the underlying -handle</FONT> -<BR> ACE_HANDLE -<BR> get_handle(void) const{ -<BR> return this->peer_acceptor.get_handle(); -<BR> } -<BR>private: -<BR> Acceptor peer_acceptor; -<BR>}; - -<P>int main(int argc, char * argv[]){ -<BR><FONT COLOR="#FF0000"> //Create an address on which to receive -connections</FONT> -<BR> ACE_INET_Addr addr(PORT_NO); - -<P><FONT COLOR="#FF0000">//Create the Accept Handler which automatically -begins to "listen"</FONT> -<BR><FONT COLOR="#FF0000">//for client requests for connections</FONT> -<BR> My_Accept_Handler *eh=new My_Accept_Handler(addr); - -<P><FONT COLOR="#FF0000">//Register the reactor to call back when incoming -client connects</FONT> -<BR>ACE_Reactor::instance()->register_handler(eh, -<BR> ACE_Event_Handler::ACCEPT_MASK); - -<P><FONT COLOR="#FF0000">//Start the event loop</FONT> -<BR>while(1) -<BR> ACE_Reactor::instance()->handle_events(); -<BR>} - -<P> <A HREF="ex03.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_5/ex03.html b/docs/tutorials/Chap_5/ex03.html deleted file mode 100644 index 0928cb6a6d5..00000000000 --- a/docs/tutorials/Chap_5/ex03.html +++ /dev/null @@ -1,87 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 3</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "The Reactor" (Event -Management)</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#FF0000">//Example 3</FONT> -<BR><FONT COLOR="#000099">#include</FONT> "<FONT COLOR="#006600">ace/Timer_Queue.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> "<FONT COLOR="#006600">ace/Reactor.h"</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">NUMBER_TIMERS -10</FONT> - -<P>static int done = 0; -<BR>static int count = 0; - -<P>class Time_Handler : public ACE_Event_Handler -<BR>{ -<BR>public: -<BR> <FONT COLOR="#FF0000">//Method which is called back by the Reactor -when timeout occurs.</FONT> -<BR> virtual int handle_timeout (const ACE_Time_Value &tv, -<BR> const void *arg){ -<BR> long current_count = long (arg); -<BR> ACE_ASSERT (current_count == count); -<BR> ACE_DEBUG ((LM_DEBUG, "%d: Timer #%d timed out at %d!\n", -<BR> count, current_count, tv.sec())); -<BR> - -<P><FONT COLOR="#FF0000">//Increment count</FONT> -<BR> count ++; - -<P><FONT COLOR="#FF0000">//Make sure assertion doesnt fail for missing -5th timer.</FONT> -<BR> if (count ==5) -<BR> count++; -<BR> -<BR><FONT COLOR="#FF0000"> //If all timers done then set done flag</FONT> -<BR> if (current_count == NUMBER_TIMERS - 1) -<BR> done = 1; -<BR><FONT COLOR="#FF0000"> //Keep yourself registered with the Reactor.</FONT> -<BR> return 0; -<BR> } -<BR>}; - -<P>int -<BR>main (int, char *[]) -<BR>{ -<BR> ACE_Reactor reactor; -<BR> Time_Handler *th=new Time_Handler; -<BR> int timer_id[NUMBER_TIMERS]; -<BR> int i; - -<P> for (i = 0; i < NUMBER_TIMERS; i++) -<BR> timer_id[i] = reactor.schedule_timer (th, -<BR> (const void *) i, <FONT COLOR="#FF0000">// argument sent -to handle_timeout()</FONT> -<BR> ACE_Time_Value (2 * i + 1));<FONT COLOR="#FF0000"> //set -timer to go off with delay</FONT> - -<P><FONT COLOR="#CC0000"> //Cancel the fifth timer before it goes -off</FONT> -<BR> reactor.cancel_timer(timer_id[5]);<FONT COLOR="#FF0000">//Timer -ID of timer to be removed</FONT> - -<P> while (!done) -<BR> reactor.handle_events (); - -<P> return 0; -<BR>} - -<P> <A HREF="ex04.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_5/ex04.html b/docs/tutorials/Chap_5/ex04.html deleted file mode 100644 index 95971be40b3..00000000000 --- a/docs/tutorials/Chap_5/ex04.html +++ /dev/null @@ -1,85 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 4</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "The Reactor" (Event -Management)</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#FF0000">//Example 4</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Reactor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Event_Handler.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Synch_T.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Thread_Manager.h"</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">WAIT_TIME -1</FONT> -<BR><FONT COLOR="#000099">#define</FONT><FONT COLOR="#663366"> SLEEP_TIME -2</FONT> - -<P>class My_Handler: public ACE_Event_Handler{ -<BR> public: - -<P><FONT COLOR="#FF0000"> //Start the event handling process.</FONT> -<BR> My_Handler(){ -<BR> ACE_DEBUG((LM_DEBUG,"Event Handler created\n")); -<BR> ACE_Reactor::instance()->max_notify_iterations(5); -<BR> return 0; -<BR> } - -<P><FONT COLOR="#FF0000">//Perform the notifications i.e., notify the reactor -10 times</FONT> -<BR> void perform_notifications(){ -<BR> for(int i=0;i<10;i++) -<BR> ACE_Reactor::instance()-> -<BR> notify(this,ACE_Event_Handler::READ_MASK); -<BR> } -<BR> -<BR><FONT COLOR="#FF0000"> //The actual handler which in this case -will handle the notifications</FONT> -<BR> int handle_input(int){ -<BR> ACE_DEBUG((LM_DEBUG,"Got notification # %d\n",no)); -<BR> no++; -<BR> return 0; -<BR> } -<BR>private: -<BR> static int no; -<BR>}; - -<P><FONT COLOR="#FF0000">//Static members</FONT> -<BR>int My_Handler::no=1; -<BR> - -<P>int main(int argc, char *argv[]){ -<BR><FONT COLOR="#FF0000"> //Instantiating the handler</FONT> -<BR> My_Handler handler; -<BR> -<BR><FONT COLOR="#FF0000"> //The done flag is set to not done yet.</FONT> -<BR> int done=0; - -<P>while(1){ -<BR> <FONT COLOR="#FF0000"> //After WAIT_TIME the handle_events will -fall through if no events arrive.</FONT> -<BR> ACE_Reactor::instance()->handle_events(ACE_Time_Value(WAIT_TIME)); -<BR> if(!done){ -<BR> handler.perform_notifications(); -<BR> done=1; -<BR> } -<BR> sleep(SLEEP_TIME); -<BR> } -<BR>} - -<P> <A HREF="ex05.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_5/ex05.html b/docs/tutorials/Chap_5/ex05.html deleted file mode 100644 index 80422683cd6..00000000000 --- a/docs/tutorials/Chap_5/ex05.html +++ /dev/null @@ -1,88 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 5</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "The Reactor" (Event -Management)</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 5</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Reactor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Event_Handler.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Synch_T.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Thread_Manager.h"</FONT> - -<P>class My_Handler: public ACE_Event_Handler{ -<BR>public: -<BR><FONT COLOR="#FF0000"> //Start the event handling process.</FONT> -<BR> My_Handler(){ -<BR> ACE_DEBUG((LM_DEBUG,"Got open\n")); -<BR> activate_threads(); -<BR> ACE_Reactor::instance()->max_notify_iterations(5); -<BR> return 0; -<BR> } - -<P><FONT COLOR="#FF0000">//Spawn a separate thread so that it notifies -the reactor</FONT> -<BR> void activate_threads(){ -<BR> ACE_Thread_Manager::instance() -<BR> ->spawn((ACE_THR_FUNC)svc_start,(void*)this); -<BR> } -<BR> -<BR><FONT COLOR="#FF0000"> //Notify the Reactor 10 times.</FONT> -<BR> void svc(){ -<BR> for(int i=0;i<10;i++) -<BR> ACE_Reactor::instance() -<BR> ->notify(this, ACE_Event_Handler::READ_MASK); -<BR> } - -<P><FONT COLOR="#FF0000">//The actual handler which in this case will handle -the notifications</FONT> -<BR> int handle_input(int){ -<BR> ACE_DEBUG((LM_DEBUG, ?Got notification # %d\n?, no)); -<BR> no++; -<BR> return 0; -<BR> } - -<P> <FONT COLOR="#FF0000">//The entry point for the new thread that -is to be created.</FONT> -<BR> static int svc_start(void* arg); -<BR>private: -<BR> static int no; -<BR>}; -<BR> - -<P><FONT COLOR="#FF0000">//Static members</FONT> -<BR>int My_Handler::no=1; -<BR>int My_Handler::svc_start(void* arg){ -<BR> My_Handler *eh= (My_Handler*)arg; -<BR> eh->svc(); -<BR> return -1; <FONT COLOR="#FF0000">//de-register from the reactor</FONT> -<BR> } - -<P>int main(int argc, char *argv[]){ -<BR> ACE_DEBUG((LM_DEBUG,"Starting test \n")); -<BR> My_Handler handler; - -<P> while(1){ -<BR> ACE_Reactor::instance()->handle_events(); -<BR> sleep(3); -<BR> } -<BR>} -<BR> -<BR> -<BR> <A HREF="../Chap_6/ex01.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_6/Chap_6.zip b/docs/tutorials/Chap_6/Chap_6.zip Binary files differdeleted file mode 100644 index fcfd5455cba..00000000000 --- a/docs/tutorials/Chap_6/Chap_6.zip +++ /dev/null diff --git a/docs/tutorials/Chap_6/ex01.html b/docs/tutorials/Chap_6/ex01.html deleted file mode 100644 index 473c1c3b0e9..00000000000 --- a/docs/tutorials/Chap_6/ex01.html +++ /dev/null @@ -1,82 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 1</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "The Acceptor/Connector" -(Connection Initialization)</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#FF0000">//Example 1</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Reactor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT><FONT COLOR="#006600"> "ace/Svc_Handler.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Acceptor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT><FONT COLOR="#006600"> "ace/Synch.h"</FONT> -<BR><FONT COLOR="#000099">#include </FONT><FONT COLOR="#006600">"ace/SOCK_Acceptor.h"</FONT> - -<P><FONT COLOR="#FF0000">//Create a Service Handler whose open() method -will be called back automatically.</FONT> -<BR><FONT COLOR="#FF0000">//This class MUST derive from ACE_Svc_Handler -which is an interface and</FONT> -<BR><FONT COLOR="#FF0000">//as can be seen is a template container class -itself. The first parameter to //ACE_Svc_Handler is the underlying stream -that it may use for communication.</FONT> -<BR><FONT COLOR="#FF0000">//Since we are using TCP sockets the stream is -ACE_SOCK_STREAM.</FONT> -<BR><FONT COLOR="#FF0000">//The second is the internal synchronization -mechanism it could use.</FONT> -<BR><FONT COLOR="#FF0000">//Since we have a single threaded application -we pass it a "null" lock</FONT> -<BR><FONT COLOR="#FF0000">//which will do nothing.</FONT> - -<P>class My_Svc_Handler: -<BR> public ACE_Svc_Handler <ACE_SOCK_STREAM,ACE_NULL_SYNCH>{ -<BR><FONT COLOR="#FF0000">//the open method which will be called back automatically -after the</FONT> -<BR><FONT COLOR="#FF0000">//connection has been established</FONT>. - -<P>public: -<BR>int open(void*){ -<BR> cout<<?Connection established?<<endl; -<BR> } -<BR>}; -<BR><FONT COLOR="#FF0000">// Create the acceptor as described above.</FONT> -<BR>typedef ACE_Acceptor<My_Svc_Handler,ACE_SOCK_ACCEPTOR> MyAcceptor; - -<P>int main(int argc, char* argv[]){ -<BR><FONT COLOR="#FF0000">//create the address on which we wish to -connect. The constructor takes</FONT> -<BR><FONT COLOR="#FF0000">//the port number on which to listen and will -automatically take the hosts</FONT> -<BR><FONT COLOR="#FF0000">//IP address as the IP Address for the addr object</FONT> - -<P>ACE_INET_Addr addr(PORT_NUM); - -<P><FONT COLOR="#FF0000">//instantiate the appropriate acceptor object -with the address on which we wish to</FONT> -<BR><FONT COLOR="#FF0000">//accept and the Reactor instance we want to -use. In this case we just use the global</FONT> -<BR><FONT COLOR="#FF0000">//ACE_Reactor singleton. (Read more about the -reactor in the previous chapter)</FONT> -<BR>MyAcceptor acceptor(address, ACE_Reactor::instance()); - -<P>while(1) -<BR><FONT COLOR="#FF0000"> // Start the reactors event loop</FONT> -<BR> ACE_Reactor::instance()->handle_events(); -<BR>} - -<P> <A HREF="ex02.html">Next Example</A> -<BR> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_6/ex02.html b/docs/tutorials/Chap_6/ex02.html deleted file mode 100644 index fffb3b64adb..00000000000 --- a/docs/tutorials/Chap_6/ex02.html +++ /dev/null @@ -1,95 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 2</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "The Acceptor/Connector" -(Connection Initialization)</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 2</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Reactor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Svc_Handler.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Acceptor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Synch.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/SOCK_Acceptor.h"</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">PORT_NUM -10101</FONT> -<BR><FONT COLOR="#000099">#define</FONT><FONT COLOR="#663366"> DATA_SIZE -12</FONT> - -<P><FONT COLOR="#FF0000">//forward declaration</FONT> -<BR>class My_Svc_Handler; - -<P><FONT COLOR="#FF0000">//Create the Acceptor class</FONT> -<BR>typedef ACE_Acceptor<My_Svc_Handler,ACE_SOCK_ACCEPTOR> MyAcceptor; - -<P><FONT COLOR="#FF0000">//Create a service handler similar to as seen -in example 1.</FONT> -<BR><FONT COLOR="#FF0000">//Except this time include the handle_input() -method which will be</FONT> -<BR><FONT COLOR="#FF0000">//called back automatically by the reactor when -new data arrives</FONT> -<BR><FONT COLOR="#FF0000">//on the newly established connection</FONT> -<BR>class My_Svc_Handler: -<BR> public ACE_Svc_Handler <ACE_SOCK_STREAM,ACE_NULL_SYNCH>{ -<BR>public: -<BR>My_Svc_Handler(){ -<BR> data= new char[DATA_SIZE]; -<BR> } -<BR>int open(void*){ -<BR> ACE_DEBUG((LM_DEBUG,"Connection established")); - -<P><FONT COLOR="#FF0000"> //Register the service handler with the -reactor</FONT> -<BR> ACE_Reactor::instance()->register_handler(this, -<BR> ACE_Event_Handler::READ_MASK); -<BR> return 0; -<BR> } - -<P>int handle_input(ACE_HANDLE){ -<BR> <FONT COLOR="#FF0000">//After using the peer() method of ACE_Svc_Handler -to obtain a</FONT> -<BR><FONT COLOR="#FF0000">//reference to the underlying stream of the service -handler class</FONT> -<BR><FONT COLOR="#FF0000">//we call recv_n() on it to read the data which -has been received.</FONT> -<BR><FONT COLOR="#FF0000">//This data is stored in the data array and then -printed out</FONT> -<BR> peer().recv_n(data,DATA_SIZE); -<BR> ACE_OS::printf("<< %s\n",data); - -<P> <FONT COLOR="#FF0000">//keep yourself registered with the reactor</FONT> -<BR> return 0; -<BR> } -<BR>private: -<BR> char* data; -<BR>}; - -<P>int main(int argc, char* argv[]){ -<BR> ACE_INET_Addr addr(PORT_NUM); -<BR><FONT COLOR="#FF0000"> //create the acceptor</FONT> -<BR> MyAcceptor acceptor(addr, <FONT COLOR="#FF0000">//address to -accept on</FONT> -<BR> ACE_Reactor::instance()); <FONT COLOR="#FF0000">//the reactor -to use</FONT> - -<P>while(1) -<BR><FONT COLOR="#FF0000"> //Start the reactor?s event loop</FONT> -<BR> ACE_Reactor::instance()->handle_events(); -<BR>} - -<P> <A HREF="ex03.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_6/ex03.html b/docs/tutorials/Chap_6/ex03.html deleted file mode 100644 index fd88fd05eaf..00000000000 --- a/docs/tutorials/Chap_6/ex03.html +++ /dev/null @@ -1,51 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 3</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "The Acceptor/Connector" -(Connection Initialization)</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example3</FONT> - -<P>class My_Svc_Handler: -<BR>public ACE_Svc_Handler <ACE_LSOCK_STREAM,ACE_NULL_SYNCH>{ -<BR>public: -<BR>int open(void*){ -<BR> ACE_DEBUG((LM_DEBUG,"Connection established")); -<BR> ACE_Reactor::instance() ->register_handler(this,ACE_Event_Handler::READ_MASK); -<BR> } - -<P> int handle_input(ACE_HANDLE){ -<BR> char* data= new char[DATA_SIZE]; -<BR> peer().recv_n(data,DATA_SIZE); -<BR> ACE_OS::printf("<< %s\n",data); -<BR> return 0; -<BR> } -<BR>}; - -<P>typedef ACE_Acceptor<My_Svc_Handler,ACE_LSOCK_ACCEPTOR> MyAcceptor; - -<P>int main(int argc, char* argv[]){ -<BR> ACE_UNIX_Addr addr("/tmp/addr.ace"); -<BR> MyAcceptor acceptor(address, ACE_Reactor::instance()); - -<P>while(1) <FONT COLOR="#FF0000">/* Start the reactors event loop */</FONT> -<BR> ACE_Reactor::instance()->handle_events(); -<BR>} - -<P> <A HREF="ex04.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_6/ex04.html b/docs/tutorials/Chap_6/ex04.html deleted file mode 100644 index c0577bb1752..00000000000 --- a/docs/tutorials/Chap_6/ex04.html +++ /dev/null @@ -1,45 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 4</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "The Acceptor/Connector" -(Connection Initialization)</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 4 (Use in conjunction with other examples -to create running example)</FONT><FONT COLOR="#CC0000"></FONT> - -<P>typedef ACE_Connector<My_Svc_Handler,ACE_SOCK_CONNECTOR> MyConnector; - -<P>int main(int argc, char * argv[]){ -<BR> ACE_INET_Addr addr(PORT_NO,HOSTNAME); -<BR> My_Svc_Handler * handler= new My_Svc_Handler; - -<P><FONT COLOR="#FF0000">//Create the connector</FONT> -<BR> MyConnector connector; - -<P><FONT COLOR="#FF0000">//Connects to remote machine</FONT> -<BR> if(connector.connect(handler,addr)==-1) -<BR> ACE_ERROR(LM_ERROR,?%P|%t, %p?,?Connection failed?); -<BR> - -<P><FONT COLOR="#FF0000">//Registers with the Reactor</FONT> -<BR> while(1) -<BR> ACE_Reactor::instance()->handle_events(); -<BR>} - -<P> <A HREF="ex05.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_6/ex05.html b/docs/tutorials/Chap_6/ex05.html deleted file mode 100644 index 9763486a71f..00000000000 --- a/docs/tutorials/Chap_6/ex05.html +++ /dev/null @@ -1,130 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 5</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "The Acceptor/Connector" -(Connection Initialization)</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 5</FONT> -<BR><FONT COLOR="#000099">#include</FONT><FONT COLOR="#006600"> "ace/Reactor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> "<FONT COLOR="#006600">ace/Svc_Handler.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> "<FONT COLOR="#006600">ace/Acceptor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Synch.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/SOCK_Acceptor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Thread.h"</FONT> - -<P><FONT COLOR="#FF0000">//Add our own Reactor singleton</FONT> -<BR>typedef ACE_Singleton<ACE_Reactor,ACE_Null_Mutex> Reactor; -<BR><FONT COLOR="#FF0000">//Create an Acceptor</FONT> -<BR>typedef ACE_Acceptor<MyServiceHandler,ACE_SOCK_ACCEPTOR> Acceptor; -<BR><FONT COLOR="#FF0000">//Create a Connector</FONT> -<BR>typedef ACE_Connector<MyServiceHandler,ACE_SOCK_CONNECTOR> Connector; - -<P>class MyServiceHandler: -<BR>public ACE_Svc_Handler<ACE_SOCK_STREAM,ACE_NULL_SYNCH>{ -<BR>public: -<BR><FONT COLOR="#FF0000"> //Used by the two threads "globally" to -determine their peer stream</FONT> -<BR> static ACE_SOCK_Stream* Peer; - -<P><FONT COLOR="#FF0000">//Thread ID used to identify the threads</FONT> -<BR> ACE_thread_t t_id; - -<P>int open(void*){ -<BR> ACE_DEBUG((LM_DEBUG,"Acceptor: received new connection\n")); - -<P><FONT COLOR="#FF0000">//Register with the reactor to remember this handlle</FONT> -<BR> Reactor::instance() ->register_handler(this,ACE_Event_Handler::READ_MASK); - -<P><FONT COLOR="#FF0000">//Determine the peer stream and record it globally</FONT> -<BR> MyServiceHandler::Peer=&peer(); -<BR> -<BR> <FONT COLOR="#FF0000">//Spawn new thread to send string every -second</FONT> -<BR> ACE_Thread::spawn((ACE_THR_FUNC)send_data,0,THR_NEW_LWP,&t_id); -<BR> -<BR> <FONT COLOR="#FF0000"> //keep the service handler registered -by returning 0 to the reactor</FONT> -<BR> return 0; -<BR> } -<BR> - -<P>static void* send_data(void*){ -<BR> while(1){ -<BR> ACE_DEBUG((LM_DEBUG,"Hello World\n")); -<BR> Peer->send_n("Hello World",sizeof("Hello World")); -<BR> -<BR> <FONT COLOR="#FF0000">//Go to sleep for a second before -sending again</FONT> -<BR> ACE_OS::sleep(1); -<BR> } -<BR> return 0; -<BR> } -<BR> - -<P>int handle_input(ACE_HANDLE){ -<BR> char* data= new char[12]; -<BR> -<BR> <FONT COLOR="#FF0000"> //Check if peer aborted the connection</FONT> -<BR> if(Peer.recv_n(data,12)==0){ -<BR> ACE_DEBUG((LM_DEBUG,"Peer probably aborted connection\n")); -<BR> ACE_Thread::cancel(t_id); <FONT COLOR="#CC0000">//kill -sending thread ..</FONT> -<BR> return -1; <FONT COLOR="#FF0000">//de-register from the -Reactor.</FONT> -<BR> } - -<P> <FONT COLOR="#FF0000"> //Show what you got..</FONT> -<BR> ACE_DEBUG((LM_DEBUG,"<< %s\n",data)); -<BR> -<BR> <FONT COLOR="#FF0000">//keep yourself registered</FONT> -<BR> return 0; -<BR> } -<BR>}; - -<P><FONT COLOR="#FF0000">//Global stream identifier used by both threads</FONT> -<BR>ACE_SOCK_Stream * MyServiceHandler::Peer=0; -<BR> - -<P>void main_accept(){ -<BR> ACE_INET_Addr addr(PORT_NO); -<BR> Acceptor myacceptor(addr,Reactor::instance()); -<BR> while(1) -<BR> Reactor::instance()->handle_events(); - -<P> return 0; -<BR> } - -<P>void main_connect(){ -<BR> ACE_INET_Addr addr(PORT_NO,HOSTNAME); -<BR> Connector myconnector; -<BR> myconnector.connect(my_svc_handler,addr); -<BR> while(1) -<BR> Reactor::instance()->handle_events(); - -<P> } -<BR> - -<P>int main(int argc, char* argv[]){ -<BR><FONT COLOR="#FF0000"> // Use ACE_Get_Opt to parse and obtain -arguments and then call the</FONT> -<BR> <FONT COLOR="#FF0000">// approriate function for accept or connect.</FONT> -<BR><FONT COLOR="#CC0000">//...</FONT> -<BR>} -<BR> -<BR> <A HREF="ex06.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_6/ex06.html b/docs/tutorials/Chap_6/ex06.html deleted file mode 100644 index 9c6fd395d52..00000000000 --- a/docs/tutorials/Chap_6/ex06.html +++ /dev/null @@ -1,135 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 6</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "The Acceptor/Connector" -(Connection Initialization)</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 6</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Reactor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Svc_Handler.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Acceptor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Synch.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/SOCK_Acceptor.h"</FONT> - -<P>class MyServiceHandler; //forward declaration -<BR>typedef ACE_Singleton<ACE_Reactor,ACE_Null_Mutex> Reactor; -<BR>typedef ACE_Acceptor<MyServiceHandler,ACE_SOCK_ACCEPTOR> Acceptor; - -<P>class MyServiceHandler: -<BR>public ACE_Svc_Handler<ACE_SOCK_STREAM,ACE_MT_SYNCH>{ -<BR><FONT COLOR="#FF0000">// The two thread names are kept here</FONT> -<BR>ACE_thread_t thread_names[2]; - -<P>public: -<BR>int open(void*){ -<BR> ACE_DEBUG((LM_DEBUG, "Acceptor: received new connection \n")); -<BR> -<BR> <FONT COLOR="#FF0000">//Register with the reactor to remember -this handler..</FONT> -<BR> Reactor::instance() ->register_handler(this,ACE_Event_Handler::READ_MASK); -<BR> ACE_DEBUG((LM_DEBUG,"Acceptor: ThreadID:(%t) open\n")); - -<P><FONT COLOR="#CC0000"> //Create two new threads to create and send -messages to the remote machine.</FONT> -<BR> activate(THR_NEW_LWP, -<BR> 2, <FONT COLOR="#FF0000">//2 new threads</FONT> -<BR> 0, <FONT COLOR="#FF0000">//force active false, if already -created dont try again.</FONT> -<BR> ACE_DEFAULT_THREAD_PRIORITY,<FONT COLOR="#FF0000">//Use -default thread priority</FONT> -<BR> -1, -<BR> this,<FONT COLOR="#FF0000">//Which ACE_Task object to -create? In this case this one.</FONT> -<BR> 0,<FONT COLOR="#FF0000">// dont care about thread handles -used</FONT> -<BR> 0,<FONT COLOR="#FF0000">// dont care about where stacks -are created</FONT> -<BR> 0,<FONT COLOR="#FF0000">//dont care about stack sizes</FONT> -<BR> thread_names); <FONT COLOR="#FF0000">// keep identifiers -in thread_names</FONT> -<BR> -<BR><FONT COLOR="#FF0000"> //keep the service handler registered with -the acceptor.</FONT> -<BR> return 0; -<BR> } - -<P>void send_message1(void){ -<BR> <FONT COLOR="#FF0000">//Send message type 1</FONT> -<BR> ACE_DEBUG((LM_DEBUG,"(%t)Sending message >>")); - -<P> <FONT COLOR="#FF0000">//Send the data to the remote peer</FONT> -<BR> ACE_DEBUG((LM_DEBUG,"Sent message1")); -<BR> peer().send_n("Message1",LENGTH_MSG_1); -<BR> } <FONT COLOR="#FF0000">//end send_message1</FONT> - -<P>int send_message2(void){ -<BR> <FONT COLOR="#FF0000">//Send message type 1</FONT> -<BR> ACE_DEBUG((LM_DEBUG,"(%t)Sending message >>")); - -<P> <FONT COLOR="#FF0000">//Send the data to the remote peer</FONT> -<BR> ACE_DEBUG((LM_DEBUG,"Sent Message2")); -<BR> peer().send_n("Message2",LENGTH_MSG_2); -<BR> }<FONT COLOR="#FF0000">//end send_message_2</FONT> -<BR> -<BR>int svc(void){ -<BR> ACE_DEBUG( (LM_DEBUG,?(%t) Svc thread \n?)); -<BR> -<BR> if(ACE_Thread::self()== thread_names[0]) -<BR> while(1) send_message1(); <FONT COLOR="#FF0000">//send message -1s forever</FONT> -<BR> else -<BR> while(1) send_message2(); <FONT COLOR="#FF0000">//send message -2s forever</FONT> -<BR> return 0; <FONT COLOR="#FF0000">// keep the compiler happy.</FONT> -<BR>} -<BR> -<BR>int handle_input(ACE_HANDLE){ -<BR> ACE_DEBUG((LM_DEBUG,?(%t) handle_input ::?)); -<BR> char* data= new char[13]; -<BR> -<BR> <FONT COLOR="#FF0000">//Check if peer aborted the connection</FONT> -<BR> if(peer().recv_n(data,12)==0){ -<BR> ACE_OS::printf("Peer probably aborted connection\n"); -<BR> return -1; <FONT COLOR="#FF0000">//de-register from the Reactor.</FONT> -<BR> } -<BR> -<BR> <FONT COLOR="#FF0000">//Show what you got..</FONT> -<BR> ACE_OS::printf("<< %s\n",data); -<BR> -<BR> <FONT COLOR="#FF0000">//keep yourself registered</FONT> -<BR> return 0; -<BR> -<BR> } -<BR>}; - -<P>int main(int argc, char* argv[]){ -<BR> ACE_INET_Addr addr(10101); -<BR> ACE_DEBUG((LM_DEBUG,"Thread: (%t) main\n")); - -<P> <FONT COLOR="#FF0000">//Prepare to accept connections</FONT> -<BR> Acceptor myacceptor(addr,Reactor::instance()); - -<P><FONT COLOR="#FF0000"> // wait for something to happen.</FONT> -<BR> while(1) -<BR> Reactor::instance()->handle_events(); -<BR> -<BR> return 0; -<BR>} - -<P> <A HREF="ex07.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_6/ex07.html b/docs/tutorials/Chap_6/ex07.html deleted file mode 100644 index 60053887cf5..00000000000 --- a/docs/tutorials/Chap_6/ex07.html +++ /dev/null @@ -1,174 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 7</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "The Acceptor/Connector" -(Connection Initialization)</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 7</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Reactor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Svc_Handler.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT><FONT COLOR="#006600"> "ace/Acceptor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT><FONT COLOR="#006600"> "ace/Synch.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/SOCK_Acceptor.h"</FONT> -<BR><FONT COLOR="#000099">#include </FONT><FONT COLOR="#006600">"ace/Thread.h"</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">NETWORK_SPEED -3</FONT> -<BR>class MyServiceHandler;<FONT COLOR="#FF0000"> //forward declaration</FONT> -<BR>typedef ACE_Singleton<ACE_Reactor,ACE_Null_Mutex> Reactor; -<BR>typedef ACE_Acceptor<MyServiceHandler,ACE_SOCK_ACCEPTOR> Acceptor; - -<P>class MyServiceHandler: -<BR>public ACE_Svc_Handler<ACE_SOCK_STREAM,ACE_MT_SYNCH>{ -<BR><FONT COLOR="#FF0000">// The message sender and creator threads are -handled here.</FONT> -<BR>ACE_thread_t thread_names[2]; - -<P>public: -<BR>int open(void*){ -<BR> ACE_DEBUG((LM_DEBUG, "Acceptor: received new connection \n")); - -<P><FONT COLOR="#FF0000"> //Register with the reactor to remember -this handler..</FONT> -<BR> Reactor::instance() ->register_handler(this,ACE_Event_Handler::READ_MASK); -<BR> ACE_DEBUG((LM_DEBUG,"Acceptor: ThreadID:(%t) open\n")); - -<P><FONT COLOR="#CC0000"> //Create two new threads to create and send -messages to the</FONT> -<BR><FONT COLOR="#CC0000"> //remote machine.</FONT> -<BR> activate(THR_NEW_LWP, -<BR> 2, <FONT COLOR="#FF0000">//2 new threads</FONT> -<BR> 0, -<BR> ACE_DEFAULT_THREAD_PRIORITY, -<BR> -1, -<BR> this, -<BR> 0, -<BR> 0, -<BR> 0, -<BR> thread_names); <FONT COLOR="#FF0000">// identifiers in -thread_handles</FONT> -<BR> -<BR> <FONT COLOR="#FF0000">//keep the service handler registered with -the acceptor.</FONT> -<BR> return 0; -<BR> } - -<P>void send_message(void){ -<BR><FONT COLOR="#FF0000"> //Dequeue the message and send it off</FONT> -<BR> ACE_DEBUG((LM_DEBUG,"(%t)Sending message >>")); - -<P><FONT COLOR="#FF0000"> //dequeue the message from the message queue</FONT> -<BR> ACE_Message_Block *mb; -<BR> ACE_ASSERT(this->getq(mb)!=-1); -<BR> int length=mb->length(); -<BR> char *data =mb->rd_ptr(); - -<P> -<BR><FONT COLOR="#FF0000"> //Send the data to the remote peer</FONT> -<BR> ACE_DEBUG((LM_DEBUG,"%s \n",data,length)); -<BR> peer().send_n(data,length); - -<P> <FONT COLOR="#FF0000">//Simulate very SLOW network.</FONT> -<BR> ACE_OS::sleep(NETWORK_SPEED); - -<P><FONT COLOR="#FF0000"> //release the message block</FONT> -<BR> mb->release(); -<BR> } <FONT COLOR="#FF0000">//end send_message</FONT> - -<P>int construct_message(void){ -<BR><FONT COLOR="#FF0000"> // A very fast message creation algorithm</FONT> -<BR><FONT COLOR="#FF0000"> // would lead to the need for queuing messages..</FONT> -<BR><FONT COLOR="#FF0000"> // here. These messages are created and -then sent</FONT> -<BR><FONT COLOR="#FF0000"> // using the SLOW send_message() routine -which is</FONT> -<BR><FONT COLOR="#FF0000"> // running in a different thread so that -the message</FONT> -<BR><FONT COLOR="#FF0000"> //construction thread isn?t blocked.</FONT> -<BR> ACE_DEBUG((LM_DEBUG,"(%t)Constructing message >> ")); - -<P> <FONT COLOR="#FF0000">// Create a new message to send</FONT> -<BR> ACE_Message_Block *mb; -<BR> char *data="Hello Connector"; -<BR> ACE_NEW_RETURN (mb,ACE_Message_Block (16,<FONT COLOR="#FF0000">//Message -16 bytes long</FONT> -<BR> ACE_Message_Block::MB_DATA,<FONT COLOR="#FF0000">//Set -header to data</FONT> -<BR> 0,<FONT COLOR="#FF0000">//No continuations</FONT>. -<BR> data<FONT COLOR="#FF0000">//The data we want to send</FONT> -<BR> ), 0); -<BR> mb->wr_ptr(16); <FONT COLOR="#FF0000">//Set the write pointer.</FONT> -<BR> -<BR> <FONT COLOR="#FF0000">// Enqueue the message into the message -queue</FONT> -<BR><FONT COLOR="#FF0000"> // we COULD have done a timed wait for -enqueuing in case</FONT> -<BR><FONT COLOR="#FF0000"> // someone else holds the lock to the queue -so it doesn?t block</FONT> -<BR><FONT COLOR="#FF0000"> //forever..</FONT> -<BR> ACE_ASSERT(this->putq(mb)!=-1); -<BR> ACE_DEBUG((LM_DEBUG,"Enqueued msg successfully\n")); -<BR>} -<BR> -<BR>int svc(void){ -<BR> ACE_DEBUG( (LM_DEBUG,?(%t) Svc thread \n?)); -<BR> -<BR><FONT COLOR="#FF0000"> //call the message creator thread</FONT> -<BR> if(ACE_Thread::self()== thread_names[0]) -<BR> while(1) construct_message(); <FONT COLOR="#FF0000">//create -messages forever</FONT> -<BR> else -<BR> while(1) send_message(); <FONT COLOR="#FF0000">//send messages -forever</FONT> -<BR> return 0; <FONT COLOR="#FF0000">// keep the compiler happy.</FONT> -<BR>} -<BR> -<BR>int handle_input(ACE_HANDLE){ -<BR> ACE_DEBUG((LM_DEBUG,"(%t) handle_input ")); -<BR> char* data= new char[13]; -<BR> -<BR> <FONT COLOR="#FF0000">//Check if peer aborted the connection</FONT> -<BR> if(peer().recv_n(data,12)==0){ -<BR> ACE_OS::printf("Peer probably aborted connection"); -<BR> return -1; <FONT COLOR="#FF0000">//de-register from the Reactor.</FONT> -<BR> } -<BR> -<BR><FONT COLOR="#FF0000"> //Show what you got..</FONT> -<BR> ACE_OS::printf("<< %s\n",data); -<BR> -<BR><FONT COLOR="#FF0000"> //keep yourself registered</FONT> -<BR> return 0; -<BR> -<BR> } -<BR>}; - -<P>int main(int argc, char* argv[]){ -<BR> ACE_INET_Addr addr(10101); -<BR> ACE_DEBUG((LM_DEBUG,"Thread: (%t) main\n")); - -<P> <FONT COLOR="#FF0000">//Prepare to accept connections</FONT> -<BR> Acceptor myacceptor(addr,Reactor::instance()); - -<P><FONT COLOR="#FF0000"> // wait for something to happen.</FONT> -<BR> while(1) -<BR> Reactor::instance()->handle_events(); -<BR> -<BR> return 0; -<BR>} - -<P> <A HREF="ex08.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_6/ex08.html b/docs/tutorials/Chap_6/ex08.html deleted file mode 100644 index 5e044e9e0a4..00000000000 --- a/docs/tutorials/Chap_6/ex08.html +++ /dev/null @@ -1,97 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 8</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "The Acceptor/Connector" -(Connection Initialization)</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 8</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Reactor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Svc_Handler.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Acceptor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Synch.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/SOCK_Acceptor.h"</FONT> -<BR><FONT COLOR="#000099">#define</FONT><FONT COLOR="#663366"> PORT_NUM -10101</FONT> -<BR><FONT COLOR="#000099">#define</FONT><FONT COLOR="#663366"> DATA_SIZE -12</FONT><FONT COLOR="#FF0000"></FONT> - -<P><FONT COLOR="#FF0000">//forward declaration</FONT> -<BR>class My_Svc_Handler;<FONT COLOR="#FF0000"></FONT> - -<P><FONT COLOR="#FF0000">//instantiate a strategy acceptor</FONT> -<BR>typedef ACE_Strategy_Acceptor<My_Svc_Handler,ACE_SOCK_ACCEPTOR> -MyAcceptor;<FONT COLOR="#FF0000"></FONT> - -<P><FONT COLOR="#FF0000">//instantiate a concurrency strategy</FONT> -<BR>typedef ACE_Process_Strategy<My_Svc_Handler> Concurrency_Strategy; - -<P><FONT COLOR="#FF0000">// Define the Service Handler</FONT> -<BR>class My_Svc_Handler: -<BR> public ACE_Svc_Handler <ACE_SOCK_STREAM,ACE_NULL_SYNCH>{ -<BR>private: -<BR> char* data; -<BR>public: -<BR> My_Svc_Handler(){ -<BR> data= new char[DATA_SIZE]; -<BR> } -<BR> My_Svc_Handler(ACE_Thread_Manager* tm){ -<BR> data= new char[DATA_SIZE]; -<BR> } -<BR> int open(void*){ -<BR> ACE_DEBUG((LM_DEBUG,"Connection -established\n")); -<BR><FONT COLOR="#FF0000"> -//Register with the reactor</FONT> -<BR> ACE_Reactor::instance()->register_handler(this, -<BR> ACE_Event_Handler::READ_MASK); -<BR> return 0; -<BR> } - -<P> int handle_input(ACE_HANDLE){ -<BR> peer().recv_n(data,DATA_SIZE); -<BR> ACE_OS::printf(?<< %s\n?,data); -<BR> -<BR><FONT COLOR="#FF0000"> // keep yourself registered -with the reactor</FONT> -<BR> return 0; -<BR> } -<BR>}; - -<P>int main(int argc, char* argv[]){ -<BR> ACE_INET_Addr addr(PORT_NUM); - -<P> <FONT COLOR="#FF0000">//Concurrency Strategy</FONT> -<BR> Concurrency_Strategy my_con_strat; - -<P><FONT COLOR="#FF0000">//Instantiate the acceptor</FONT> -<BR> MyAcceptor acceptor(addr, <FONT COLOR="#FF0000">//address to -accept on</FONT> -<BR> ACE_Reactor::instance(), <FONT COLOR="#FF0000">//the reactor -to use</FONT> -<BR> 0, <FONT COLOR="#FF0000">// dont care about creation strategy</FONT> -<BR> 0, <FONT COLOR="#FF0000">// dont care about connection estb. -strategy</FONT> -<BR> &my_con_strat);<FONT COLOR="#FF0000"> // use our new process -concurrency strategy</FONT> - -<P>while(1)<FONT COLOR="#FF0000"> // Start the reactors event loop</FONT> -<BR> ACE_Reactor::instance()->handle_events(); -<BR>} - -<P> <A HREF="ex09.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_6/ex09.html b/docs/tutorials/Chap_6/ex09.html deleted file mode 100644 index e280f2371c0..00000000000 --- a/docs/tutorials/Chap_6/ex09.html +++ /dev/null @@ -1,212 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 9</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "The Acceptor/Connector" -(Connection Initialization)</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 9</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Reactor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT><FONT COLOR="#663366"> </FONT><FONT COLOR="#006600">"ace/Svc_Handler.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT><FONT COLOR="#006600"> "ace/Connector.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT><FONT COLOR="#006600"> "ace/Synch.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/SOCK_Connector.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/INET_Addr.h"</FONT> - -<P><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">PORT_NUM -10101</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">DATA_SIZE -16</FONT> - -<P><FONT COLOR="#FF0000">//forward declaration</FONT> -<BR>class My_Svc_Handler; -<BR><FONT COLOR="#FF0000">//Function prototype</FONT> -<BR>static void make_connections(void *arg); - -<P><FONT COLOR="#FF0000">// Template specializations for the hashing function -for the</FONT> -<BR><FONT COLOR="#FF0000">// hash_map which is used by the cache. The cache -is used internally by the</FONT> -<BR><FONT COLOR="#FF0000">// Cached Connection Strategy . Here we use ACE_Hash_Addr</FONT> -<BR><FONT COLOR="#FF0000">// as our external identifier. This utility class -has already</FONT> -<BR><FONT COLOR="#FF0000">// overloaded the == operator and the hash() -method. (The</FONT> -<BR><FONT COLOR="#FF0000">// hashing function). The hash() method delgates -the work to</FONT> -<BR><FONT COLOR="#FF0000">// hash_i() and we use the IP address and port -to get a</FONT> -<BR><FONT COLOR="#FF0000">// a unique integer hash value.</FONT> -<BR>size_t -<BR>ACE_Hash_Addr<ACE_INET_Addr>::hash_i (const ACE_INET_Addr &addr) -const -<BR>{ -<BR> return addr.get_ip_address () + addr.get_port_number (); -<BR>} - -<P><FONT COLOR="#FF0000">//instantiate a strategy acceptor</FONT> -<BR>typedef ACE_Strategy_Connector<My_Svc_Handler,ACE_SOCK_CONNECTOR> -<BR>STRATEGY_CONNECTOR; - -<P><FONT COLOR="#FF0000">//Instantiate the Creation Strategy</FONT> -<BR>typedef ACE_NOOP_Creation_Strategy<My_Svc_Handler> -<BR> NULL_CREATION_STRATEGY; -<BR><FONT COLOR="#FF0000">//Instantiate the Concurrency Strategy</FONT> -<BR>typedef ACE_NOOP_Concurrency_Strategy<My_Svc_Handler> -<BR> NULL_CONCURRENCY_STRATEGY; -<BR><FONT COLOR="#FF0000">//Instantiate the Connection Strategy</FONT> -<BR>typedef ACE_Cached_Connect_Strategy<My_Svc_Handler, -<BR> -ACE_SOCK_CONNECTOR, -<BR> -ACE_SYNCH_RW_MUTEX> -<BR> CACHED_CONNECT_STRATEGY; -<BR> -<BR>class My_Svc_Handler: -<BR>public ACE_Svc_Handler <ACE_SOCK_STREAM,ACE_MT_SYNCH>{ -<BR>private: -<BR>char* data; - -<P>public: -<BR>My_Svc_Handler(){ -<BR>data= new char[DATA_SIZE]; -<BR> } -<BR>My_Svc_Handler(ACE_Thread_Manager* tm){ -<BR>data= new char[DATA_SIZE]; -<BR> } -<BR><FONT COLOR="#FF0000">//Called before the service handler is recycled..</FONT> -<BR>int -<BR>recycle (void *a=0){ -<BR> ACE_DEBUG ((LM_DEBUG, -<BR> "(%P|%t) recycling Svc_Handler %d with handle %d\n", -<BR> -this, this->peer ().get_handle ())); -<BR> return 0; -<BR> } - -<P>int open(void*){ -<BR> ACE_DEBUG((LM_DEBUG,"(%t)Connection established \n")); -<BR> -<BR> -<BR> - -<P><FONT COLOR="#FF0000"> //Register the service handler with the -reactor</FONT> -<BR> ACE_Reactor::instance() ->register_handler(this,ACE_Event_Handler::READ_MASK); -<BR> activate(THR_NEW_LWP|THR_DETACHED); -<BR> return 0; -<BR> } - -<P>int handle_input(ACE_HANDLE){ -<BR> ACE_DEBUG((LM_DEBUG,"Got input in thread: (%t) \n")); -<BR> peer().recv_n(data,DATA_SIZE); -<BR> ACE_DEBUG((LM_DEBUG,"<< %s\n",data)); - -<P> <FONT COLOR="#FF0000">//keep yourself registered with the reactor</FONT> -<BR> return 0; -<BR>} - -<P>int svc(void){ -<BR><FONT COLOR="#FF0000"> //send a few messages and then mark connection -as idle so that it can be recycled later.</FONT> -<BR> ACE_DEBUG((LM_DEBUG,"Started the service routine \n")); - -<P> for(int i=0;i<3;i++){ -<BR> ACE_DEBUG((LM_DEBUG,"(%t)>>Hello World\n")); -<BR> ACE_OS::fflush(stdout); -<BR> peer().send_n("Hello World",sizeof("Hello World")); -<BR> } - -<P> <FONT COLOR="#FF0000">//Mark the service handler as being idle -now and let the other threads reuse this connection</FONT> -<BR> this->idle(1); - -<P> <FONT COLOR="#FF0000">//Wait for the thread to die</FONT> -<BR> this->thr_mgr()->wait(); -<BR> return 0; -<BR> } -<BR>}; -<BR>ACE_INET_Addr *addr; - -<P>int main(int argc, char* argv[]){ -<BR> addr= new ACE_INET_Addr(PORT_NUM,argv[1]); -<BR><FONT COLOR="#FF0000"> //Creation Strategy</FONT> -<BR> NULL_CREATION_STRATEGY creation_strategy; - -<P><FONT COLOR="#FF0000"> //Concurrency Strategy</FONT> -<BR> NULL_CONCURRENCY_STRATEGY concurrency_strategy; - -<P><FONT COLOR="#FF0000"> //Connection Strategy</FONT> -<BR> CACHED_CONNECT_STRATEGY caching_connect_strategy; -<BR> - -<P><FONT COLOR="#FF0000"> //instantiate the connector</FONT> -<BR> STRATEGY_CONNECTOR connector( -<BR> ACE_Reactor::instance(),<FONT COLOR="#FF0000"> //the reactor -to use</FONT> -<BR> &creation_strategy, -<BR> &caching_connect_strategy, -<BR> &concurrency_strategy); -<BR><FONT COLOR="#FF0000"> //Use the thread manager to spawn -a single thread to</FONT> -<BR><FONT COLOR="#FF0000"> //connect multiple times passing it the -address</FONT> -<BR><FONT COLOR="#FF0000"> //of the strategy connector</FONT> -<BR> if(ACE_Thread_Manager::instance()->spawn( -<BR> (ACE_THR_FUNC) make_connections, -<BR> (void *) &connector, -<BR> THR_NEW_LWP) == -1) -<BR> ACE_ERROR ((LM_ERROR, "(%P|%t) %p\n%a", "client thread spawn -failed")); - -<P>while(1) /* Start the reactor?s event loop */ -<BR> ACE_Reactor::instance()->handle_events(); -<BR>} - -<P><FONT COLOR="#FF0000">//Connection establishment function, tries to -establish connections</FONT> -<BR><FONT COLOR="#FF0000">//to the same server again and re-uses the connections -from the</FONT> -<BR><FONT COLOR="#FF0000">//cache</FONT> -<BR>void make_connections(void *arg){ -<BR> ACE_DEBUG((LM_DEBUG,"(%t)Prepared to connect \n")); -<BR> STRATEGY_CONNECTOR *connector= (STRATEGY_CONNECTOR*) arg; -<BR> for (int i = 0; i < 10; i++){ -<BR> My_Svc_Handler *svc_handler = 0; -<BR> - -<P> <FONT COLOR="#FF0000">// Perform a blocking connect to the server -using the Strategy</FONT> -<BR><FONT COLOR="#FF0000"> // Connector with a connection caching -strategy. Since we are</FONT> -<BR><FONT COLOR="#FF0000"> // connecting to the same <server_addr> -these calls will return the</FONT> -<BR><FONT COLOR="#FF0000"> // same dynamically allocated <Svc_Handler> -for each <connect> call.</FONT> -<BR> if (connector->connect (svc_handler, *addr) == -1){ -<BR> ACE_ERROR ((LM_ERROR, "(%P|%t) %p\n", "connection failed\n")); -<BR> return; -<BR> } - -<P><FONT COLOR="#FF0000"> // Rest for a few seconds so that the connection -has been freed up</FONT> -<BR> ACE_OS::sleep (5); -<BR> } -<BR>} -<BR> -<BR> <A HREF="ex10.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_6/ex10.html b/docs/tutorials/Chap_6/ex10.html deleted file mode 100644 index 5d57ca7d99e..00000000000 --- a/docs/tutorials/Chap_6/ex10.html +++ /dev/null @@ -1,111 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 10</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "The Acceptor/Connector" -(Connection Initialization)</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 10</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Reactor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Svc_Handler.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Acceptor.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Synch.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/SOCK_Acceptor.h"</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">PORT_NUM -10101</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">DATA_SIZE -12</FONT> - -<P><FONT COLOR="#FF0000">//forward declaration</FONT> -<BR>class My_Svc_Handler; - -<P><FONT COLOR="#FF0000">//Create the Acceptor class</FONT> -<BR>typedef ACE_Acceptor<My_Event_Handler,ACE_SOCK_ACCEPTOR> -<BR>MyAcceptor; - -<P><FONT COLOR="#FF0000">//Create an event handler similar to as seen in -example 2.</FONT> -<BR><FONT COLOR="#FF0000">//We have to overload the get_handle() method -and write the peer()</FONT> -<BR><FONT COLOR="#FF0000">//method. We also provide the data member peer_ -as the underlying</FONT> -<BR><FONT COLOR="#FF0000">//stream which is used.</FONT> -<BR>class My_Event_Handler: -<BR> public ACE_Event_Handler{ -<BR>private: -<BR>char* data; -<BR><FONT COLOR="#FF0000">//Add a new attribute for the underlying stream -which will be used by the Event Handler</FONT> -<BR>ACE_SOCK_Stream peer_; -<BR>public: -<BR>My_Event_Handler(){ -<BR> data= new char[DATA_SIZE]; -<BR> } - -<P>int -<BR>open(void*){ -<BR> ACE_DEBUG((LM_DEBUG,"Connection established\n")); -<BR><FONT COLOR="#FF0000"> //Register the event handler with the reactor</FONT> -<BR> ACE_Reactor::instance()->register_handler(this, ACE_Event_Handler::READ_MASK); -<BR> return 0; -<BR> } - -<P>int -<BR>handle_input(ACE_HANDLE){ -<BR> <FONT COLOR="#FF0000">// After using the peer() method of our -ACE_Event_Handler to obtain a</FONT> -<BR><FONT COLOR="#FF0000"> //reference to the underlying stream of -the service handler class we</FONT> -<BR><FONT COLOR="#FF0000"> //call recv_n() on it to read the data -which has been received. This</FONT> -<BR><FONT COLOR="#FF0000"> //data is stored in the data array and -then printed out</FONT> -<BR> peer().recv_n(data,DATA_SIZE); -<BR> ACE_OS::printf("<< %s\n",data); - -<P> <FONT COLOR="#FF0000">// keep yourself registered with the reactor</FONT> -<BR> return 0; -<BR> } - -<P><FONT COLOR="#FF0000">// new method which returns the handle to the -reactor when it asks for it.</FONT> -<BR>ACE_HANDLE -<BR>get_handle(void) const{ -<BR> return this->peer_.get_handle(); -<BR> } - -<P><FONT COLOR="#FF0000">//new method which returns a reference to the -peer stream</FONT> -<BR>ACE_SOCK_Stream & -<BR>peer(void) const{ -<BR> return (ACE_SOCK_Stream &) this->peer_; -<BR> } -<BR>}; - -<P>int main(int argc, char* argv[]){ -<BR> ACE_INET_Addr addr(PORT_NUM); -<BR> <FONT COLOR="#FF0000">//create the acceptor</FONT> -<BR> MyAcceptor acceptor(addr,<FONT COLOR="#FF0000"> //address to -accept on</FONT> -<BR> ACE_Reactor::instance()); <FONT COLOR="#FF0000">//the reactor -to use</FONT> -<BR>while(1)<FONT COLOR="#FF0000"> // Start the reactors event loop</FONT> -<BR> ACE_Reactor::instance()->handle_events(); -<BR>} -<BR> -<BR> <A HREF="../Chap_7/ex01.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_7/Chap_7.zip b/docs/tutorials/Chap_7/Chap_7.zip Binary files differdeleted file mode 100644 index 0073e63d504..00000000000 --- a/docs/tutorials/Chap_7/Chap_7.zip +++ /dev/null diff --git a/docs/tutorials/Chap_7/ex01.html b/docs/tutorials/Chap_7/ex01.html deleted file mode 100644 index 988c876bf39..00000000000 --- a/docs/tutorials/Chap_7/ex01.html +++ /dev/null @@ -1,91 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 1</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "The Message Queue"</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 1</FONT> -<BR><FONT COLOR="#000099">#include</FONT> "<FONT COLOR="#006600">ace/Message_Queue.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> <FONT COLOR="#006600">"ace/Get_Opt.h"</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">SIZE_BLOCK -1</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">NO_MSGS -10</FONT> - -<P>class QTest{ -<BR>public: -<BR>QTest():no_msgs_(NO_MSGS){ -<BR> <FONT COLOR="#FF0000">//First create a message queue of default -size.</FONT> -<BR> if(!(this->mq_=new ACE_Message_Queue<ACE_NULL_SYNCH> ())) -<BR> ACE_DEBUG((LM_ERROR,"Error in message queue initialization \n")); -<BR> } -<BR> -<BR>int start_test(){ -<BR> for(int i=0; i<no_msgs_;i++){ -<BR> <FONT COLOR="#FF0000">//create a new message block of size 1</FONT> -<BR> ACE_Message_Block *mb= new ACE_Message_Block(SIZE_BLOCK);<FONT COLOR="#FF0000"></FONT> - -<P><FONT COLOR="#FF0000"> //Insert data into the message block using -the rd_ptr</FONT> -<BR> *mb->wr_ptr()=i; - -<P><FONT COLOR="#FF0000"> //Be careful to advance the wr_ptr</FONT> -<BR> mb->wr_ptr(1); - -<P> <FONT COLOR="#FF0000">//Enqueue the message block onto the message -queue</FONT> -<BR> if(this->mq_->enqueue_prio(mb)==-1){ -<BR> ACE_DEBUG((LM_ERROR,"\nCould not enqueue on to mq!!\n")); -<BR> return -1; -<BR> } -<BR> -<BR> ACE_DEBUG((LM_INFO,"EQd data: %d\n",*mb->rd_ptr())); -<BR> } <FONT COLOR="#FF0000">//end for</FONT> - -<P><FONT COLOR="#FF0000">//Now dequeue all the messages</FONT> -<BR>this->dequeue_all(); -<BR>return 0; -<BR> } - -<P>void dequeue_all(){ -<BR> ACE_DEBUG((LM_INFO,"\n\nBeginning DQ \n")); -<BR> ACE_DEBUG((LM_INFO,"No. of Messages on Q:%d Bytes on Q:%d \n",mq_->message_count(), -mq_->message_bytes())); -<BR> ACE_Message_Block *mb; - -<P> <FONT COLOR="#FF0000">//dequeue the head of the message queue -until no more messages are left</FONT> -<BR> for(int i=0;i<no_msgs_;i++){ -<BR> mq_->dequeue_head(mb); -<BR> ACE_DEBUG((LM_INFO,"DQd data %d\n",*mb->rd_ptr())); -<BR> } -<BR> } -<BR>private: -<BR> ACE_Message_Queue<ACE_NULL_SYNCH> *mq_; -<BR> int no_msgs_; -<BR>}; -<BR> - -<P>int main(int argc, char* argv[]){ -<BR> QTest test; -<BR> if(test.start_test()<0) -<BR> ACE_DEBUG((LM_ERROR,"Program failure \n")); -<BR>} - -<P> <A HREF="ex02.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_7/ex02.html b/docs/tutorials/Chap_7/ex02.html deleted file mode 100644 index 65b148fde6e..00000000000 --- a/docs/tutorials/Chap_7/ex02.html +++ /dev/null @@ -1,166 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 2</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "The Message Queue"</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 2</FONT><FONT COLOR="#000099"></FONT> - -<P><FONT COLOR="#000099">#include</FONT><FONT COLOR="#006600"> "ace/Message_Queue.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT><FONT COLOR="#006600"> "ace/Get_Opt.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> "<FONT COLOR="#006600">ace/Malloc_T.h"</FONT> -<BR><FONT COLOR="#000099">#define</FONT> <FONT COLOR="#663366">SIZE_BLOCK -1</FONT> - -<P>class Args{ -<BR>public: -<BR>Args(int argc, char*argv[],int& no_msgs, ACE_Message_Queue<ACE_NULL_SYNCH>* -&mq){ -<BR> ACE_Get_Opt get_opts(argc,argv,"h:l:t:n:xsd"); -<BR> while((opt=get_opts())!=-1) -<BR> switch(opt){ -<BR> case 'n': -<BR> <FONT COLOR="#FF0000"> //set the number of messages we -wish to enqueue and dequeue</FONT> -<BR> no_msgs=ACE_OS::atoi(get_opts.optarg); -<BR> ACE_DEBUG((LM_INFO,"Number of Messages %d \n",no_msgs)); -<BR> break; - -<P> case 'h': -<BR> <FONT COLOR="#FF0000">//set the high water mark</FONT> -<BR> hwm=ACE_OS::atoi(get_opts.optarg); -<BR> mq->high_water_mark(hwm); -<BR> ACE_DEBUG((LM_INFO,"High Water Mark %d msgs \n",hwm)); -<BR> break; -<BR> case 'l': -<BR> <FONT COLOR="#FF0000"> //set the low water mark</FONT> -<BR> lwm=ACE_OS::atoi(get_opts.optarg); -<BR> mq->low_water_mark(lwm); -<BR> ACE_DEBUG((LM_INFO,"Low Water Mark %d msgs \n",lwm)); -<BR> break; -<BR> default: -<BR> ACE_DEBUG((LM_ERROR, "Usage -n<no. messages> -h<hwm> --l<lwm>\n")); -<BR> break; -<BR> } -<BR> } - -<P>private: -<BR> int opt; -<BR> int hwm; -<BR> int lwm; -<BR>}; -<BR> -<BR> - -<P>class QTest{ -<BR>public: -<BR>QTest(int argc, char*argv[]){ -<BR><FONT COLOR="#FF0000"> //First create a message queue of default -size.</FONT> -<BR> if(!(this->mq_=new ACE_Message_Queue<ACE_NULL_SYNCH> ())) -<BR> ACE_DEBUG((LM_ERROR,"Error in message queue initialization \n")); -<BR> -<BR> <FONT COLOR="#FF0000">//Use the arguments to set the water marks -and the no of messages</FONT> -<BR> args_ = new Args(argc,argv,no_msgs_,mq_); -<BR> } -<BR>int start_test(){ -<BR> for(int i=0; i<no_msgs_;i++){ -<BR> <FONT COLOR="#FF0000">//Create a new message block of data buffer -size 1</FONT> -<BR> ACE_Message_Block * mb= new ACE_Message_Block(SIZE_BLOCK); -<BR> -<BR><FONT COLOR="#FF0000"> //Insert data into the message block using -the rd_ptr</FONT> -<BR> *mb->wr_ptr()=i; -<BR> -<BR> <FONT COLOR="#FF0000">//Be careful to advance the wr_ptr</FONT> -<BR> mb->wr_ptr(1); - -<P><FONT COLOR="#FF0000"> //Enqueue the message block onto the message -queue</FONT> -<BR> if(this->mq_->enqueue_prio(mb)==-1){ -<BR> ACE_DEBUG((LM_ERROR,"\nCould not enqueue on to mq!!\n")); -<BR> return -1; -<BR> } -<BR> -<BR> ACE_DEBUG((LM_INFO,"EQd data: %d\n",*mb->rd_ptr())); -<BR> } -<BR> <FONT COLOR="#FF0000">//Use the iterators to read</FONT> -<BR> this->read_all(); - -<P> <FONT COLOR="#FF0000">//Dequeue all the messages</FONT> -<BR> this->dequeue_all(); -<BR> return 0; -<BR> } - -<P>void read_all(){ -<BR> ACE_DEBUG((LM_INFO,"No. of Messages on Q:%d Bytes on Q:%d \n", -mq_->message_count(),mq_->message_bytes())); -<BR> ACE_Message_Block *mb; - -<P> <FONT COLOR="#FF0000">//Use the forward iterator</FONT> -<BR> ACE_DEBUG((LM_INFO,"\n\nBeginning Forward Read \n")); -<BR> ACE_Message_Queue_Iterator<ACE_NULL_SYNCH> mq_iter_(*mq_); -<BR> while(mq_iter_.next(mb)){ -<BR> mq_iter_.advance(); -<BR> ACE_DEBUG((LM_INFO,"Read data %d\n",*mb->rd_ptr())); -<BR> } -<BR> -<BR> <FONT COLOR="#FF0000">//Use the reverse iterator</FONT> -<BR> ACE_DEBUG((LM_INFO,"\n\nBeginning Reverse Read \n")); -<BR> ACE_Message_Queue_Reverse_Iterator<ACE_NULL_SYNCH> -<BR> mq_rev_iter_(*mq_); -<BR> while(mq_rev_iter_.next(mb)){ -<BR> mq_rev_iter_.advance(); -<BR> ACE_DEBUG((LM_INFO,"Read data %d\n",*mb->rd_ptr())); -<BR> } -<BR> -<BR> } - -<P>void dequeue_all(){ -<BR> ACE_DEBUG((LM_INFO,"\n\nBeginning DQ \n")); -<BR> ACE_DEBUG((LM_INFO,"No. of Messages on Q:%d Bytes on Q:%d \n", -mq_->message_count(),mq_->message_bytes())); -<BR> ACE_Message_Block *mb; - -<P><FONT COLOR="#FF0000"> //dequeue the head of the message queue -until no more messages are left</FONT> -<BR> for(int i=0;i<no_msgs_;i++){ -<BR> mq_->dequeue_head(mb); -<BR> ACE_DEBUG((LM_INFO,"DQd data %d\n",*mb->rd_ptr())); -<BR> } -<BR> } - -<P>private: -<BR> Args *args_; -<BR> ACE_Message_Queue<ACE_NULL_SYNCH> *mq_; -<BR> int no_msgs_; -<BR>}; -<BR> -<BR> - -<P>int main(int argc, char* argv[]){ -<BR> QTest test(argc,argv); -<BR> if(test.start_test()<0) -<BR> ACE_DEBUG((LM_ERROR,"Program failure \n")); -<BR> -<BR>} - -<P> <A HREF="ex03.html">Next Example</A> -</BODY> -</HTML> diff --git a/docs/tutorials/Chap_7/ex03.html b/docs/tutorials/Chap_7/ex03.html deleted file mode 100644 index 71ae5e8a7a8..00000000000 --- a/docs/tutorials/Chap_7/ex03.html +++ /dev/null @@ -1,159 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="Author" CONTENT="Ambreen Ilyas"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> - <TITLE>Example 3</TITLE> -</HEAD> -<BODY> -<FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> -<BR><FONT COLOR="#CC0000">//// This example is from the ACE Programmers -Guide.</FONT> -<BR><FONT COLOR="#CC0000">//// Chapter: "The Message Queue"</FONT> -<BR><FONT COLOR="#CC0000">//// For details please see the guide at</FONT> -<BR><FONT COLOR="#CC0000">//// http://www.cs.wustl.edu/~schmidt/ACE.html</FONT> -<BR><FONT COLOR="#CC0000">//// AUTHOR: Umar Syyid (usyyid@hns.com)</FONT> -<BR><FONT COLOR="#CC0000">//// and Ambreen Ilyas (ambreen@bitsmart.com)</FONT> -<BR><FONT COLOR="#CC0000">/////////////////////////////////////////////////////////////////////////////////////////////////////////////</FONT> - -<P><FONT COLOR="#CC0000">//Example 3</FONT> -<BR><FONT COLOR="#000099">#include</FONT> "<FONT COLOR="#006600">ace/Message_Queue.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> "<FONT COLOR="#006600">ace/Get_Opt.h"</FONT> -<BR><FONT COLOR="#000099">#include</FONT> "<FONT COLOR="#006600">ace/OS.h"</FONT> - -<P>class Args{ -<BR>public: -<BR>Args(int argc, char*argv[],int& no_msgs, int& time,ACE_Message_Queue<ACE_NULL_SYNCH>* -&mq){ -<BR> ACE_Get_Opt get_opts(argc,argv,"h:l:t:n:xsd"); -<BR> while((opt=get_opts())!=-1) -<BR> switch(opt){ -<BR> case 't': -<BR> time=ACE_OS::atoi(get_opts.optarg); -<BR> ACE_DEBUG((LM_INFO,"Time: %d \n",time)); -<BR> break; -<BR> case 'n': -<BR> no_msgs=ACE_OS::atoi(get_opts.optarg); -<BR> ACE_DEBUG((LM_INFO,"Number of Messages %d \n",no_msgs)); -<BR> break; -<BR> case 'x': -<BR> mq=ACE_Message_Queue_Factory<ACE_NULL_SYNCH>:: create_laxity_message_queue(); -<BR> ACE_DEBUG((LM_DEBUG,"Creating laxity q\n")); -<BR> break; -<BR> case 'd': -<BR> mq=ACE_Message_Queue_Factory<ACE_NULL_SYNCH>:: create_deadline_message_queue(); -<BR> ACE_DEBUG((LM_DEBUG,"Creating deadline q\n")); -<BR> break; -<BR> case 's': -<BR> mq=ACE_Message_Queue_Factory<ACE_NULL_SYNCH>:: create_static_message_queue(); -<BR> ACE_DEBUG((LM_DEBUG,"Creating static q\n")); -<BR> break; -<BR> case 'h': -<BR> hwm=ACE_OS::atoi(get_opts.optarg); -<BR> mq->high_water_mark(hwm); -<BR> ACE_DEBUG((LM_INFO,"High Water Mark %d msgs \n",hwm)); -<BR> break; -<BR> case 'l': -<BR> lwm=ACE_OS::atoi(get_opts.optarg); -<BR> mq->low_water_mark(lwm); -<BR> ACE_DEBUG((LM_INFO,"Low Water Mark %d msgs \n",lwm)); -<BR> break; -<BR> default: -<BR> ACE_DEBUG((LM_ERROR,"Usage specify queue type\n")); -<BR> break; -<BR> } -<BR> } - -<P>private: -<BR> int opt; -<BR> int hwm; -<BR> int lwm; -<BR>}; -<BR> -<BR> - -<P>class QTest{ -<BR>public: -<BR>QTest(int argc, char*argv[]){ -<BR> args_ = new Args(argc,argv,no_msgs_,time_,mq_); -<BR> array_ =new ACE_Message_Block*[no_msgs_]; -<BR> } - -<P>int start_test(){ -<BR> for(int i=0; i<no_msgs_;i++){ -<BR> ACE_NEW_RETURN (array_[i], ACE_Message_Block (1), -1); -<BR> set_deadline(i); -<BR> set_execution_time(i); -<BR> enqueue(i); -<BR> } - -<P> this->dequeue_all(); -<BR> return 0; -<BR> } - -<P><FONT COLOR="#FF0000">//Call the underlying ACE_Message_Block method -msg_deadline_time() to set the deadline of the message.</FONT> -<BR>void set_deadline(int msg_no){ -<BR> float temp=(float) time_/(msg_no+1); -<BR> ACE_Time_Value tv; -<BR> tv.set(temp); -<BR> ACE_Time_Value deadline(ACE_OS::gettimeofday()+tv); -<BR> array_[msg_no]->msg_deadline_time(deadline); -<BR> ACE_DEBUG((LM_INFO,"EQd with DLine %d:%d\n", deadline.sec(),deadline.usec())); -<BR> } - -<P><FONT COLOR="#FF0000">//Call the underlying ACE_Message_Block method -to set the execution time</FONT> -<BR>void set_execution_time(int msg_no){ -<BR> float temp=(float) time_/10*msg_no; -<BR> ACE_Time_Value tv; -<BR> tv.set(temp); -<BR> ACE_Time_Value xtime(ACE_OS::gettimeofday()+tv); -<BR> array_[msg_no]->msg_execution_time (xtime); -<BR> ACE_DEBUG((LM_INFO,"Xtime %d:%d\n",xtime.sec(),xtime.usec())); -<BR> } - -<P>void enqueue(int msg_no){ -<BR><FONT COLOR="#FF0000"> //Set the value of data at the read position</FONT> -<BR> *array_[msg_no]->rd_ptr()=msg_no; -<BR><FONT COLOR="#FF0000"> //Advance write pointer</FONT> -<BR> array_[msg_no]->wr_ptr(1); -<BR><FONT COLOR="#FF0000"> //Enqueue on the message queue</FONT> -<BR> if(mq_->enqueue_prio(array_[msg_no])==-1){ -<BR> ACE_DEBUG((LM_ERROR,"\nCould not enqueue on to mq!!\n")); -<BR> return; -<BR> } -<BR> ACE_DEBUG((LM_INFO,"Data %d\n",*array_[msg_no]->rd_ptr())); -<BR> } - -<P>void dequeue_all(){ -<BR> ACE_DEBUG((LM_INFO,"Beginning DQ \n")); -<BR> ACE_DEBUG((LM_INFO,"No. of Messages on Q:%d Bytes on Q:%d \n", -mq_->message_count(),mq_->message_bytes())); -<BR> for(int i=0;i<no_msgs_ ;i++){ -<BR> ACE_Message_Block *mb; -<BR> if(mq_->dequeue_head(mb)==-1){ -<BR> ACE_DEBUG((LM_ERROR,'\nCould not dequeue from mq!!\n")); -<BR> return; -<BR> } -<BR> ACE_DEBUG((LM_INFO,"DQd data %d\n",*mb->rd_ptr())); -<BR> } -<BR> } -<BR>private: -<BR> Args *args_; -<BR> ACE_Message_Block **array_; -<BR> ACE_Message_Queue<ACE_NULL_SYNCH> *mq_; -<BR> int no_msgs_; -<BR> int time_; -<BR>}; - -<P>int main(int argc, char* argv[]){ -<BR> QTest test(argc,argv); -<BR> if(test.start_test()<0) -<BR> ACE_DEBUG((LM_ERROR,"Program failure \n")); -<BR> -<BR>} -<BR> -</BODY> -</HTML> diff --git a/docs/tutorials/Makefile b/docs/tutorials/Makefile deleted file mode 100644 index 4a88e3b566a..00000000000 --- a/docs/tutorials/Makefile +++ /dev/null @@ -1,9 +0,0 @@ - -# $Id$ - -all clean realclean UNSHAR SHAR HTML CLEAN : # - for i in ??? ; do \ - [ -f $$i/Makefile ] || continue ; \ - ( cd $$i ; $(MAKE) $@ ) ; \ - done - diff --git a/docs/tutorials/colorize b/docs/tutorials/colorize deleted file mode 100755 index ee61d4bfb14..00000000000 --- a/docs/tutorials/colorize +++ /dev/null @@ -1,20 +0,0 @@ -eval '(exit $?0)' && eval 'exec perl -w -S $0 ${1+"$@"}' - & eval 'exec perl -S $0 $argv:q' - if 0; - -print "<PRE>\n"; -while( <STDIN> ) -{ - s/</\</g; - s,\#(\s*)(e?l?if !?defined|pragma|ifn?def|define)(\W*)([\w\.]+),<font color=blue>\#$1$2</font>$3<font color=purple>$4</font>,; - s,\#\s*(include|endif),<font color=blue>$&</font>,; - s,"([^"]+)","<font color=green>$1</font>",g; - s,//.*$,<font color=red>$&</font>,; - s,/\*,<font color=red>$&,; - s,\*/,$&</font>,; - s,\w+::\~?\w+,<font color=\#008888>$&</font>,; - print STDOUT $_; -} -print "</PRE>\n"; - -0; diff --git a/docs/tutorials/combine b/docs/tutorials/combine deleted file mode 100755 index 24f208880a4..00000000000 --- a/docs/tutorials/combine +++ /dev/null @@ -1,171 +0,0 @@ -eval '(exit $?0)' && eval 'exec perl -w -S $0 ${1+"$@"}' - & eval 'exec perl -S $0 $argv:q' - if 0; - -# $Id$ - -# -# This perl script will combine a set of files into one or more HTML pages. -# -# The file fooNN.html will be created by combining the files: -# fooNN.hdr -# fooNN.pre -# fooNN.bdy -# fooNN.pst -# -# Where NN is a 2-digit number. If fooNN.hdr does not exist, the file 'hdr' -# will be used. If any of the other file-parts don't exist, they will be -# ignored. -# -# Usage: -# combine *.html -# combine *.pre -# -# Input files: -# -# -# hdr -# If no *.hdr exists for the current page, this is used. You will typically -# use this to add <TITLE> and such to each page created. -# -# *.hdr -# You can override the generic hdr you create by creating one for -# a specific page. -# -# *.pre -# Prefix files. Their content is included after the hdr. -# -# *.bdy -# Body files follow prefix. You generally use the links file to create -# links between source-code and a bdy filename. The bdy files are -# examined and "fontified" (think emacs). -# -# bodies -# The list of files to use for the body of the HTML pages generated -# -# *.pst -# Post files. This content follows the bdy content. -# -# *.html -# These are the output. If they exist before you run combine, they -# will be overwritten. -# -use File::Copy; - -%format = (); - -$PAGE=0; - -open(LINKS,"<bodies") || die("No 'bodies' file found!"); -while( ($file = <LINKS>) ) { - - chomp($file); - - next if( $file =~ /^#/ || $file eq '' ); - - if( $file =~ /^.*=/ ) { - ($var,$value) = split(/=/,$file); - if( $var =~ /PAGE/ ) { - $PAGE = $value + 0; - } - next; - } - - $body{$PAGE++} = "$file"; -} -close(LINKS); - -foreach $file (@ARGV) { - ($base = $file) =~ s/.html$//; - $base =~ s/.pre$//; - - open(FILE,">$base.html") || die; - select(FILE); - $| = 1; - - print FILE '<!-- $Id$ -->' . "\n"; - - # .hdr has the HTML header, title, etc... - if( -f "$base.hdr" ) { - copy("$base.hdr",\*FILE); - } - elsif( -f "hdr" ) { - copy("hdr",\*FILE); - } - # .pre has the discussion of what you'll see on this page - if( -f "$base.pre" ) { - copy("$base.pre",\*FILE); - } - # .bdy is the body of the page - if( -f "$base.bdy" ) { - &addFile("$base.bdy"); - } - - ($num = $base) =~ s/[A-z]//g; - $num += 0; - - if( -f "$body{$num}" || "$body{$num}" =~ /\s/ ) { - &addFile("$body{$num}"); - } - # .pst summarizes what was seen - if( -f "$base.pst" ) { - copy("$base.pst",\*FILE); - } - # .ftr follows the footer to show "continue to next page" stuff - if( -f "$base.ftr" ) { - copy("$base.ftr",\*FILE); - } - else { - ++$num; - $base =~ s/[0-9]//g; - $next = sprintf("$base%02.2d",$num); - print FILE "<P><HR WIDTH=\"100%\">\n"; - print FILE "<CENTER>[<A HREF=\"../online-tutorials.html\">Tutorial Index</A>] "; - if( $file ne $ARGV[$#ARGV] ) { - print FILE "[<A HREF=\"$next.html\">Continue This Tutorial</A>]"; - } - print FILE "</CENTER>\n"; - } - print FILE "\n"; - close(FILE); -} - -sub addFile { - local($file) = @_; - - local(@file) = split(/\s+/,$file); - - foreach $file (@file) - { - if( $#file > 0 ) - { - print FILE "<HR width=50%><P><center>$file</center><HR width=50%>\n"; - } - print FILE "<PRE>\n" ; - open(INPUT,"<$file") || die "Cannot open $file for read\n"; - # Do some substitutes on each line to try and get the output to - # look like it does in fontified emacs. - while( <INPUT> ) - { - s/</\</g; - if( m,include\s+"ace/.*\.h", ) { - s,(ace/.*\.h),<A HREF="../../../$1">$1</A>,; - s,\#\s*include,<font color=blue>$&</font>,; - } - else - { - s,\#(\s*)(e?l?if !?defined|pragma|ifn?def|define)(\W*)([\w\.]+),<font color=blue>\#$1$2</font>$3<font color=purple>$4</font>,; - s,\#\s*(include|endif),<font color=blue>$&</font>,; - s,"([^"]+)","<font color=green>$1</font>",g; - s,//.*$,<font color=red>$&</font>,; - s,/\*,<font color=red>$&,; - s,\*/,$&</font>,; - s,\w+::\~?\w+,<font color=\#008888>$&</font>,; - } - s/[ \t]+$//; - s/\t/ /g; - print FILE $_; - } - print FILE "</PRE>\n"; - } -} diff --git a/docs/tutorials/fix.Makefile b/docs/tutorials/fix.Makefile deleted file mode 100755 index 8e3d2ac9187..00000000000 --- a/docs/tutorials/fix.Makefile +++ /dev/null @@ -1,68 +0,0 @@ -eval '(exit $?0)' && eval 'exec perl -w -S $0 ${1+"$@"}' - & eval 'exec perl -S $0 $argv:q' - if 0; - -require "getopts.pl"; -&Getopts("f:o:"); - -$opt_f = "Makefile" if( ! $opt_f ); -$opt_o = ".depend" if( ! $opt_o ); - - # Open the Makefile that has been mangled by 'make depend' - # and suck it into a perl array. -open(IF,"<$opt_f") || die; -@makefile = <IF>; -close(IF); - - # Now open our .depend file and a temporary Makefile. - # We'll split the original Makefile between these two. -open(DF,">$opt_o") || die; -open(MF,">$opt_f.tmp") || die; - - # For each line we read out of the original file... -foreach (@makefile) { - - # If we're into the dependency section, write the line - # into the .depend file. - # - if( $depend ) { - print DF $_; - } - else { - # If we haven't gotten to the dependency section yet - # then see if the current line is the separator that - # "make depend" causes to be inserted. - # - if( m/^\Q# DO NOT DELETE THIS LINE -- g++dep uses it.\E/ ) { - - # If so, change our "mode" and skip this line. - ++$depend; - next; - } - - # Also skip the "include .depend" that we insert. If we - # don't do this, it is possible to have a bunch of these - # inserted into the output when we read an unmangled Makefile - next if( m/^include $opt_o/ ); - - # Print the non-dependency info to the temporary Makefile - print MF $_; - } -} - -# Tell our new Makefile to include the dependency file -print MF "include $opt_o\n"; - -# Close the two output files... -close(DF); -close(MF); - -# Unlink (remove) the original Makefile and rename our -# temporary file. There's obviously room for error checking -# here but we've got the Makefile checked into some revision -# control system anyway. Don't we? - -unlink("$opt_f"); -rename("$opt_f.tmp","$opt_f"); - -exit(0); diff --git a/docs/tutorials/guide-tutorials.html b/docs/tutorials/guide-tutorials.html deleted file mode 100644 index 38455b7e51d..00000000000 --- a/docs/tutorials/guide-tutorials.html +++ /dev/null @@ -1,47 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.05 [en] (X11; I; SunOS 5.5.1 sun4u) [Netscape]"> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#333333" ALINK="#FE0000"> - -<HR WIDTH="100%"><P> -<H3>Online Examples from the ACE Programmers Guide</H3> - -The following page has links to the example code that is presented in -the <A HREF="http://www.cs.wustl.edu/~schmidt/ACE-tutorial.ps.gz">ACE -programmers guide</a>. The guide was created at <A -HREF="http://www.hns.com">Hughes Network Systems</A>. Questions -regarding the guide should be sent to <A -HREF="mailto:usyyid@hns.com">Umar Syyid <usyyid@hns.com></A> - -<P> -<HR WIDTH="100%"> -<H3>Chapter Breakdown</H3> - - -<H4> Chapter 2: <A HREF="Chap_2/ex01.html">IPC _SAP</A></H4> - -<H4> Chapter 3: <A HREF="Chap_3/ex01.html">Memory Management</A></H4> - -<H4> Chapter 4: <A HREF="Chap_4/ex01.html">Thread Management</A></H4> - -<H4> Chapter 5: Tasks and Active Objects</H4> - -<H4> Chapter 6: <A HREF="Chap_5/ex01.html">The Reactor</A></H4> - -<H4> Chapter 7: <A HREF="Chap_6/ex01.html">The Acceptor and Connector</A></H4> - -<H4> Chapter 8: The Service Configurator</H4> - -<H4> Chapter 9: <A HREF="Chap_7/ex01.html">Message Queues</A></H4> - -<P><HR> - -<P>Back to the <A HREF="../ACE-tutorials.html">ACE tutorials</A> page. - -<P> -<!--#include virtual="/~schmidt/cgi-sig.html" --> -</BODY> -</HTML> diff --git a/docs/tutorials/linify b/docs/tutorials/linify deleted file mode 100755 index ad2016905ff..00000000000 --- a/docs/tutorials/linify +++ /dev/null @@ -1,54 +0,0 @@ -eval '(exit $?0)' && eval 'exec perl -w -S $0 ${1+"$@"}' - & eval 'exec perl -S $0 $argv:q' - if 0; - -while( $#ARGV > -1 ) { - - print "$ARGV[0]\n"; - - $source = "$ARGV[0]"; - - if( $source =~ /~$/ ) { - $dest = "$`"; - } else { - rename("$source","$source"."~") || die "Cannot rename ($source)"; - $dest = "$source"; - $source .= "~"; - } - - open(INPUT,"<$source") || die "Cannot open ($source)"; - open(OUTPUT,">$dest") || die "Cannot open ($dest)"; - - $n = 1; - - $prestrip = 0; - while( <INPUT> ) { - chomp; - - if( ! $prestrip && /^[0-9]+\.\t/ ) { - $prestrip = 1; - $_ = $'; - } elsif( $prestrip ) { - if( /^[0-9]+\.\t/ ) { - $_ = $'; - } else { - s/^\t//; - } - } - - if( /^\s*$/ || /^\s*({|})\s*;?\s*$/ || /^\s*\/\// - || /^\s*private\s*:/ || /^\s*protected\s*:/ || /^\s*public\s*:/ - || /^\s*}?\s*else\s*{?\s*:/ - ) { - print OUTPUT "\t$_\n"; - } else { - print OUTPUT "$n.\t$_\n"; - ++$n; - } - } - - close(INPUT); - close(OUTPUT); - - shift(@ARGV); -} diff --git a/docs/tutorials/new-tutorials.html b/docs/tutorials/new-tutorials.html deleted file mode 100644 index 60748d02f4b..00000000000 --- a/docs/tutorials/new-tutorials.html +++ /dev/null @@ -1,76 +0,0 @@ - <!-- $Id$ --> -<TITLE>Developing New ACE+TAO Tutorials</TITLE> -<BODY text = "#000000" link="#000fff" vlink="#ff0f0f" bgcolor="#ffffff"> - -<HR><P> -<H3>Developing New ACE+TAO Tutorials</H3> - -Here are some general guidelines for creating new ACE+TAO tutorials: -<P> - -<hr width=50% align=left> -<H4>Choose a Topic You Know Very Well (or are just learning)</h4> - - This isn't really a conflict... -<P> - If you know a topic very well, you're likely to know what is most - important to the novice and what can be left until later. If you're - just learning a topic, then you know what questions you have that - must be answered before you can continue. -<P> -<hr width=50% align=left> -<H4> Keep It Simple</H4> -<P> - Don't try to use a lot of really cool ACE+TAO features along the way. Stick - to the basic stuff and show that. Try to use a minimum of ACE+TAO objects - that are not the direct target of the tutorial. -<P> - (For instance, don't get all caught up in ACE_Singleton<> if you're - trying to show how to use an ACE_Reactor.) -<P> - If you want to show something really cool that happens to depend on - another ACE+TAO feature, do a tutorial on that other feature first! I've - found that folks will tend to get stuck on *anything* they don't - understand even if it isn't directly relevant to what you're trying - to teach. -<P> -<hr width=50% align=left> -<h4>Document the Heck Out of It!</H4> -<P> - There's no such thing as too much documentation. Don't worry about - repeating yourself along the way. Assume that the reader knows nothing - at all about the topic at hand and explain even the parts that you feel - are painfully obvious. -<P> - If you feel that sticking a bunch of comments in the code makes it harder - to read then stick in a label and document at the end of the file or - something. Alternately, create both a well-documented version and a - sparsely-documented version. Then folks can choose between 'em. -<P> -<hr width=50% align=left> -<h4>Over-teach It</H4> -<P> - If there's a tutorial created for a topic that you feel strong in, - create another one anyway. Everybody tends to code a little differently. - Perhaps your tutorial style will "feel" better to some newcomers - than an existing tutorial. You won't hurt anybody's feelings if - you present the same material in a different way. -<P> -<hr width=50% align=left> -<h4>Leverage Existing Code</H4> -<P> - The ultimate form of code reuse :-) Seriously... grab one or more - of the existing ACE+TAO tests or examples. Then strip it down to the - bare bones & add heaps of comments. I don't think the software-police - will be coming after anyone for that! - -<P> If this thing takes off, I'll start to organize the tutorials into -groups. For now, lets concentrate on quantity & quality. -Organization can come later... <P> - -<HR><P> -Back to the <A -HREF="../ACE-tutorials.html">ACE -tutorials</A> or <A HREF="../../TAO/docs/TAO-tutorials.html">TAO -tutorials</A> page. - diff --git a/docs/tutorials/online-tutorials.html b/docs/tutorials/online-tutorials.html deleted file mode 100644 index 60be812258d..00000000000 --- a/docs/tutorials/online-tutorials.html +++ /dev/null @@ -1,154 +0,0 @@ -<HTML> -<!-- $Id$ --> -<HEAD> - <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> - <META NAME="GENERATOR" CONTENT="Mozilla/4.04 [en] (X11; I; Linux 2.0.32 i486) [Netscape]"> - <META NAME="Author" CONTENT="James CE Johnson"> - <TITLE>Online ACE Tutorials</TITLE> -</HEAD> -<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> - -<HR> -<H3> -Online ACE Tutorials</H3> - -The following online tutorials are designed to help get you started -with ACE. The original audience for these tutorials was the <A -HREF="http://www.lads.com">Automated Design Systems</A> (ADS) IPC -team, lead by <A HREF="mailto:jcej@lads.com">James Johnson</A>. Since -then, the scope has been changed to include anyone who wants to learn -about the ACE framework. Hopefully, even experienced ACE programmers -will find something new here. With a framework as encompassing as ACE, -it is easy to become an expert in one area and know little or nothing -about others. <P> - -<FONT size=-1>Before you try compiling Tutorial 2 (and beyond) you -might want to read these comments about <A HREF="templates.html">C++ -templates</A></font> <P> - -<P><HR WIDTH="50%" align=left><P> -<H4> -Your basic Client/Server hookup</H4> - -<OL> -<LI> -<A HREF="001/page01.html">A -Simple Server</A></LI> - -<LI> -<A HREF="002/page01.html">A -Simpler Server</A></LI> - -<LI> -<A HREF="003/page01.html">Finally, -a Client</A></LI> - -<LI> -<A HREF="004/page01.html">A -much <I>cooler</I> client</A></LI> -</OL> - -<P><HR WIDTH="50%" align=left><P> -<H4> -A word about concurrency</H4> - -<OL> -<LI> -<A HREF="005/page01.html">No -threads, nothing fancy, just do the work!</A></LI> - -<LI> -<A HREF="006/page01.html">I'd -like to dedicate... a thread to each connection.</A></LI> - -<LI> -<A HREF="007/page01.html">Let's -pool our resources: a fixed-size pool of threads.</A></LI> -</OL> - -<P><HR WIDTH="50%" align=left><P> - -<H4> -Finding servers on your network</H4> - -<OL> -<LI> -<A HREF="008/page01.html">Calling -all servers!</A></LI> - -<LI> -<A HREF="009/page01.html">Discriminating tastes...</A></LI> -</OL> - -<P><HR WIDTH="50%" align=left><P> - -<H4> -A word about ACE_Message_Queue</H4> - -<OL> -<LI> -<A HREF="010/page01.html">Puttin' data</A></LI> -<LI> -<A HREF="011/page01.html">What about non-trivial data?</A></LI> -<LI> -<A HREF="012/page01.html">Puttin' pointers</A></LI> -<LI> -<A HREF="013/page01.html">Task chains and state machines</A></LI> -</OL> - -<P><HR WIDTH="50%" align=left><P> - -<H4> -Paddling down (and up) the ACE_Stream</H4> - -<OL> -<LI> -<A HREF="014/page01.html">ACE_Stream Tutorial, Of Sorts</A></LI> -<LI> -<A HREF="015/page01.html">A certain amount of Protocol is required!</A></LI> -</OL> - -<P><HR WIDTH="50%" align=left><P> - -<H4> -Keeping yourself in synch</H4> -<OL> -<LI> -<A HREF="016/page01.html">On one condition...</A> -<LI> -<A HREF="017/page01.html">Something about Barriers</A> -<LI> -<A HREF="018/page01.html">Tokens & templates</A> -</OL> - -<P><HR WIDTH="50%" align=left><P> - -<H4> -Do you remember...</H4> -<OL> -<LI> -<A HREF="019/page01.html">Using System V Shared Memory for telepathy</A> -<LI> -<A HREF="020/page01.html">Never forget anything else again!</A> -<LI> -<A HREF="021/page01.html">Pooling your memories via ACE_Malloc</A> -</OL> - -<P><HR WIDTH="50%" align=left><P> - -<H4> -Configurin' components dynamically</H4> -<OL> -<LI> -<A HREF="022/page01.html">Using the ACE Service Configurator framework</A> -</OL> - -<HR> - -<P>Back to the <A HREF="../ACE-tutorials.html">ACE tutorials</A> page. - -<P> -<!--#include virtual="/~schmidt/cgi-sig.html" --> -</BODY> -</HTML> - diff --git a/docs/tutorials/templates.html b/docs/tutorials/templates.html deleted file mode 100644 index 76822f7071d..00000000000 --- a/docs/tutorials/templates.html +++ /dev/null @@ -1,190 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> -<html> - <!-- $Id$ --> - <head> - <title>About C++ Templates</title> - </head> - - <BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#000FFF" VLINK="#FF0F0F"> -<center> - <h1>About C++ Templates</h1> -</center> - - - <hr> - -When you get to server.cpp in Tutorial 2 you'll see these lines at the bottom: -<P> -<UL> -<PRE> -<font color=blue>#if defined</font> (<font color=purple>ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION</font>) -template class ACE_Acceptor <Logging_Handler, ACE_SOCK_ACCEPTOR>; -template class ACE_Svc_Handler<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 <Logging_Handler, ACE_SOCK_ACCEPTOR> -<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> -<font color=blue>#endif</font> <font color=red>/* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */</font> -Thanks to Krishna Padmasola for providing these. -</PRE> -</UL> -<P> -What's that all about? -<P> -Well, if you've been doing ACE for more than about 30 seconds you will -have run into the joys and sorrows of C++ templates. They're really -great things that prevent the need for complex #define'd macros, -ensure type safety and do other really nifty things. One of the -problems, however, is that not all compilers can figure out what -templates you need. -<P> -Take the simple templated class: -<UL> -<PRE> - -template <class DATATYPE> -class MyTemplate -{ -public: - MyTemplate(void) - { - } - - DATATYPE data(void) - { - return data_; - } - - void data( DATATYPE _data ) - { - data_ = _data; - } - -protected: - - DATATYPE data_; -}; -</PRE> -</UL> -<P> -Now suppose you write the following code fragment: -<P> -<UL> -<PRE> -int main(int,char**) -{ - MyTemplate<int> itemp; - MyTemplate<char> ctemp; - - ... -} -</pre> -</ul> -<P> -Some compilers will take care of you and automatically generate the -equivalent classes: -<UL> -<pre> -class MyTemplate -{ -public: - MyTemplate(void) - { - } - - int data(void) - { - return data_; - } - - void data( int _data ) - { - data_ = _data; - } - -protected: - - int data_; -}; - -class MyTemplate -{ -public: - MyTemplate(void) - { - } - - char data(void) - { - return data_; - } - - void data( char _data ) - { - data_ = _data; - } - -protected: - - char data_; -}; -</pre> -</ul> -<P> -On the other hand, some compilers will complain loudly about undefined -symbols and all sorts of other things. When Clinton Carr compiled -server.cpp of Tutorial 2 on his RedHat 5.1 (gcc) system, for instance, -he was rewarded with these lovely errors: -<P> -<UL> -<PRE> -server.cpp:60: undefined reference to `ACE_Acceptor<Client_Handler, ACE_SOCK_Acceptor>::ACE_Acceptor(ACE_Reactor *)' -server.cpp:72: undefined reference to `ACE_Acceptor<Client_Handler, ACE_SOCK_Acceptor>::open(ACE_INET_Addr const &, ACE_Reactor *,int)' -server.cpp:73: undefined reference to `ACE_Acceptor<Client_Handler, ACE_SOCK_Acceptor>::~ACE_Acceptor(void)' -server.cpp:112: undefined reference to `ACE_Acceptor<Client_Handler, ACE_SOCK_Acceptor>::~ACE_Acceptor(void)' - -</PRE> -</UL> -<P> -Figuring out the correct manual instantiations is usually an -iterative and tedious process. On Linux, I generally use a version of gcc that -will do automatic instantiaion. "Normal" gcc with the Cygnus repo -patches does that as does egcs. Lately (1/99) I've been using egcs -1.1.1 with pretty good results. On our Digital Unix 4.0b system the -native compiler (CXX) has switches that will request it to also -automatically instantiate templates as needed. -<P> -The tradeoffs? -<P> -If you choose to do manual instantiation then your code will work just -about anywhere ACE will. For complex applications, it can take a -number of hours to get things right. -<P> -If you choose to let the compiler do instantiations for you then it -will perform the iterative process. That means that every compile -will be longer than without manual instantiations. -<P> -Compromise? -<P> -Yes, you can do that. You can manually instantiate some -templates and let the compiler get the rest. Some compilers will -generate output that you can then use to figure out the correct -templates. Gcc/egcs create .rpo files for each object. These files -contain mangled names that the compiler uses to figure out what to -instantiate. With c++filt and some patience, you can parse that stuff -to figure out what the compiler is instantiating for you. Note that -c++filt expects you to have a GNU-flavored C++ compiler available. -<P> -My best advice is to get a compiler that will handle the -instantiations for you. When you have some free time on your hands, -take a look at its intermediate files (if any) and start working on -manual instantiation. -<P> -For some more hints, take a look at <A HREF="../../ACE-INSTALL.html#g++">ACE-INSTALL</A> -<P> - <hr> - -Thanks to Amos Shapira for catching a number of errors here. - - </body> -</html> - diff --git a/docs/tutorials/tutorials.dsw b/docs/tutorials/tutorials.dsw deleted file mode 100644 index f443e215f03..00000000000 --- a/docs/tutorials/tutorials.dsw +++ /dev/null @@ -1,412 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00
-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
-
-###############################################################################
-
-Project: "001"=.\001\001.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "002"=.\002\002.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "003"=.\003\003.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "004"=.\004\004.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "005"=.\005\005.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "006"=.\006\006.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "007"=.\007\007.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "008 broadcast"=".\008\008-broadcast.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "008 direct"=".\008\008-direct.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "008 server"=".\008\008-server.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "009 broadcast"=".\009\009-broadcast.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "009 directed"=".\009\009-directed.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "009 server"=".\009\009-server.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "010"=.\010\010.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "011"=.\011\011.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "012"=.\012\012.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "013"=.\013\013.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "014"=.\014\014.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "015 client"=".\015\015-client.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "015 server"=".\015\015-server.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "016"=.\016\016.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "017"=.\017\017.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "018"=.\018\018.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "019 client"=".\019\019-client.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "019 client2"=".\019\019-client2.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "019 server"=".\019\019-server.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "019 server2"=".\019\019-server2.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "020 client"=".\020\020-client.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "020 client2"=".\020\020-client2.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "020 server"=".\020\020-server.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "020 server2"=".\020\020-server2.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "021 client"=".\021\021-client.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "021 server"=".\021\021-server.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Global:
-
-Package=<5>
-{{{
-}}}
-
-Package=<3>
-{{{
-}}}
-
-###############################################################################
|