Boost logo

Boost :

From: Christopher Kohlhoff (chris_at_[hidden])
Date: 2005-12-13 06:37:10


Hi Eugene,

--- Eugene Alterman <eugalt_at_[hidden]> wrote:
> I will call this interfaces core_socket and stream_socket
> respectively. You always start with an object of a
> stream_socket class and then obtain a reference to core_socket
> from it.
>
> Let us first start with a design that does not change the
> current interface of stream_socket. Define a new core_socket
> class template, and derive stream_socket from it adding the
> stream functionality. Then we can define lowest_layer_type as
> core_socket. This will solve the stream layering problem since
> having a reference to core_socket of a lower layer would not
> allow performing stream operations on it.
>
> The next step would be to derive stream_socket privately from
> core_socket and provide a public member function returning a
> reference to core_socket. This would deal with any temptation
> to downcast a core_socket reference to stream_socket.

I think I understand what you want now, however I propose a few
modifications, especially to preserve source compatibility with
existing code and keep the common use cases simple.

The core_socket template (don't particularly like the name, will
think about it) could be used as the base for both stream_socket
and datagram socket since they share everything except the
read_some/write_some/send*/receive* functions. E.g.:

template <typename Service>
class core_socket
{
public:
  ...
  typedef core_socket<Service> lowest_layer_type;
  lowest_layer_type& lowest_layer() { return *this; }

protected:
  service_type& service_;
  impl_type impl_;
};

template <typename Service>
class basic_stream_socket
  : private core_socket<Service>
{
public:
  ...
  typedef core_socket<Service> lowest_layer_type;
  lowest_layer_type& lowest_layer() { return *this; }
};

template <typename Service>
class basic_datagram_socket
  : private core_socket<Service>
{
public:
  ...
  typedef core_socket<Service> lowest_layer_type;
  lowest_layer_type& lowest_layer() { return *this; }
};

The next_layer_type typedefs and next_layer() functions would
be removed.

The derived type should bring all public names from core_socket
into its own public interface. Are using declarations OK in this
case? If not, then via forwarding functions.

That way existing uses of stream_socket continue to work as-is.
Uses of stream templates would lose access to the underlying
socket's I/O functions, as you want.

Note there is still a way to circumvent the layering but it is
now an explicit choice, e.g.:

  stream_socket inner(demuxer);
  buffered_stream<stream_socket&> outer(inner);

Would anyone else care to comment on this modification?

Cheers,
Chris


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk