Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does libuv provide any facilities to attach a buffer to a connection and re use it

Tags:

c

libuv

I am evaluating libuv as a library for a C/c++ server that I am writing. The protocol is length prefixed so as soon as I can read a 32 bit integer from the stream I should be able to tell what size of buffer I should allocate. The documentation says that the uv_read_start function might be called multiple times.

UV_EXTERN int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read_cb read_cb);

Since I am using a length prefixed protocol, once I know the right size of the buffer I would like to allocate it and re use it for subsequent reads till I have received all my bytes. Is there an easy way to do this with libuv? Right now it seems like the uv_alloc_cb function has to take care of this. Can I associate a buffer with my stream object instead of putting it in a map or something?

Since I am using a length prefixed protocol, I would not like to allocate a buffer on the heap at all till I can read the first 4 bytes (32 bits). Is it possible for me to allocate on the stack a buffer of size 4 and have the uv_read_cb function actually do the heap allocation? Is the uv_read_cb function invoked synchronously as part of the uv_read_start function? If it is then seems like I should be able to allocate on the stack when I know that I don't already have a buffer attached to my stream.

like image 563
Rajiv Avatar asked Oct 07 '13 01:10

Rajiv


1 Answers

Answering my own question. I found the answers on the libuv mailing list here: https://groups.google.com/forum/#!topic/libuv/fRNQV_QGgaA

Copying the details here if the link becomes unavailable:

Attaching your own data structure to a handle:

The handle has a void* data field that is yours to use. You can make it point it to an auxiliary structure where you store the length and the buffer.

Alternatively, you can embed the uv_tcp_t in another structure, then look up the embedding structure with container_of. It's not a standard C macro but you can find its definition and usage examples in the libuv/ source tree. Its benefit is that it just does some pointer arithmetic, it saves you from another level of pointer indirection.

Stack allocation for the receiving buffer:

No, that's not possible. The proper way of thinking about it is that your alloc_cb returns a buffer that libuv will fill with data sometime in the future. The stress is on "sometime" because there are no guarantees when that will happen; it may be immediate, it may be seconds (or minutes) away.

like image 135
Rajiv Avatar answered Oct 04 '22 00:10

Rajiv