
Felipe Magno de Almeida wrote:
IMHO it is not true that a socket is *conceptually* not copyable. In every platform I use copying sockets are a very intuitive operation. Couldnt a socket be *conceptually* a reference counted resource? What, IMO, a socket is *not* is a resource that uses dynamic allocation. There's no point in using new operator to allocate memory for a socket!
Well, what you have is actually an *handle* to a dynamically allocated socket resource: an int on posix system (where the resource is usually in kernel space) and a SOCKET on win32 that if I'm not mistaken is actually a typedefed pointer to a dynamically allocated userspace resource. So, yes, the handle can be copied in the same way you can copy a *pointer* to a asio::stream_socket. The fact that boost::stream_socket is itself implemented using a non aliased handle to a socket is an implementation and transport specific detail. Conceptually a stream_socket behaves as a reference to the underlying stream. This means that if you want to share a asio::stream_socket you usually have do dynamically allocate it. And btw system sockets cannot be copied. For example, you can open a file two times or you can dup() a socket, but the new handle refers always to the underlying resource.
My point is that it shouldnt be needed to use dynamic allocation to use a socket. Even if you need to share it.
[snip]
Yes what? Always what? Are you talking about always needing dynamic allocation? Definitely not. I've written code that uses asio stream_sockets without using dynamic allocation nor moving nor sharing ownership.
If you could show me maybe it could explain a lot of what you mean. Can you show me any code and what is its use case?
Well, my code is not actually the expected way to use asio. I'm using a coroutine library tightly coupled with asio. asio_sockets are allocated on the stack and are and callbacks simply resume the coroutine that queued a call to an asio asynch function. You can find some experimental code in the boost vault under concurrency. Beware, it is still experimental, and I've found out that the package that I've uploaded does not compile. Unfortunately i won't be able to work on it until the next week. But you can check the examples to get a feeling of what I've in mind.
But I'm still not getting how you solve most of the use cases for asio without relying on dynamic memory allocation or why you believe it should be needed dynamic memory allocation on these cases.
Not considering my coroutine example (very exotic and not yet complete), I think that often you do not need to really share an asio::stream_socket. That means that you usually have only one object that owns it. Other objects that might have a reference do not dictate its lifetime. This means that you can use weak pointers (and, as you have already stated, shared_ptr and smart_ptr do not imply dynamic allocation). You could argue that as this is a useful behavior stream_socket should have pointer semantics by default and be reference counted. But you would force the space and time overhead of a shared_ptr to everybody (btw, shared_ptr still require dynamic allocation of the reference counter). Most of asio examples use a dynamically allocate stream_socket that is passed from callback to callback until the last one closes it explicitly. A shared_ptr in this case works well, but is less than ideal (you really have only one reference to the object at any time). An move pointer would be better, but it still require dynamic allocation. If the asio_stream itself was movable it would be perfect. This would require asio to be *move* around callbacks instead of copying them (and probably would require support from boost::bind and boost::function as these are often used with asio). Disclaimer: I do not really have enough experience to say that asio can really solve all use case easily. You are certainly more experienced than I am. In the network library i was working on I've used exactly the same approach you have described (the stream object holds a shared_ptr to the stream_impl), but later I did realize that a non copyable socket would have been better. -- Giovanni P. Deretta