diff --git a/Userland/Libraries/LibThreading/BackgroundAction.cpp b/Userland/Libraries/LibThreading/BackgroundAction.cpp index 7e95cec977c..5ddcb84ec5a 100644 --- a/Userland/Libraries/LibThreading/BackgroundAction.cpp +++ b/Userland/Libraries/LibThreading/BackgroundAction.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2019-2020, Sergey Bugaev + * Copyright (c) 2021, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ @@ -8,24 +9,33 @@ #include #include #include +#include static Threading::Lockable>>* s_all_actions; static Threading::Thread* s_background_thread; +static int s_notify_pipe_fds[2]; static intptr_t background_thread_func() { while (true) { - Function work_item; + char buffer[1]; + auto nread = read(s_notify_pipe_fds[0], buffer, sizeof(buffer)); + if (nread < 0) { + perror("read"); + _exit(1); + } + + Vector> work_items; { Threading::Locker locker(s_all_actions->lock()); - if (!s_all_actions->resource().is_empty()) - work_item = s_all_actions->resource().dequeue(); + while (!s_all_actions->resource().is_empty()) { + work_items.append(s_all_actions->resource().dequeue()); + } } - if (work_item) + + for (auto& work_item : work_items) work_item(); - else - sleep(1); } VERIFY_NOT_REACHED(); @@ -33,22 +43,32 @@ static intptr_t background_thread_func() static void init() { + if (pipe(s_notify_pipe_fds) < 0) { + perror("pipe"); + _exit(1); + } s_all_actions = new Threading::Lockable>>(); s_background_thread = &Threading::Thread::construct(background_thread_func).leak_ref(); s_background_thread->set_name("Background thread"); s_background_thread->start(); } -Threading::Lockable>>& Threading::BackgroundActionBase::all_actions() -{ - if (s_all_actions == nullptr) - init(); - return *s_all_actions; -} - Threading::Thread& Threading::BackgroundActionBase::background_thread() { if (s_background_thread == nullptr) init(); return *s_background_thread; } + +void Threading::BackgroundActionBase::enqueue_work(Function work) +{ + if (s_all_actions == nullptr) + init(); + Locker locker(s_all_actions->lock()); + s_all_actions->resource().enqueue(move(work)); + char ch = 'x'; + if (write(s_notify_pipe_fds[1], &ch, sizeof(ch)) < 0) { + perror("write"); + _exit(1); + } +} diff --git a/Userland/Libraries/LibThreading/BackgroundAction.h b/Userland/Libraries/LibThreading/BackgroundAction.h index 2ac77d57589..d169ae4aa31 100644 --- a/Userland/Libraries/LibThreading/BackgroundAction.h +++ b/Userland/Libraries/LibThreading/BackgroundAction.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2019-2020, Sergey Bugaev + * Copyright (c) 2021, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ @@ -13,7 +14,6 @@ #include #include #include -#include #include namespace Threading { @@ -28,7 +28,7 @@ class BackgroundActionBase { private: BackgroundActionBase() { } - static Lockable>>& all_actions(); + static void enqueue_work(Function); static Thread& background_thread(); }; @@ -63,9 +63,7 @@ private: , m_action(move(action)) , m_on_complete(move(on_complete)) { - Locker locker(all_actions().lock()); - - all_actions().resource().enqueue([this] { + enqueue_work([this] { m_result = m_action(*this); if (m_on_complete) { Core::EventLoop::current().post_event(*this, make([this](auto&) {