[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 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?
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,
 struct evbuffer *buf = evbuffer_new();
 evbuffer_add_reference(buf, data, len, cleanup, buf);
 bufferevent_write_buffer(evbuf, 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.
"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?

To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users    in the body.