Sophie

Sophie

distrib > Mandriva > 10.0-com > i586 > by-pkgid > 21280410b6ea906d791d7a12afae2579 > files > 105

libace5-doc-5.4-2mdk.i586.rpm

<!-- page03.html,v 1.10 2000/03/19 20:09:23 jcej Exp -->
<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>// page03.html,v 1.10 2000/03/19 20:09:23 jcej Exp</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>