Boost logo

Boost :

From: Christopher Kohlhoff (chris_at_[hidden])
Date: 2005-09-02 08:05:55


Hello all,

Thanks to the feedback on the previous thread, I have just released
asio 0.3.3. You can download it, or view the documentation online, at
http://asio.sourceforge.net.

In addition to some general cleanup, the changes include:

- dgram_socket has been renamed to datagram_socket

- send and recv have been replaced by write and read respectively.
  Functions called send and receive have been retained on the socket
  classes with an additonal flags argument. On the datagram_socket,
  sendto has been renamed to send_to, and recvfrom to receive_from.

- timer has been renamed to deadline_timer and redesigned to use
  Boost.Date_Time classes.

- socket_connector has been dropped in favour of connect/async_connect
  functions on both stream_socket and datagram_socket.

- async_get_host_by_address and async_get_host_by_name functions have
  been added to ipv4::host_resolver. The implementation is simple and
  only simulates asynchronicity (using one background thread
per-demuxer
  to execute the corresponding blocking call).

- The ipv4::host structure has been turned into a class.

- The asio::arg namespace has been renamed to asio::placeholders. The
  bytes_recvd and bytes_sent placeholders have been replaced with
  bytes_transferred. Similarly, the last_bytes_recvd/sent and
  total_bytes_recvd/sent have been replaced with last_bytes_transferred
  and total_bytes_transferred.

- The "services" have been made part of the public interface of asio.
  E.g. for basic_stream_socket there is a stream_socket_service. These
  services are also templates and have an allocator as the template
  parameter (although this currently has no effect on the
  implementation).

- Requires Boost 1.33.

I still have much to do in terms of examples and design documentation.

I think the one remaining design issue to address for now is that of
safety (i.e. that some people don't like a void*+size_t interface) and
reconciling that with the others' need for efficiency (sending data
structures directly and avoiding copying).

After pondering for some time, I think I have devised an approach that
meets both requirements. The approach is loosely based on Symbian's
TPtr/TPtrC classes.

Here is an outline of the idea:

- Define two new concepts, Buffer and Const_Buffer:

  class Buffer
  {
  public:
    size_t segment_count() const;
    void* segment_data(size_t index) const;
    size_t segment_size(size_t index) const;
    size_t total_size() const; // sum of all segment sizes
    Buffer sub_buffer(size_t start) const;
    Buffer sub_buffer(size_t start, size_t length) const;
  };

  class Const_Buffer
  {
  public:
    size_t segment_count() const;
    const void* segment_data(size_t index) const;
    size_t segment_size(size_t index) const;
    size_t total_size() const; // sum of all segment sizes
    Const_Buffer sub_buffer(size_t start) const;
    Const_Buffer sub_buffer(size_t start, size_t length) const;
  };

  These concepts are Assignable and CopyConstructible. I included
  the support for multiple segments as it provides a neat solution
  to doing scatter-gather I/O.

- Change all read/write/send/receive functions to only take a buffer
concept, e.g.

  template <typename Const_Buffer>
  size_t send(Const_Buffer b);

  template <typename Buffer>
  size_t receive(Buffer b);

- Provide helper functions to create buffer objects for various types:

  impl_defined_buffer make_buffer(void* data, size_t len);
  impl_defined_const_buffer make_buffer(const void* data, size_t len);

  template <typename T, size_t N>
  impl_defined_buffer make_buffer(T[N] data);
  template <typename T, size_t N>
  impl_defined_const_buffer make_buffer(const T[N] data);

  template <typename T>
  impl_defined_buffer make_buffer(std::vector<T>& data);
  template <typename T>
  impl_defined_const_buffer make_buffer(const std::vector<T>& data);

  // For scatter-gather...
  impl_defined_buffer make_buffer(void* data0, size_t len0,
      ..., void* dataN, size_t lenN);
  impl_defined_const_buffer make_buffer(const void* data0, size_t len0,
      ..., const void* dataN, size_t lenN);

The important thing to note is that the buffer objects do not own the
data they represent. They are intended to be cheap-to-copy value
objects that simply represent a region of memory.

Here are some usage examples:

  demuxer d;
  socket s(d);
 
  // ...

  mystruct m = { ... };
  s.send(make_buffer(&m, sizeof(m)));

  char s[] = "Hello world";
  s.send(make_buffer(s));

  std::vector<char> v(1024);
  s.receive(make_buffer(v));

Thoughts? I'm not really happy with the name Buffer, but couldn't think
of anything else. I'm open to any suggestions.

Cheers,
Chris


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