Commit 61b938d6 authored by Max Kellermann's avatar Max Kellermann

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.
parent 0c34555b
...@@ -38,7 +38,7 @@ IdleMonitor::Cancel() ...@@ -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 */
......
...@@ -32,6 +32,9 @@ EventLoop::EventLoop(Default) ...@@ -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() ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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);
......
...@@ -98,6 +98,14 @@ class EventLoop final : SocketMonitor ...@@ -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;
...@@ -200,6 +208,13 @@ public: ...@@ -200,6 +208,13 @@ public:
#ifndef NDEBUG #ifndef NDEBUG
gcc_pure gcc_pure
bool IsInsideOrVirgin() const {
return virgin || IsInside();
}
#endif
#ifndef NDEBUG
gcc_pure
bool IsInsideOrNull() const { bool IsInsideOrNull() const {
return thread.IsNull() || thread.IsInside(); return thread.IsNull() || thread.IsInside();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment