event/DeferredMonitor: make fully thread-safe

Instead of creating a new eventfd for each DeferredMonitor instance,
reuse EventLoop's eventfd, and add a std::list to EventLoop that
manages the list of pending DeferredMonitors.  This std::list is
protected by the same mutex as the "calls" list.

The bottom line is: reduced overhead because the per-instance eventfd
was eliminated, slightly added overhead due to Mutex usage (but
negligible), and we're thread-safe now.

This subsystem is now good enough to replace EventLoop::AddCall().
This commit is contained in:
Max Kellermann
2014-01-04 14:56:02 +01:00
parent 48c96bbaea
commit a357d84dce
4 changed files with 77 additions and 54 deletions

View File

@@ -25,7 +25,7 @@ void
DeferredMonitor::Cancel()
{
#ifdef USE_INTERNAL_EVENTLOOP
pending = false;
loop.RemoveDeferred(*this);
#endif
#ifdef USE_GLIB_EVENTLOOP
const auto id = source_id.exchange(0);
@@ -38,8 +38,7 @@ void
DeferredMonitor::Schedule()
{
#ifdef USE_INTERNAL_EVENTLOOP
if (!pending.exchange(true))
fd.Write();
loop.AddDeferred(*this);
#endif
#ifdef USE_GLIB_EVENTLOOP
const unsigned id = loop.AddIdle(Callback, this);
@@ -49,21 +48,6 @@ DeferredMonitor::Schedule()
#endif
}
#ifdef USE_INTERNAL_EVENTLOOP
bool
DeferredMonitor::OnSocketReady(unsigned)
{
fd.Read();
if (pending.exchange(false))
RunDeferred();
return true;
}
#endif
#ifdef USE_GLIB_EVENTLOOP
void