event/Loop: set thread to current thread by default

Allows eliminating lots of complexity and workarounds for bogus
assertion failures.
This commit is contained in:
Max Kellermann 2017-08-18 17:57:59 +02:00
parent 94525d3952
commit 5ac72211cd
7 changed files with 24 additions and 59 deletions

View File

@ -62,7 +62,7 @@ UpdateService::~UpdateService()
void void
UpdateService::CancelAllAsync() UpdateService::CancelAllAsync()
{ {
assert(GetEventLoop().IsInsideOrNull()); assert(GetEventLoop().IsInside());
queue.Clear(); queue.Clear();
@ -144,7 +144,7 @@ UpdateService::Task()
void void
UpdateService::StartThread(UpdateQueueItem &&i) UpdateService::StartThread(UpdateQueueItem &&i)
{ {
assert(GetEventLoop().IsInsideOrNull()); assert(GetEventLoop().IsInside());
assert(walk == nullptr); assert(walk == nullptr);
modified = false; modified = false;
@ -170,7 +170,7 @@ UpdateService::GenerateId()
unsigned unsigned
UpdateService::Enqueue(const char *path, bool discard) UpdateService::Enqueue(const char *path, bool discard)
{ {
assert(GetEventLoop().IsInsideOrNull()); assert(GetEventLoop().IsInside());
/* determine which (mounted) database will be updated and what /* determine which (mounted) database will be updated and what
storage will be scanned */ storage will be scanned */

View File

@ -79,7 +79,7 @@ private:
void void
BlockingCall(EventLoop &loop, std::function<void()> &&f) BlockingCall(EventLoop &loop, std::function<void()> &&f)
{ {
if (loop.IsInsideOrNull()) { if (loop.IsInside()) {
/* we're already inside the loop - we can simply call /* we're already inside the loop - we can simply call
the function */ the function */
f(); f();

View File

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

View File

@ -27,8 +27,8 @@
#include <algorithm> #include <algorithm>
EventLoop::EventLoop() EventLoop::EventLoop(ThreadId _thread)
:SocketMonitor(*this) :SocketMonitor(*this), thread(_thread)
{ {
SocketMonitor::Open(SocketDescriptor(wake_fd.Get())); SocketMonitor::Open(SocketDescriptor(wake_fd.Get()));
} }
@ -52,7 +52,7 @@ EventLoop::Break()
bool bool
EventLoop::Abandon(int _fd, SocketMonitor &m) EventLoop::Abandon(int _fd, SocketMonitor &m)
{ {
assert(IsInsideOrVirgin()); assert(IsInside());
poll_result.Clear(&m); poll_result.Clear(&m);
return poll_group.Abandon(_fd); return poll_group.Abandon(_fd);
@ -61,7 +61,7 @@ EventLoop::Abandon(int _fd, SocketMonitor &m)
bool bool
EventLoop::RemoveFD(int _fd, SocketMonitor &m) EventLoop::RemoveFD(int _fd, SocketMonitor &m)
{ {
assert(IsInsideOrNull()); assert(IsInside());
poll_result.Clear(&m); poll_result.Clear(&m);
return poll_group.Remove(_fd); return poll_group.Remove(_fd);
@ -70,7 +70,7 @@ EventLoop::RemoveFD(int _fd, SocketMonitor &m)
void void
EventLoop::AddIdle(IdleMonitor &i) EventLoop::AddIdle(IdleMonitor &i)
{ {
assert(IsInsideOrVirgin()); assert(IsInside());
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);
@ -80,7 +80,7 @@ EventLoop::AddIdle(IdleMonitor &i)
void void
EventLoop::RemoveIdle(IdleMonitor &i) EventLoop::RemoveIdle(IdleMonitor &i)
{ {
assert(IsInsideOrVirgin()); assert(IsInside());
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());
@ -91,9 +91,7 @@ EventLoop::RemoveIdle(IdleMonitor &i)
void void
EventLoop::AddTimer(TimeoutMonitor &t, std::chrono::steady_clock::duration d) EventLoop::AddTimer(TimeoutMonitor &t, std::chrono::steady_clock::duration d)
{ {
/* can't use IsInsideOrVirgin() here because libavahi-client assert(IsInside());
modifies the timeout during avahi_client_free() */
assert(IsInsideOrNull());
timers.insert(TimerRecord(t, now + d)); timers.insert(TimerRecord(t, now + d));
again = true; again = true;
@ -102,7 +100,7 @@ EventLoop::AddTimer(TimeoutMonitor &t, std::chrono::steady_clock::duration d)
void void
EventLoop::CancelTimer(TimeoutMonitor &t) EventLoop::CancelTimer(TimeoutMonitor &t)
{ {
assert(IsInsideOrNull()); assert(IsInside());
for (auto i = timers.begin(), end = timers.end(); i != end; ++i) { for (auto i = timers.begin(), end = timers.end(); i != end; ++i) {
if (&i->timer == &t) { if (&i->timer == &t) {
@ -128,15 +126,10 @@ ExportTimeoutMS(std::chrono::steady_clock::duration timeout)
void void
EventLoop::Run() EventLoop::Run()
{ {
assert(thread.IsNull()); if (thread.IsNull())
assert(virgin);
#ifndef NDEBUG
virgin = false;
#endif
thread = ThreadId::GetCurrent(); thread = ThreadId::GetCurrent();
assert(IsInside());
assert(!quit); assert(!quit);
assert(busy); assert(busy);
@ -226,8 +219,6 @@ EventLoop::Run()
assert(busy); assert(busy);
assert(thread.IsInside()); assert(thread.IsInside());
#endif #endif
thread = ThreadId::Null();
} }
void void

View File

@ -98,14 +98,6 @@ class EventLoop final : SocketMonitor
*/ */
bool busy = true; bool busy = true;
#ifndef NDEBUG
/**
* True if Run() was never called. This is used for assert()
* calls.
*/
bool virgin = true;
#endif
PollGroup poll_group; PollGroup poll_group;
PollResult poll_result; PollResult poll_result;
@ -115,7 +107,9 @@ class EventLoop final : SocketMonitor
ThreadId thread = ThreadId::Null(); ThreadId thread = ThreadId::Null();
public: public:
EventLoop(); explicit EventLoop(ThreadId _thread);
EventLoop():EventLoop(ThreadId::GetCurrent()) {}
~EventLoop(); ~EventLoop();
/** /**
@ -135,7 +129,7 @@ public:
void Break(); void Break();
bool AddFD(int _fd, unsigned flags, SocketMonitor &m) { bool AddFD(int _fd, unsigned flags, SocketMonitor &m) {
assert(thread.IsNull() || thread.IsInside()); assert(IsInside());
return poll_group.Add(_fd, flags, &m); return poll_group.Add(_fd, flags, &m);
} }
@ -200,28 +194,8 @@ public:
*/ */
gcc_pure gcc_pure
bool IsInside() const noexcept { bool IsInside() const noexcept {
assert(!thread.IsNull());
return thread.IsInside(); return thread.IsInside();
} }
#ifndef NDEBUG
gcc_pure
bool IsInsideOrVirgin() const noexcept {
return virgin || IsInside();
}
#endif
/**
* Like IsInside(), but also returns true if the thread has
* already ended (or was not started yet). This is useful for
* code which may run during startup or shutdown, when events
* are not yet/anymore handled.
*/
gcc_pure
bool IsInsideOrNull() const noexcept {
return thread.IsNull() || thread.IsInside();
}
}; };
#endif /* MAIN_NOTIFY_H */ #endif /* MAIN_NOTIFY_H */

View File

@ -34,7 +34,7 @@ MultiSocketMonitor::MultiSocketMonitor(EventLoop &_loop)
void void
MultiSocketMonitor::Reset() MultiSocketMonitor::Reset()
{ {
assert(GetEventLoop().IsInsideOrNull()); assert(GetEventLoop().IsInside());
fds.clear(); fds.clear();
IdleMonitor::Cancel(); IdleMonitor::Cancel();
@ -45,7 +45,7 @@ MultiSocketMonitor::Reset()
void void
MultiSocketMonitor::ClearSocketList() MultiSocketMonitor::ClearSocketList()
{ {
assert(GetEventLoop().IsInsideOrNull()); assert(GetEventLoop().IsInside());
fds.clear(); fds.clear();
} }

View File

@ -34,7 +34,7 @@ class EventThread final {
public: public:
EventThread() EventThread()
:thread(BIND_THIS_METHOD(Run)) {} :event_loop(ThreadId::Null()), thread(BIND_THIS_METHOD(Run)) {}
~EventThread() { ~EventThread() {
Stop(); Stop();