Boost logo

Boost :

From: Giovanni P. Deretta (gpderetta_at_[hidden])
Date: 2006-02-06 23:06:20


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

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk