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
IdleMonitor::Schedule()
{
assert(loop.IsInside());
assert(loop.IsInsideOrVirgin());
if (IsActive())
/* already scheduled */

View File

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

View File

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