event/Loop: split InjectBreak() from Break()

This commit is contained in:
Max Kellermann 2022-11-22 22:26:16 +01:00
parent a57cf443ed
commit a3b32819b1
3 changed files with 33 additions and 17 deletions

View File

@ -87,17 +87,6 @@ EventLoop::GetUring() noexcept
#endif #endif
void
EventLoop::Break() noexcept
{
if (quit.exchange(true))
return;
#ifdef HAVE_THREADED_EVENT_LOOP
wake_fd.Write();
#endif
}
bool bool
EventLoop::AddFD(int fd, unsigned events, SocketEvent &event) noexcept EventLoop::AddFD(int fd, unsigned events, SocketEvent &event) noexcept
{ {
@ -286,6 +275,7 @@ EventLoop::Run() noexcept
assert(IsInside()); assert(IsInside());
assert(!quit); assert(!quit);
assert(!quit_injected);
#ifdef HAVE_THREADED_EVENT_LOOP #ifdef HAVE_THREADED_EVENT_LOOP
assert(alive); assert(alive);
assert(busy); assert(busy);
@ -437,6 +427,11 @@ EventLoop::OnSocketReady([[maybe_unused]] unsigned flags) noexcept
wake_fd.Read(); wake_fd.Read();
if (quit_injected) {
Break();
return;
}
const std::scoped_lock<Mutex> lock(mutex); const std::scoped_lock<Mutex> lock(mutex);
HandleInject(); HandleInject();
} }

View File

@ -115,7 +115,7 @@ class EventLoop final
bool alive; bool alive;
#endif #endif
std::atomic_bool quit{false}; bool quit = false;
/** /**
* True when the object has been modified and another check is * True when the object has been modified and another check is
@ -124,6 +124,8 @@ class EventLoop final
bool again; bool again;
#ifdef HAVE_THREADED_EVENT_LOOP #ifdef HAVE_THREADED_EVENT_LOOP
bool quit_injected = false;
/** /**
* True when handling callbacks, false when waiting for I/O or * True when handling callbacks, false when waiting for I/O or
* timeout. * timeout.
@ -187,11 +189,30 @@ public:
#endif #endif
/** /**
* Stop execution of this #EventLoop at the next chance. This * Stop execution of this #EventLoop at the next chance.
* method is thread-safe and non-blocking: after returning, it *
* is not guaranteed that the EventLoop has really stopped. * This method is not thread-safe. For stopping the
* #EventLoop from within another thread, use InjectBreak().
*/ */
void Break() noexcept; void Break() noexcept {
quit = true;
}
#ifdef HAVE_THREADED_EVENT_LOOP
/**
* Like Break(), but thread-safe. It is also non-blocking:
* after returning, it is not guaranteed that the EventLoop
* has really stopped.
*/
void InjectBreak() noexcept {
{
const std::scoped_lock lock{mutex};
quit_injected = true;
}
wake_fd.Write();
}
#endif // HAVE_THREADED_EVENT_LOOP
bool AddFD(int fd, unsigned events, SocketEvent &event) noexcept; bool AddFD(int fd, unsigned events, SocketEvent &event) noexcept;
bool ModifyFD(int fd, unsigned events, SocketEvent &event) noexcept; bool ModifyFD(int fd, unsigned events, SocketEvent &event) noexcept;

View File

@ -45,7 +45,7 @@ EventThread::Stop() noexcept
assert(event_loop.IsAlive()); assert(event_loop.IsAlive());
event_loop.SetAlive(false); event_loop.SetAlive(false);
event_loop.Break(); event_loop.InjectBreak();
thread.Join(); thread.Join();
} }
} }