[Home]BoostSocket/AsynchAcceptorConcept

BOOST WIKI | BoostSocket | RecentChanges | Preferences | Page List | Links List

It would be cool if we could abstract away the multiplexing policy and async/polling selecting style.

There might be some subtle difference in the behavior of the code with respect to thread affinity for operations and such (with poll/select style all notifications for a socket will come on exactly one thread in async style the notifications will come on any thread).

Who will own the multiplexor and drive the eventloop?

 template <typename SocketBase?, typename Multiplexor>
 class acceptor_socket
 {
   template <typename Protocol, class Addr>
   socket_errno open(
      const Protocol& protocol, 
      const Addr& address, 
      Multiplexor& multiplexor)
   {
      m_base.open(protocol, address);
      m_impl.attach(multiplexor);
      return Success;
   }
   template <class Addr>
      socket_errno accept(
      data_connection_t& data_socket, 
      Addr& address, 
      std::function<void(socket_errno)> callback)
   {
   }

 private:
   template<typename SCHEME>
   struct accept_impl {};
   template<multiplex_scheme::polling>
   struct accept_impl 
   {
      ~accept_impl()
      {
         multiplexor.detach(m_base.socket()); // detach from multiplexor
      }

      typedef tuple< data_connection_t*, std::pair<void*, unsigned int>, std::function<void(socket_errno)> > accept_args;
      template <class Addr>
         socket_errno accept(
         data_connection_t& data_socket, 
         Addr& address, 
         std::function<void(socket_errno)> callback = std::function<void(socket_errno)>())
      {
         m_queue.push_back( accept_args(&data_socket, address.representation(), callback) );
      }
      void attach(Multiplexor& multiplexor) 
      {
         multiplexor.attach(
               m_base.socket(), 
               boost::bind(&accept_impl<Multiplexor::Type>::on_accept, boost::ref(*this)), event_mask::accept);

      }

      void on_accept(event_mask evt)
      {
         accept_args args = m_queue.top();                        
         m_queue.pop();                                           // pop arguments
         socket_errno errno = do_accept(*t.get<0>(), t.get<1>()); // execute accept
         t.get<3>()(errno);                                       // call completion

      }

      std::queue< accept_args > m_queue;
      Multiplexor*                   m_multiplexor;
   };

   template<multiplex_scheme::asynch>
   struct accept_impl 
   {
      template <class Addr>
         socket_errno accept(
         data_connection_t& data_socket, 
         Addr& address, 
         std::function<void(socket_errno)> callback = std::function<void(socket_errno)>())
      {
         do_asynch_accept(data_socket, address, callback); // queue a synch accept on socket
      }
      void on_accept(event_mask evt)
      {
         // callback will be called by proactor. when accept is finished
      }

      void attach(Multiplexor& multiplexor) 
      {
         multiplexor.attach(m_base.socket());

      }

   };
   accept_impl<Multiplexor::Type> m_impl;
 };

And based on multiplexing policy callback will be called when the accept is done. If a reactor and asynch base socket is used the accept is queued directly to the lower levels, if a proactor is used the operations is queued in the acceptor until an accept notification is received. Threading issues isn't being addressed in the code maybe the queue need to be protected by some kind of lock based on the type of multiplexor.

/Michel?


BOOST WIKI | BoostSocket | RecentChanges | Preferences | Page List | Links List
Edit text of this page | View other revisions
Last edited December 18, 2004 12:31 pm (diff)
Search:
Disclaimer: This site not officially maintained by Boost Developers