
Felipe Magno de Almeida wrote:
On 2/6/06, Giovanni P. Deretta <gpderetta@gmail.com> wrote:
While Christopher can certainly answer better than i can, i think that the answer is: because it often doesn't need to be! A socket is a non copyable value based object. It doesn't need dynamic allocation and could very well be stack based (as the datagram_socket and the socket_acceptor in the example).
And it doesnt have to, I use shared_ptr to handle my sockets while not using dynamic allocation. The ability to configure a deleter makes it very easy to handle resources without using operator new and nor delete. And IMO it would be much easier than prohibing copying of the socket.
The problem is that a socket is *conceptually* not copyable. Even if you have multiple handles to it, they all refer to the same underlying stream. Standard streams are not copyable for the same reason. If you want different objects to *share* a socket you use a shared_ptr and dynamically allocate it.
Only if you need the lifetime of the object to be dynamic (as the example does, but it is *not* always the case) you directly allocate it. Or make it be a member of a class that is itself dynamically allocated.
Even making it a member of the class you'll probably need it to be passed along to another class, which is impossible without copy-construction. Which would need the socket (or the class that owns the socket) to be dynamically allocated and its lifetime to be watched (maybe through shared_ptr).
well, you could hold a shared_ptr (with a null deleter) to the socket or class that owns it and have its lifetime be watched by weak_pointers. This way no dynamic allocation is needed. If you want the lifetime to be dynamic, that is "as long as some one has a reference to it", use dynamic allocation an shared_ptr.
You could make the socket class hold internally a shared_ptr to a socket_impl and make it (shallow) copyable, but it would it be surprising and would require dynamic allocation(*) even if not needed.
Yes, probably always since you cant copy or move the socket...
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.
A nice solution would be to make socket movable...
IMO, it wouldnt be a complete solution, but part of it.
Why not? If you want shared ownership you dynamically allocate, there is no way around it. If you want to give up ownership (to move the object a long a chain of functions implementing a state machine for example), you move it.
(*) Not really, all copies of stream could hold a copy of socket_imp and only the last one would close it, but it would still require some sort of reference counting.
shared_ptr can be used, since it is already done and optimized to a lot of platforms. Why not use it inside the library?
Well, I'm sure asio uses it in lot's of places :) ... if you mean asio should use it to implement reference counting of the underlying socket_impl, yes, it could do it *if* you decide to make the socket copyable (and I think it the wrong choice). BTW, I might have misunderstood some (or all) of your reply and be arguing about the wrong thing. Sorry if it is so :) -- Giovanni P. Deretta