
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