event/Loop: allow scheduling events before Run()

Add the debug-only flag "virgin" which gets checked by assert()
calls.  Fixes assertion failures when using zeroconf/avahi.
This commit is contained in:
Max Kellermann 2014-01-09 17:50:29 +01:00
parent 0c34555b02
commit 61b938d6fa
3 changed files with 29 additions and 5 deletions

View File

@ -38,7 +38,7 @@ IdleMonitor::Cancel()
void void
IdleMonitor::Schedule() IdleMonitor::Schedule()
{ {
assert(loop.IsInside()); assert(loop.IsInsideOrVirgin());
if (IsActive()) if (IsActive())
/* already scheduled */ /* already scheduled */

View File

@ -32,6 +32,9 @@ EventLoop::EventLoop(Default)
:SocketMonitor(*this), :SocketMonitor(*this),
now_ms(::MonotonicClockMS()), now_ms(::MonotonicClockMS()),
quit(false), busy(true), quit(false), busy(true),
#ifndef NDEBUG
virgin(true),
#endif
thread(ThreadId::Null()) thread(ThreadId::Null())
{ {
SocketMonitor::Open(wake_fd.Get()); SocketMonitor::Open(wake_fd.Get());
@ -58,7 +61,7 @@ EventLoop::Break()
bool bool
EventLoop::Abandon(int _fd, SocketMonitor &m) EventLoop::Abandon(int _fd, SocketMonitor &m)
{ {
assert(IsInside()); assert(IsInsideOrVirgin());
poll_result.Clear(&m); poll_result.Clear(&m);
return poll_group.Abandon(_fd); return poll_group.Abandon(_fd);
@ -76,7 +79,7 @@ EventLoop::RemoveFD(int _fd, SocketMonitor &m)
void void
EventLoop::AddIdle(IdleMonitor &i) EventLoop::AddIdle(IdleMonitor &i)
{ {
assert(IsInside()); assert(IsInsideOrVirgin());
assert(std::find(idle.begin(), idle.end(), &i) == idle.end()); assert(std::find(idle.begin(), idle.end(), &i) == idle.end());
idle.push_back(&i); idle.push_back(&i);
@ -86,7 +89,7 @@ EventLoop::AddIdle(IdleMonitor &i)
void void
EventLoop::RemoveIdle(IdleMonitor &i) EventLoop::RemoveIdle(IdleMonitor &i)
{ {
assert(IsInside()); assert(IsInsideOrVirgin());
auto it = std::find(idle.begin(), idle.end(), &i); auto it = std::find(idle.begin(), idle.end(), &i);
assert(it != idle.end()); assert(it != idle.end());
@ -97,7 +100,7 @@ EventLoop::RemoveIdle(IdleMonitor &i)
void void
EventLoop::AddTimer(TimeoutMonitor &t, unsigned ms) EventLoop::AddTimer(TimeoutMonitor &t, unsigned ms)
{ {
assert(IsInside()); assert(IsInsideOrVirgin());
timers.insert(TimerRecord(t, now_ms + ms)); timers.insert(TimerRecord(t, now_ms + ms));
again = true; again = true;
@ -120,6 +123,12 @@ void
EventLoop::Run() EventLoop::Run()
{ {
assert(thread.IsNull()); assert(thread.IsNull());
assert(virgin);
#ifndef NDEBUG
virgin = false;
#endif
thread = ThreadId::GetCurrent(); thread = ThreadId::GetCurrent();
assert(!quit); assert(!quit);

View File

@ -98,6 +98,14 @@ class EventLoop final : SocketMonitor
*/ */
bool busy; bool busy;
#ifndef NDEBUG
/**
* True if Run() was never called. This is used for assert()
* calls.
*/
bool virgin;
#endif
PollGroup poll_group; PollGroup poll_group;
PollResult poll_result; PollResult poll_result;
@ -198,6 +206,13 @@ public:
return thread.IsInside(); return thread.IsInside();
} }
#ifndef NDEBUG
gcc_pure
bool IsInsideOrVirgin() const {
return virgin || IsInside();
}
#endif
#ifndef NDEBUG #ifndef NDEBUG
gcc_pure gcc_pure
bool IsInsideOrNull() const { bool IsInsideOrNull() const {