asio 0.3.8rc3 | Home | Reference | Tutorial | Examples | Design

Design

# Services

The abstractions asio publishes for sockets (and other resources) are divided into three parts:

- A service that provides a wrapper around a platform's implementation of the resource:

    template <typename Allocator = std::allocator<void> >
    class stream_socket_service
    {
    public:
      // ...

      typedef implementation_defined impl_type;

      // ...

      template <typename Handler>
      void async_receive(impl_type& impl, void* data, size_t max_length,
          socket_base::message_flags flags, Handler handler);

      // ...
    };

- A class template providing an object-oriented interface, where the template parameter is the service:

    template <typename Service>
    class basic_stream_socket
    {
    public:
      typedef Service service_type;
      typedef typename service_type::impl_type impl_type;

      // ...

      template <typename Handler>
      void async_receive(void* data, size_t max_length,
          socket_base::message_flags flags, Handler handler)
      {
        service_.async_receive(impl_, data, max_length, flags, handler);
      }

      // ...

    private:
      service_type& service_;
      impl_type impl_;
    };

- A typedef for the typical usage:

    typedef basic_stream_socket<stream_socket_service<> > stream_socket;

This design attempts meet the following goals:

- To efficiently encapsulate the operating system's interface for the corresponding resource. On most operating systems a socket is represented by an integer, and so the service class wraps that facility portably and without adding a "heavyweight" class around it.

- To allow the implementation of the socket to be customised. Some developers may need to use a different allocator, or perhaps a completely different implementation for sockets. This can be done by supplying a different argument to the basic_stream_socket template.

- To make the most common usage appear no different to a class (in a similar fashion to std::string vs std::basic_string).

## Services and the Demuxer

The asio::io_service object acts as an extensible collection of services, not dissimilar to the way a std::locale object is composed of facets. The io_service contains one service object for each service type, and the service objects are accessed by their types (see asio::basic_io_service::get_service).

However, unlike std::locale, services are loaded by the io_service only when first used. This means that you do not pay for the resources associated with a service unless you instantiate the corresponding class. For example, the deadline_timer_service implementation for Win32 uses a background thread, but this thread will not be created if there are no deadline_timer objects in a program.

This design also allows the io_service to be extended by user-defined services. As an example, a user may want to simulate asynchronous database access using a pool of background threads. A database_connection_service class can be defined to create and manage the thread pool, and each database_connection object uses this service.

asio 0.3.8rc3 | Home | Reference | Tutorial | Examples | Design