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

View File

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

View File

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

View File

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

View File

@ -98,14 +98,6 @@ class EventLoop final : SocketMonitor
*/
bool busy = true;
#ifndef NDEBUG
/**
* True if Run() was never called. This is used for assert()
* calls.
*/
bool virgin = true;
#endif
PollGroup poll_group;
PollResult poll_result;
@ -115,7 +107,9 @@ class EventLoop final : SocketMonitor
ThreadId thread = ThreadId::Null();
public:
EventLoop();
explicit EventLoop(ThreadId _thread);
EventLoop():EventLoop(ThreadId::GetCurrent()) {}
~EventLoop();
/**
@ -135,7 +129,7 @@ public:
void Break();
bool AddFD(int _fd, unsigned flags, SocketMonitor &m) {
assert(thread.IsNull() || thread.IsInside());
assert(IsInside());
return poll_group.Add(_fd, flags, &m);
}
@ -200,28 +194,8 @@ public:
*/
gcc_pure
bool IsInside() const noexcept {
assert(!thread.IsNull());
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 */

View File

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

View File

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