diff options
Diffstat (limited to 'docs/tutorials/007/page08.html')
-rw-r--r-- | docs/tutorials/007/page08.html | 537 |
1 files changed, 0 insertions, 537 deletions
diff --git a/docs/tutorials/007/page08.html b/docs/tutorials/007/page08.html deleted file mode 100644 index 094804e743d..00000000000 --- a/docs/tutorials/007/page08.html +++ /dev/null @@ -1,537 +0,0 @@ -<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> - - -<P> -<HR WIDTH="100%"> - -<P>Finally, <A HREF="thread_pool.cpp">thread_pool.cpp</A> -where we have the Thread_Pool object implementation. - -<P> -<HR WIDTH="100%"> - -<P><FONT FACE="Arial,Helvetica">// $Id: thread_pool.cpp,v 1.1 1998/08/30 -23:47:15 schmidt Exp $</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">#include "thread_pool.h"</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> We need this header so that -we can invoke handle_input() on the objects we dequeue.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica">#include "ace/Event_Handler.h"</FONT> -<BR><FONT FACE="Arial,Helvetica"></FONT> <FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> All we do here is initialize -our active thread counter.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica">Thread_Pool::Thread_Pool(void)</FONT> -<BR><FONT FACE="Arial,Helvetica"> : active_threads_(0)</FONT> -<BR><FONT FACE="Arial,Helvetica">{</FONT> -<BR><FONT FACE="Arial,Helvetica">}</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> Our open() method is a thin -disguise around the ACE_Task<> activate() method. By</FONT> -<BR><FONT FACE="Arial,Helvetica"> hiding activate() in this -way, the users of Thread_Pool don't have to worry about</FONT> -<BR><FONT FACE="Arial,Helvetica"> the thread configuration -flags.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica">int Thread_Pool::open( int _pool_size -)</FONT> -<BR><FONT FACE="Arial,Helvetica">{</FONT> -<BR><FONT FACE="Arial,Helvetica"> return this->activate(THR_NEW_LWP|THR_DETACHED,_pool_size);</FONT> -<BR><FONT FACE="Arial,Helvetica">}</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> Closing the thread pool can -be a tricky exercise. I've decided to take an easy approach</FONT> -<BR><FONT FACE="Arial,Helvetica"> and simply enqueue a secret -message for each thread we have active.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica">int Thread_Pool::close(void)</FONT> -<BR><FONT FACE="Arial,Helvetica">{</FONT> -<BR><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Find out how many threads are currently active</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT> -<BR><FONT FACE="Arial,Helvetica"> -int counter = active_threads_.value();</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -For each one of the active threads, enqueue a "null" event handler. -Below, we'll</FONT> -<BR><FONT FACE="Arial,Helvetica"> -teach our svc() method that "null" means "shutdown".</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT> -<BR><FONT FACE="Arial,Helvetica"> -while( counter-- )</FONT> -<BR><FONT FACE="Arial,Helvetica"> -{</FONT> -<BR><FONT FACE="Arial,Helvetica"> -this->enqueue( 0 );</FONT> -<BR><FONT FACE="Arial,Helvetica"> -}</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -As each svc() method exits, it will decrement the active thread counter. -We just wait</FONT> -<BR><FONT FACE="Arial,Helvetica"> -here for it to reach zero. Since we don't know how long it will take, -we sleep for</FONT> -<BR><FONT FACE="Arial,Helvetica"> -a quarter-second or so between tries.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT> -<BR><FONT FACE="Arial,Helvetica"> -while( active_threads_.value() )</FONT> -<BR><FONT FACE="Arial,Helvetica"> -{</FONT> -<BR><FONT FACE="Arial,Helvetica"> -ACE_OS::sleep( ACE_Time_Value(0.25) );</FONT> -<BR><FONT FACE="Arial,Helvetica"> -}</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -return(0);</FONT> -<BR><FONT FACE="Arial,Helvetica">}</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> When an object wants to do -work in the pool, it should call the enqueue() method.</FONT> -<BR><FONT FACE="Arial,Helvetica"> We introduce the ACE_Message_Block -here but, unfortunately, we seriously missuse it.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica">int Thread_Pool::enqueue( ACE_Event_Handler -* _handler )</FONT> -<BR><FONT FACE="Arial,Helvetica">{</FONT> -<BR><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -An ACE_Message_Block is a chunk of data. You put them into an ACE_Message_Queue.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -ACE_Task<> has an ACE_Message_Queue built in. In fact, the parameter -to ACE_Task<></FONT> -<BR><FONT FACE="Arial,Helvetica"> -is passed directly to ACE_Message_Queue. If you look back at our -header file you'll</FONT> -<BR><FONT FACE="Arial,Helvetica"> -see that we used ACE_MT_SYNCH as the parameter indicating that we want -MultiThread</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Synch safety. This allows us to safely put ACE_Message_Block objects -into the</FONT> -<BR><FONT FACE="Arial,Helvetica"> -message queue in one thread and take them out in another.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -An ACE_Message_Block wants to have char* data. We don't have that. -We could</FONT> -<BR><FONT FACE="Arial,Helvetica"> -cast our ACE_Event_Handler* directly to a char* but I wanted to be more -explicit.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Since casting pointers around is a dangerous thing, I've gone out of my -way here</FONT> -<BR><FONT FACE="Arial,Helvetica"> -to be very clear about what we're doing.</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -First: Cast the handler pointer to a void pointer. You can't -do any useful work</FONT> -<BR><FONT FACE="Arial,Helvetica"> -on a void pointer, so this is a clear message that we're making the</FONT> -<BR><FONT FACE="Arial,Helvetica"> -pointer unusable.</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -Next: Cast the void pointer to a char pointer that the ACE_Message_Block -will accept.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT> -<BR><FONT FACE="Arial,Helvetica"> -void * v_data = (void*)_handler;</FONT> -<BR><FONT FACE="Arial,Helvetica"> -char * c_data = (char*)v_data;</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Construct a new ACE_Message_Block. For efficiency, you might want -to preallocate a</FONT> -<BR><FONT FACE="Arial,Helvetica"> -stack of these and reuse them. For simplicity, I'll just create what -I need as I need it.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT> -<BR><FONT FACE="Arial,Helvetica"> -ACE_Message_Block * mb = new ACE_Message_Block( c_data );</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Our putq() method is a wrapper around one of the enqueue methods of the -ACE_Message_Queue</FONT> -<BR><FONT FACE="Arial,Helvetica"> -that we own. Like all good methods, it returns -1 if it fails for -some reason.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT> -<BR><FONT FACE="Arial,Helvetica"> -if( this->putq(mb) == -1 )</FONT> -<BR><FONT FACE="Arial,Helvetica"> -{</FONT> -<BR><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Another trait of the ACE_Message_Block objects is that they are reference -counted.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Since they're designed to be passed around between various objects in several -threads</FONT> -<BR><FONT FACE="Arial,Helvetica"> -we can't just delete them whenever we feel like it. The release() -method is similar</FONT> -<BR><FONT FACE="Arial,Helvetica"> -to the destroy() method we've used elsewhere. It watches the reference -count and will</FONT> -<BR><FONT FACE="Arial,Helvetica"> -delete the object when possible.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT> -<BR><FONT FACE="Arial,Helvetica"> -mb->release();</FONT> -<BR><FONT FACE="Arial,Helvetica"> -return(-1);</FONT> -<BR><FONT FACE="Arial,Helvetica"> -}</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -return(0);</FONT> -<BR><FONT FACE="Arial,Helvetica">}</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> The "guard" concept is very -powerful and used throughout multi-threaded applications.</FONT> -<BR><FONT FACE="Arial,Helvetica"> A guard normally does some -operation on an object at construction and the "opposite"</FONT> -<BR><FONT FACE="Arial,Helvetica"> operation at destruction. -For instance, when you guard a mutex (lock) object, the guard</FONT> -<BR><FONT FACE="Arial,Helvetica"> will acquire the lock on -construction and release it on destruction. In this way, your</FONT> -<BR><FONT FACE="Arial,Helvetica"> method can simply let the -guard go out of scope and know that the lock is released.</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> Guards aren't only useful -for locks however. In this application I've created two guard</FONT> -<BR><FONT FACE="Arial,Helvetica"> objects for quite a different -purpose.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> The Counter_Guard is constructed -with a reference to the thread pool's active thread</FONT> -<BR><FONT FACE="Arial,Helvetica"> counter. The guard -increments the counter when it is created and decrements it at</FONT> -<BR><FONT FACE="Arial,Helvetica"> destruction. By creating -one of these in svc(), I know that the counter will be decremented</FONT> -<BR><FONT FACE="Arial,Helvetica"> no matter how or where svc() -returns.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica">class Counter_Guard</FONT> -<BR><FONT FACE="Arial,Helvetica">{</FONT> -<BR><FONT FACE="Arial,Helvetica">public:</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Counter_Guard( Thread_Pool::counter_t & _counter )</FONT> -<BR><FONT FACE="Arial,Helvetica"> -: counter_(_counter)</FONT> -<BR><FONT FACE="Arial,Helvetica"> -{</FONT> -<BR><FONT FACE="Arial,Helvetica"> -++counter_;</FONT> -<BR><FONT FACE="Arial,Helvetica"> -}</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -~Counter_Guard(void)</FONT> -<BR><FONT FACE="Arial,Helvetica"> -{</FONT> -<BR><FONT FACE="Arial,Helvetica"> ---counter_;</FONT> -<BR><FONT FACE="Arial,Helvetica"> -}</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">protected:</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Thread_Pool::counter_t & counter_;</FONT> -<BR><FONT FACE="Arial,Helvetica">};</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> My Message_Block_Guard is -also a little non-traditional. It doesn't do anything in the</FONT> -<BR><FONT FACE="Arial,Helvetica"> constructor but it's destructor -ensures that the message block's release() method is called.</FONT> -<BR><FONT FACE="Arial,Helvetica"> This is a cheap way to prevent -a memory leak if I need an additional exit point in svc().</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica">class Message_Block_Guard</FONT> -<BR><FONT FACE="Arial,Helvetica">{</FONT> -<BR><FONT FACE="Arial,Helvetica">public:</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Message_Block_Guard( ACE_Message_Block * & _mb )</FONT> -<BR><FONT FACE="Arial,Helvetica"> -: mb_(_mb)</FONT> -<BR><FONT FACE="Arial,Helvetica"> -{</FONT> -<BR><FONT FACE="Arial,Helvetica"> -}</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -~Message_Block_Guard( void )</FONT> -<BR><FONT FACE="Arial,Helvetica"> -{</FONT> -<BR><FONT FACE="Arial,Helvetica"> -mb_->release();</FONT> -<BR><FONT FACE="Arial,Helvetica"> -}</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">protected:</FONT> -<BR><FONT FACE="Arial,Helvetica"> -ACE_Message_Block * & mb_;</FONT> -<BR><FONT FACE="Arial,Helvetica">};</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica">/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> Now we come to the svc() -method. As I said, this is being executed in each thread of the</FONT> -<BR><FONT FACE="Arial,Helvetica"> Thread_Pool. Here, -we pull messages off of our built-in ACE_Message_Queue and cause them</FONT> -<BR><FONT FACE="Arial,Helvetica"> to do work.</FONT> -<BR><FONT FACE="Arial,Helvetica"> */</FONT> -<BR><FONT FACE="Arial,Helvetica">int Thread_Pool::svc(void)</FONT> -<BR><FONT FACE="Arial,Helvetica">{</FONT> -<BR><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -The getq() method takes a reference to a pointer. So... we need a -pointer to give it</FONT> -<BR><FONT FACE="Arial,Helvetica"> -a reference to.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT> -<BR><FONT FACE="Arial,Helvetica"> -ACE_Message_Block * mb;</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Create the guard for our active thread counter object. No matter -where we choose to</FONT> -<BR><FONT FACE="Arial,Helvetica"> -return() from svc(), we no know that the counter will be decremented.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Counter_Guard counter_guard(active_threads_);</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Get messages from the queue until we have a failure. There's no real -good reason</FONT> -<BR><FONT FACE="Arial,Helvetica"> -for failure so if it happens, we leave immediately.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT> -<BR><FONT FACE="Arial,Helvetica"> -while( this->getq(mb) != -1 )</FONT> -<BR><FONT FACE="Arial,Helvetica"> -{</FONT> -<BR><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -A successful getq() will cause "mb" to point to a valid refernce-counted</FONT> -<BR><FONT FACE="Arial,Helvetica"> -ACE_Message_Block. We use our guard object here so that we're sure -to call</FONT> -<BR><FONT FACE="Arial,Helvetica"> -the release() method of that message block and reduce it's reference count.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Once the count reaches zero, it will be deleted.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Message_Block_Guard message_block_guard(mb);</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -As noted before, the ACE_Message_Block stores it's data as a char*. -We pull that</FONT> -<BR><FONT FACE="Arial,Helvetica"> -out here and later turn it into an ACE_Event_Handler*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT> -<BR><FONT FACE="Arial,Helvetica"> -char * c_data = mb->base();</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -We've chosen to use a "null" value as an indication to leave. If -the data we got</FONT> -<BR><FONT FACE="Arial,Helvetica"> -from the queue is not null then we have some work to do.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT> -<BR><FONT FACE="Arial,Helvetica"> -if( c_data )</FONT> -<BR><FONT FACE="Arial,Helvetica"> -{</FONT> -<BR><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Once again, we go to great lengths to emphasize the fact that we're casting -pointers</FONT> -<BR><FONT FACE="Arial,Helvetica"> -around in rather impolite ways. We could have cast the char* directly -to an</FONT> -<BR><FONT FACE="Arial,Helvetica"> -ACE_Event_Handler* but then folks might think that's an OK thing to do.</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -(Note: The correct way to use an ACE_Message_Block is to write data -into it.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -What I should have done was create a message block big enough to hold an</FONT> -<BR><FONT FACE="Arial,Helvetica"> -event handler pointer and then written the pointer value into the block. -When</FONT> -<BR><FONT FACE="Arial,Helvetica"> -we got here, I would have to read that data back into a pointer. -While politically</FONT> -<BR><FONT FACE="Arial,Helvetica"> -correct, it is also a lot of work. If you're careful you can get -away with casting</FONT> -<BR><FONT FACE="Arial,Helvetica"> -pointers around.)</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT> -<BR><FONT FACE="Arial,Helvetica"> -void * v_data = (void*)c_data;</FONT> -<BR><FONT FACE="Arial,Helvetica"> </FONT> -<BR><FONT FACE="Arial,Helvetica"> -ACE_Event_Handler * handler = (ACE_Event_Handler*)v_data;</FONT> -<BR><FONT FACE="Arial,Helvetica"> </FONT> -<BR><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Now that we finally have an event handler pointer, invoke it's handle_input() -method.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Since we don't know it's handle, we just give it a default. That's -OK because we</FONT> -<BR><FONT FACE="Arial,Helvetica"> -know that we're not using the handle in the method anyway.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT> -<BR><FONT FACE="Arial,Helvetica"> -if( handler->handle_input(ACE_INVALID_HANDLE) == -1 )</FONT> -<BR><FONT FACE="Arial,Helvetica"> -{</FONT> -<BR><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Tell the handler that it's time to go home. The "normal" method for -shutting</FONT> -<BR><FONT FACE="Arial,Helvetica"> -down a handler whose handler failed is to invoke handle_close(). -This will</FONT> -<BR><FONT FACE="Arial,Helvetica"> -take care of cleaning it up for us.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Notice how we use the handler's get_handle() method to populate it's "handle"</FONT> -<BR><FONT FACE="Arial,Helvetica"> -parameter. Convenient isn't it?</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT> -<BR><FONT FACE="Arial,Helvetica"> -handler->handle_close(handler->get_handle(),0);</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -Also notice that we don't exit the svc() method here! The first time -I did</FONT> -<BR><FONT FACE="Arial,Helvetica"> -this, I was exiting. After a few clients disconnect you have an empty</FONT> -<BR><FONT FACE="Arial,Helvetica"> -thread pool. Hard to do any more work after that...</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT> -<BR><FONT FACE="Arial,Helvetica"> -}</FONT> -<BR><FONT FACE="Arial,Helvetica"> -}</FONT> -<BR><FONT FACE="Arial,Helvetica"> -else</FONT> -<BR><FONT FACE="Arial,Helvetica"> -{</FONT> -<BR><FONT FACE="Arial,Helvetica"> -/*</FONT> -<BR><FONT FACE="Arial,Helvetica"> -If we get here, we were given a message block with "null" data. That -is our</FONT> -<BR><FONT FACE="Arial,Helvetica"> -signal to leave, so we return(0) to leave gracefully.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -*/</FONT> -<BR><FONT FACE="Arial,Helvetica"> -return(0); -// Ok, shutdown request</FONT> -<BR><FONT FACE="Arial,Helvetica"> -}</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -// message_block_guard goes out of scope here</FONT> -<BR><FONT FACE="Arial,Helvetica"> -// and releases the message_block instance.</FONT> -<BR><FONT FACE="Arial,Helvetica"> -}</FONT><FONT FACE="Arial,Helvetica"></FONT> - -<P><FONT FACE="Arial,Helvetica"> -return(0);</FONT> -<BR><FONT FACE="Arial,Helvetica">}</FONT> - -<P> -<HR WIDTH="100%"> -<CENTER>[<A HREF="..">Tutorial -Index</A>] [<A HREF="page09.html">Continue -This Tutorial</A>]</CENTER> - -</BODY> -</HTML> |