aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2014-01-09 17:50:29 +0100
committerMax Kellermann <max@duempel.org>2014-01-09 17:52:55 +0100
commit61b938d6fad8211d68eb3921e4c68e38b016e7cc (patch)
treee286bd6081c798507e13394e84ecce89729a526f /src
parent0c34555b02f5d24f8c836534dcc30005a42f2c95 (diff)
downloadmpd-61b938d6fad8211d68eb3921e4c68e38b016e7cc.tar.gz
mpd-61b938d6fad8211d68eb3921e4c68e38b016e7cc.tar.xz
mpd-61b938d6fad8211d68eb3921e4c68e38b016e7cc.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/event/IdleMonitor.cxx2
-rw-r--r--src/event/Loop.cxx17
-rw-r--r--src/event/Loop.hxx15
3 files changed, 29 insertions, 5 deletions
diff --git a/src/event/IdleMonitor.cxx b/src/event/IdleMonitor.cxx
index e791559a1..dd8d64f94 100644
--- a/src/event/IdleMonitor.cxx
+++ b/src/event/IdleMonitor.cxx
@@ -38,7 +38,7 @@ IdleMonitor::Cancel()
void
IdleMonitor::Schedule()
{
- assert(loop.IsInside());
+ assert(loop.IsInsideOrVirgin());
if (IsActive())
/* already scheduled */
diff --git a/src/event/Loop.cxx b/src/event/Loop.cxx
index 6e18b6bf8..8cd4cde72 100644
--- a/src/event/Loop.cxx
+++ b/src/event/Loop.cxx
@@ -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);
diff --git a/src/event/Loop.hxx b/src/event/Loop.hxx
index 4bd2a3b2c..d03259fb0 100644
--- a/src/event/Loop.hxx
+++ b/src/event/Loop.hxx
@@ -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;
@@ -200,6 +208,13 @@ public:
#ifndef NDEBUG
gcc_pure
+ bool IsInsideOrVirgin() const {
+ return virgin || IsInside();
+ }
+#endif
+
+#ifndef NDEBUG
+ gcc_pure
bool IsInsideOrNull() const {
return thread.IsNull() || thread.IsInside();
}