[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [Libevent-users] deferred callbacks and evbuffer cleanup_cb



On Sun, Mar 20, 2016 at 3:55 PM, Azat Khuzhin <a3at.mail@xxxxxxxxx> wrote:
> On Sun, Mar 20, 2016 at 03:11:31PM +0100, Jan Heylen wrote:
>> On Sun, Mar 20, 2016 at 3:01 PM, Azat Khuzhin <a3at.mail@xxxxxxxxx> wrote:
>> >> > bufferevent_write() just move data from user-passed to bufferevent
>> >> > internal, you can get internal output buffer with
>> >> > bufferevent_get_output()
>> >>
>> >> Ah, indeed, did think about that one in the scope of using the
>> >> evbuffer callbacks, but the problem remains the same at that moment:
>> >> once you have the bufferevent_get_output, one should not alter the
>> >> callbacks for the output buffer of bev. So I'm not sure what that
>> >> would bring me in this case?
>> >
>> > evbuffer callbacks will remain the same until free, but why do you need
>> > them?
>> I've got X bytes of userdata, scattered over Y memory parts, I add
>> them to one evbuffer, using the evbuffer_add_reference.
>> Then I use evbuffer_write to send them to the fd, until it gets a
>> 'wouldblock', from that point on I defer the work via a bufferevent
>> (bufferevent_write_buffer).
>>
>> But I want to inform the user who sends me X bytes, when these X bytes
>> where actually send (as one action, when they are all out).
>>
>> In first place, I was thinking on using the evbuffer callbacks, but
>> turns out that buffervevent_write_buffer already would call these
>> callbacks (as the original is buffer is drained), and the callbacks of
>> the buffervent's internal outbuf should not be overwritten. Also, even
>> with these callbacks on the internal output buffer of bufferevent, it
>> wouldn't help probably, as 'other data' is also there, so how would
>> you keep track of the right data.
>
> Actually you can add callbacks for bufferevent_get_output(), and
> libevent won't free them until bufferevent exist, so it can be used, but
> yeah cleanup_cb callback is more suitable for this case.
>
> And also quoting your original email:
>> some background:
>> * using (tcp) sockets
>> * sending data over the socket: in first place try to write
>> (evbuffer_write), if you get 'wouldblock' postpone the write by using
>> bufferevent_write_buffer. Main reason is we don't need to keep the
>> user's data in most cases and the dat is send immediatly.
>> * after sending data, a 'send cb' should be called to the user who
>> wanted to send something.
>
> Why do you need this special case evbuffer_write(), can you just use
> bufferevent_write_buffer() always?
In most cases, that would be overkill, as long as the fd/socket is not
overloaded, the data should go out immediately (so the data can be on
the stack of the function that was trying to send it, and no
'memcpy'/malloc/data housekeeping has to happen at all)

> And in case you don't call evbuffer_write() manually your must be good.
>
>> Now, when looking at the best way to get the cleanup happening (and a
>> mechanism to let the user know his data is send), I was looking at
>> both evbuffer callbacks and the evbuffer cleanup_cb.
>> I'm thinking on using the cleanup_cb, as it is only called when the
>> chain, the actual data, gets freed, so I can be sure the data is out.
>> With evbuffer callbacks, the original evbuffer gets drained upon call
>> to bufferevent_write_buffer already, and not when the data itself is
>> really 'out', so that means, I have to make a distinction.
>
> Since cleanup_cb must be called only when reference didn't exist,
> example:
>  struct evbuffer *buf = evbuffer_new();
>  evbuffer_add_reference(buf, data, len, cleanup, buf);
>  bufferevent_write_buffer(evbuf, buf);
>  evbuffer_free(buf);
> And during this calls "cleanup" will not be called because
> bufferevent_write_buffer() will take the chain ownership (part of
> evbuffer that contains you reference), so when you call evbuffer_free()
> there is no chain in evbuffer so "cleanup" will not be called yet.
Indeed, I know, the reason I want to use cleanup, suits my needs.

> "cleanup" will be called only when it will be drained from
> bufferevent_get_output() and it will happen only it will be written to
> the client, or I'm missing something and it doesn't work like this?
No, that is indeed what I was planning to do, but I thought I was
missing something, as these cleanup_cbs
didn't come with deferred thingy. At the moment I'm going to do this
without deferring. But I'll probably have to add that later.

Btw, is there a reason why the deferral infrastructure is 'internal'?
Wouldn't it be useful as an extra interface of libevent? Especially
the deferral implementation of 2.1.x, where some issues with
priorities where solved I understood from the documentation. Or is
there a reason not to use it as a more 'generic' callback deferral
infrastructure?

best regards,

Jan
>
> Regards,
> Azat.
> ***********************************************************************
> To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
> unsubscribe libevent-users    in the body.
***********************************************************************
To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users    in the body.