On Fri, Jul 4, 2014 at 9:18 PM, Niall Douglas
On 3 Jul 2014 at 23:16, Dean Michael Berris wrote:
FWIW, I was in the room when the Boost.Asio proposal was being discussed way back in Kona. I haven't seen the most recent update to the proposal, but if my original concerns were addressed, mainly:
- The io_service type was trying to be too many things at the same time (executor, ran in thread-pools, implementing IO-specific hooks, etc.) and was too prominent in the interfaces of primitive types (i.e. sockets, etc.).
Some would call that the low-level interfacing necessary to achieve bare metal performance.
But, there's no reason you couldn't decompose this and not make it part of the invariants of the objects associated with them. For example, when you create a socket object, can you not do that by acquiring it from some function that internally would determine how it's wired? auto connection = establish_connection(remote_address, my_executor);
- There were too many leaking abstractions crossing boundaries -- being able to reach in to get native handles, buffer lifetimes crossing in-and-out, etc.
Ditto.
- The fact that it seems the only implementation of the networking parts (and inter-operating bits implied by the interface) would be through a proactor -- how the API was only proactive, no support for just purely reactive applications.
Kinda hard to do true async without.
Can you expand this a little?
- There's no means for doing "zero-copy" I/O which is a platform-specific but modern way of doing data transfer through existing interfaces.
I don't know what you refer to here. ASIO doesn't copy data being sent or received. It passes through literally what it receives from the OS.
Right. Does it support direct-memory I/O -- where I write to some memory location instead of scheduling a write? See RDMA, and on Linux vmsplice(...). Can I "donate" the memory I have from user-space to the kernel, which just remaps the memory onto a device's memory buffer? How do I achieve "raw" buffer performance if I have to provide a user-space allocated buffer for data to be written into from the kernel, and then write out data if the data was in a user-space buffer that gets passed to the kernel? We've moved on to better interfaces in the lower levels of the networking stack, and it would be a shame if we precluded this from being adopted by a standard library specification.
A few that come to mind for potential approaches here are:
- Transport-level abstractions. Considering whether looking at policy-driven transport protocol abstractions (say, an http connection, a raw TCP connection, an SCTP connection with multiple streams, etc.) would be more suitable higher-level abstractions than sockets and write/read buffers.
- Agent-based models. More precisely explicitly having an agent of sorts, or an abstraction of a client/server where work could be delegated, composed with executors and schedulers.
These are all outside the remit of a core C++ networking library.
Why?
I say this with all due respect -- while network programming sounds like it's all about sockets, buffers, event loops, and such there are the "boring" bits like addressing, network byte ordering, encoding/decoding algorithms (for strings and blobs of data), framing algorithms, queueing controls, and even back-off algorithms, congestion control, traffic shaping. There's more things to think about too like data structures for efficiently representing frames, headers, network buffers, routing tables, read-write buffer halves, ip address tries, network topologies, protocol encodings (ASN.1, MIME and friends), and a whole host of network-related concepts we're not even touching in the networking discussions.
I'm personally not unsympathetic to this sentiment. However, it would surely need POSIX to move on it first before C++ could.
Why?