|
Boost : |
From: Giovanni P. Deretta (gpderetta_at_[hidden])
Date: 2006-02-06 20:03:16
Felipe Magno de Almeida wrote:
> On 2/6/06, Giovanni P. Deretta <gpderetta_at_[hidden]> 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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk