Have container bufferevents hold a reference to their underlying bufferevents.
(Commit message and minor revisions by nickm.)
/** Internal: Drop the reference count on bufev, freeing as necessary, and
* unlocking it otherwise. */
void _bufferevent_decref_and_unlock(struct bufferevent *bufev);
+/** Sometimes it is more clear to say "decref" than "free" */
+#define bufferevent_decref(b) bufferevent_free(b)
/** Internal: If callbacks are deferred and we have a read callback, schedule
* a readcb. Otherwise just run the readcb. */
{
struct bufferevent_private *bufev_private =
EVUTIL_UPCAST(bufev, struct bufferevent_private, bev);
+ struct bufferevent *underlying;
if (--bufev_private->refcnt) {
BEV_UNLOCK(bufev);
return;
}
+ underlying = bufferevent_get_underlying(bufev);
+
/* Clean up the shared info */
if (bufev->be_ops->destruct)
bufev->be_ops->destruct(bufev);
/* Free the actual allocated memory. */
mm_free(bufev - bufev->be_ops->mem_offset);
+
+ /* release the reference to underlying now that we no longer need
+ * the reference to it. This is mainly in case our lock is shared
+ * with underlying.
+ * XXX Should we/can we just refcount evbuffer/bufferevent locks?
+ * It would probably save us some headaches.
+ */
+ if (underlying)
+ bufferevent_decref(underlying);
}
void
bufferevent_filtered_outbuf_cb, bufev_f);
_bufferevent_init_generic_timeout_cbs(downcast(bufev_f));
+ bufferevent_incref(underlying);
return downcast(bufev_f);
}
if (options & BEV_OPT_THREADSAFE)
bufferevent_enable_locking(&bev_ssl->bev.bev, NULL);
- if (underlying)
+ if (underlying) {
_bufferevent_init_generic_timeout_cbs(&bev_ssl->bev.bev);
+ bufferevent_incref(underlying);
+ }
bev_ssl->state = state;
bev_ssl->last_write = -1;