summaryrefslogtreecommitdiff
path: root/docs/tutorials/007
diff options
context:
space:
mode:
Diffstat (limited to 'docs/tutorials/007')
-rw-r--r--docs/tutorials/007/007.dsp124
-rw-r--r--docs/tutorials/007/Makefile116
-rw-r--r--docs/tutorials/007/client_acceptor.cpp56
-rw-r--r--docs/tutorials/007/client_acceptor.h125
-rw-r--r--docs/tutorials/007/client_handler.cpp229
-rw-r--r--docs/tutorials/007/client_handler.h156
-rw-r--r--docs/tutorials/007/combine.shar685
-rw-r--r--docs/tutorials/007/page01.html83
-rw-r--r--docs/tutorials/007/page02.html138
-rw-r--r--docs/tutorials/007/page03.html154
-rw-r--r--docs/tutorials/007/page04.html86
-rw-r--r--docs/tutorials/007/page05.html187
-rw-r--r--docs/tutorials/007/page06.html261
-rw-r--r--docs/tutorials/007/page07.html120
-rw-r--r--docs/tutorials/007/page08.html281
-rw-r--r--docs/tutorials/007/page09.html78
-rw-r--r--docs/tutorials/007/server.cpp110
-rw-r--r--docs/tutorials/007/thread_pool.cpp252
-rw-r--r--docs/tutorials/007/thread_pool.h89
19 files changed, 0 insertions, 3330 deletions
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 079ae8e6d6a..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 ()->open (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 ()->close ();
-
- 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 02ac8590a80..00000000000
--- a/docs/tutorials/007/client_handler.cpp
+++ /dev/null
@@ -1,229 +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)
-{
- /*
- 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)
-{
- switch (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:
- 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 e6683a9d025..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 1999-09-21 22:49 EDT 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
-# 3386 -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
-# 378 -rw-rw-r-- page08.pre
-# 2071 -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 _sh04829; 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 0121152699 '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:&nbsp; thread-pool.&nbsp; 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".&nbsp; As you'll see, our basic objects will change
-but not by a whole lot.&nbsp; 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 0124153799 'page01.pre' &&
- chmod 0664 'page01.pre' ||
- $echo 'restore of' 'page01.pre' 'failed'
- if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
- && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
- md5sum -c << SHAR_EOF >/dev/null 2>&1 \
- || $echo 'page01.pre:' 'MD5 check failed'
-b38f0bc755d9398afbf71fd8261fdb9b page01.pre
-SHAR_EOF
- else
- shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`"
- test 3386 -eq "$shar_count" ||
- $echo 'page01.pre:' 'original size' '3386,' '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 0121152699 '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 0121152699 '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>.&nbsp;
-I finally had enough code to move it out of the header.
-X
-<P>
-<HR WIDTH="100%">
-SHAR_EOF
- $shar_touch -am 0121152699 '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 0121152699 '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.&nbsp;&nbsp; Just a few
-though.
-X
-<P>
-<HR WIDTH="100%">
-SHAR_EOF
- $shar_touch -am 0121152699 '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.&nbsp; The first is <A HREF="thread_pool.h">thread_pool.h</A>
-where we declare our Thread_Pool object.&nbsp; 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 0121152699 '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 0921222899 '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'
-57908face42dc1aeef042433e6877213 page08.pre
-SHAR_EOF
- else
- shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page08.pre'`"
- test 378 -eq "$shar_count" ||
- $echo 'page08.pre:' 'original size' '378,' '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.&nbsp; As with Tutorial 6, we really didn't
-have to change much to introduce a new threading strategy.&nbsp; Most of
-the work was in creating the Thread_Pool object itself.&nbsp; Everything
-else was just minor housekeeping.
-X
-<P>There is a fourth common thread strategy:&nbsp; thread-per-request.&nbsp;
-It's not one of my favorites, so I wasn't planning to go into it.&nbsp;
-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 0121152599 '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'
-74f66ca26c13797dcf3f8c3132bfe580 page09.pre
-SHAR_EOF
- else
- shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page09.pre'`"
- test 2071 -eq "$shar_count" ||
- $echo 'page09.pre:' 'original size' '2071,' '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.&nbsp;&nbsp; Maybe I should leave out comments
-on the stuff I don't change.&nbsp; Let's take a look at client_acceptor.h.
-X
-<P>
-SHAR_EOF
- $shar_touch -am 0121152899 '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 0121152699 '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.&nbsp; Most of it just manages the Thread_Pool.
-X
-<P>
-SHAR_EOF
- $shar_touch -am 0121152699 '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.&nbsp; 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 0121152899 '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.&nbsp; Beyond that, we're still about
-the same.
-X
-SHAR_EOF
- $shar_touch -am 0121152699 '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.&nbsp; What about the implementation?
-X
-SHAR_EOF
- $shar_touch -am 0121152699 '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 _sh04829
-exit 0
diff --git a/docs/tutorials/007/page01.html b/docs/tutorials/007/page01.html
deleted file mode 100644
index 99d0a81a25e..00000000000
--- a/docs/tutorials/007/page01.html
+++ /dev/null
@@ -1,83 +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:&nbsp; thread-pool.&nbsp; 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".&nbsp; As you'll see, our basic objects will change
-but not by a whole lot.&nbsp; 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 25aa0f050d6..00000000000
--- a/docs/tutorials/007/page02.html
+++ /dev/null
@@ -1,138 +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[])
-{
- <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 &lt;i>restart&lt;/i> flag on
- the open() method of ACE_Reactor if you're interested.) */</font>
- while (!finished)
- reactor.handle_events ();
-
- ACE_DEBUG ((LM_DEBUG,
- "<font color=green>(%P|%t) shutting down server daemon\n</font>"));
-
- return 0;
-}
-
-<font color=blue>#if defined</font> (<font color=purple>ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION</font>)
-template class ACE_Acceptor &lt;Client_Handler, ACE_SOCK_ACCEPTOR>;
-template class ACE_Svc_Handler&lt;ACE_SOCK_STREAM, ACE_NULL_SYNCH>;
-template class ACE_Guard&lt;ACE_Mutex>;
-template class ACE_Atomic_Op&lt;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 &lt;Client_Handler, ACE_SOCK_ACCEPTOR>
-<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Svc_Handler&lt;ACE_SOCK_STREAM, ACE_NULL_SYNCH>
-<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Guard&lt;ACE_Mutex>
-<font color=blue>#pragma</font> <font color=purple>instantiate</font> ACE_Atomic_Op&lt;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.&nbsp;&nbsp; Maybe I should leave out comments
-on the stuff I don't change.&nbsp; 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 8f7a6e9bb98..00000000000
--- a/docs/tutorials/007/page03.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 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&lt;> template lives in the ace/Acceptor.h header
- file. You'll find a very consitent naming convention between the
- ACE objects and the headers where they can be found. In general,
- the ACE object ACE_Foobar will be found in ace/Foobar.h. */</font>
-
-<font color=blue>#include</font> "<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&lt;> template's first
- parameter requires such an object. In some cases, you can get by
- with just a forward declaration on the class, in others you have to
- have the whole thing. */</font>
-<font color=blue>#include</font> "<font color=green>client_handler.h</font>"
-
-<font color=red>/* Parameterize the ACE_Acceptor&lt;> such that it will listen for socket
- connection attempts and create Client_Handler objects when they
- happen. In Tutorial 001, we wrote the basic acceptor logic on our
- own before we realized that ACE_Acceptor&lt;> was available. You'll
- get spoiled using the ACE templates because they take away a lot of
- the tedious details! */</font>
-typedef ACE_Acceptor &lt;Client_Handler, ACE_SOCK_ACCEPTOR> Client_Acceptor_Base;
-
-<font color=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&lt;> 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 2415d48ff56..00000000000
--- a/docs/tutorials/007/page04.html
+++ /dev/null
@@ -1,86 +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>.&nbsp;
-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 ()->open (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 ()->close ();
-
- return <font color=#008888>inherited::close</font> ();
-}
-
-</PRE>
-<HR WIDTH="100%">
-
-<P>Nothing really surprising here.&nbsp; 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 d0995ca37a5..00000000000
--- a/docs/tutorials/007/page05.html
+++ /dev/null
@@ -1,187 +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&lt;> 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 &lt;ACE_SOCK_STREAM, ACE_NULL_SYNCH>
-{
-public:
- typedef ACE_Svc_Handler &lt;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&lt;> will
- invoke this method after creating a new Client_Handler when a
- client connects. Notice that the parameter to open() is a void*.
- It just so happens that the pointer points to the acceptor which
- created us. You would like for the parameter to be an
- ACE_Acceptor&lt;>* but since ACE_Event_Handler is generic, that would
- tie it too closely to the ACE_Acceptor&lt;> set of objects. In our
- definition of open() you'll see how we get around that. */</font>
- int open (void *acceptor);
-
- <font color=red>/* When an ACE_Task&lt;> object falls out of the svc() method, the
- framework will call the close() method. That's where we want to
- cleanup ourselves if we're running in either thread-per-connection
- or thread-pool mode. */</font>
- int close (u_long flags = 0);
-
- <font color=red>/* When there is activity on a registered handler, the
- handle_input() method of the handler will be invoked. If that
- method returns an error code (eg -- -1) then the reactor will
- invoke handle_close() to allow the object to 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 &lt;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&lt;> and it maintains it's own peer
- (ACE_SOCK_Stream) object, this is redundant for us. However, if
- we had been derived directly from ACE_Event_Handler, we may have
- chosen not to contain the peer. In that case, the &lt;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.&nbsp; 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 61f9a4d836e..00000000000
--- a/docs/tutorials/007/page06.html
+++ /dev/null
@@ -1,261 +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.&nbsp;&nbsp; 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)
-{
- <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)
-{
- switch (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:
- 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.&nbsp; 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 462dac9189a..00000000000
--- a/docs/tutorials/007/page07.html
+++ /dev/null
@@ -1,120 +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.&nbsp; The first is <A HREF="thread_pool.h">thread_pool.h</A>
-where we declare our Thread_Pool object.&nbsp; 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&lt;> 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>#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&lt;ACE_MT_SYNCH>
-{
-public:
- typedef ACE_Task&lt;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>/* Opening the thread pool causes one or more threads to be
- activated. When activated, they all execute the svc() method
- declared below. */</font>
- int open (int pool_size = default_pool_size_);
-
- <font color=red>/* Some compilers will complain that our open() above attempts to
- override a virtual function in the baseclass. We have no
- intention of overriding that method but in order to keep the
- compiler quiet we have to add this method as a pass-thru to the
- baseclass method. */</font>
- virtual int open (void *void_data)
- {
- return <font color=#008888>inherited::open</font> (void_data);
- }
-
- <font color=red>/*
- */</font>
- virtual int close (u_long flags = 0);
-
- <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&lt;>. 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&lt;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.&nbsp; 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 d25a7e3e61d..00000000000
--- a/docs/tutorials/007/page08.html
+++ /dev/null
@@ -1,281 +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 open() method is a thin disguise around the ACE_Task&lt;>
- 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::open</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::close</font> (u_long flags)
-{
- ACE_UNUSED_ARG(flags);
-
- <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&lt;> has an ACE_Message_Queue built in.
- In fact, the parameter to ACE_Task&lt;> 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 3331cd46a4f..00000000000
--- a/docs/tutorials/007/page09.html
+++ /dev/null
@@ -1,78 +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.&nbsp; As with Tutorial 6, we really didn't
-have to change much to introduce a new threading strategy.&nbsp; Most of
-the work was in creating the Thread_Pool object itself.&nbsp; Everything
-else was just minor housekeeping.
-
-<P>There is a fourth common thread strategy:&nbsp; thread-per-request.&nbsp;
-It's not one of my favorites, so I wasn't planning to go into it.&nbsp;
-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 878a5035460..00000000000
--- a/docs/tutorials/007/server.cpp
+++ /dev/null
@@ -1,110 +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[])
-{
- /* 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 08302a6811f..00000000000
--- a/docs/tutorials/007/thread_pool.cpp
+++ /dev/null
@@ -1,252 +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 open() 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::open (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::close (u_long flags)
-{
- ACE_UNUSED_ARG(flags);
-
- /* 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 9686b5a29da..00000000000
--- a/docs/tutorials/007/thread_pool.h
+++ /dev/null
@@ -1,89 +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"
-
-#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);
-
- /* Opening the thread pool causes one or more threads to be
- activated. When activated, they all execute the svc() method
- declared below. */
- int open (int pool_size = default_pool_size_);
-
- /* Some compilers will complain that our open() above attempts to
- override a virtual function in the baseclass. We have no
- intention of overriding that method but in order to keep the
- compiler quiet we have to add this method as a pass-thru to the
- baseclass method. */
- virtual int open (void *void_data)
- {
- return inherited::open (void_data);
- }
-
- /*
- */
- virtual int close (u_long flags = 0);
-
- /* 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 */