mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 04:37:40 +00:00
CEventLoop: Add wake(), a mechanism for waking up when blocked in select().
This patch generalizes the concept used in Piano to wake up the event loop so it can react to something happening on a secondary thread. Basically, there's a pipe who is always part of the file descriptor set we pass to select(), and calling wake() simply writes a little to that pipe.
This commit is contained in:
parent
f1d6a37d5d
commit
17ee548bcd
2 changed files with 23 additions and 0 deletions
|
@ -23,6 +23,7 @@ static Vector<CEventLoop*>* s_event_loop_stack;
|
||||||
HashMap<int, OwnPtr<CEventLoop::EventLoopTimer>>* CEventLoop::s_timers;
|
HashMap<int, OwnPtr<CEventLoop::EventLoopTimer>>* CEventLoop::s_timers;
|
||||||
HashTable<CNotifier*>* CEventLoop::s_notifiers;
|
HashTable<CNotifier*>* CEventLoop::s_notifiers;
|
||||||
int CEventLoop::s_next_timer_id = 1;
|
int CEventLoop::s_next_timer_id = 1;
|
||||||
|
int CEventLoop::s_wake_pipe_fds[2];
|
||||||
|
|
||||||
CEventLoop::CEventLoop()
|
CEventLoop::CEventLoop()
|
||||||
{
|
{
|
||||||
|
@ -34,6 +35,8 @@ CEventLoop::CEventLoop()
|
||||||
|
|
||||||
if (!s_main_event_loop) {
|
if (!s_main_event_loop) {
|
||||||
s_main_event_loop = this;
|
s_main_event_loop = this;
|
||||||
|
int rc = pipe(s_wake_pipe_fds);
|
||||||
|
ASSERT(rc == 0);
|
||||||
s_event_loop_stack->append(this);
|
s_event_loop_stack->append(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,6 +172,7 @@ void CEventLoop::wait_for_event(WaitMode mode)
|
||||||
|
|
||||||
int max_fd_added = -1;
|
int max_fd_added = -1;
|
||||||
add_file_descriptors_for_select(rfds, max_fd_added);
|
add_file_descriptors_for_select(rfds, max_fd_added);
|
||||||
|
add_fd_to_set(s_wake_pipe_fds[1], rfds);
|
||||||
max_fd = max(max_fd, max_fd_added);
|
max_fd = max(max_fd, max_fd_added);
|
||||||
for (auto& notifier : *s_notifiers) {
|
for (auto& notifier : *s_notifiers) {
|
||||||
if (notifier->event_mask() & CNotifier::Read)
|
if (notifier->event_mask() & CNotifier::Read)
|
||||||
|
@ -205,6 +209,11 @@ void CEventLoop::wait_for_event(WaitMode mode)
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FD_ISSET(s_wake_pipe_fds[1], &rfds)) {
|
||||||
|
char buffer[32];
|
||||||
|
read(s_wake_pipe_fds[1], buffer, sizeof(buffer));
|
||||||
|
}
|
||||||
|
|
||||||
if (!s_timers->is_empty()) {
|
if (!s_timers->is_empty()) {
|
||||||
gettimeofday(&now, nullptr);
|
gettimeofday(&now, nullptr);
|
||||||
}
|
}
|
||||||
|
@ -301,3 +310,13 @@ void CEventLoop::unregister_notifier(Badge<CNotifier>, CNotifier& notifier)
|
||||||
{
|
{
|
||||||
s_notifiers->remove(¬ifier);
|
s_notifiers->remove(¬ifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CEventLoop::wake()
|
||||||
|
{
|
||||||
|
char ch = '!';
|
||||||
|
int nwritten = write(s_wake_pipe_fds[0], &ch, 1);
|
||||||
|
if (nwritten < 0) {
|
||||||
|
perror("CEventLoop::wake: write");
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -50,6 +50,8 @@ public:
|
||||||
m_queued_events.append(move(other.m_queued_events));
|
m_queued_events.append(move(other.m_queued_events));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wake();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void add_file_descriptors_for_select(fd_set&, int& max_fd) { UNUSED_PARAM(max_fd); }
|
virtual void add_file_descriptors_for_select(fd_set&, int& max_fd) { UNUSED_PARAM(max_fd); }
|
||||||
virtual void process_file_descriptors_after_select(const fd_set&) {}
|
virtual void process_file_descriptors_after_select(const fd_set&) {}
|
||||||
|
@ -69,6 +71,8 @@ private:
|
||||||
bool m_exit_requested { false };
|
bool m_exit_requested { false };
|
||||||
int m_exit_code { 0 };
|
int m_exit_code { 0 };
|
||||||
|
|
||||||
|
static int s_wake_pipe_fds[2];
|
||||||
|
|
||||||
CLock m_lock;
|
CLock m_lock;
|
||||||
|
|
||||||
struct EventLoopTimer {
|
struct EventLoopTimer {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue