Serenity Operating System
1/*
2 * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
3 * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8#include <AK/Queue.h>
9#include <LibThreading/BackgroundAction.h>
10#include <LibThreading/Mutex.h>
11#include <LibThreading/Thread.h>
12#include <unistd.h>
13
14static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
15static pthread_cond_t s_condition = PTHREAD_COND_INITIALIZER;
16static Queue<Function<void()>>* s_all_actions;
17static Threading::Thread* s_background_thread;
18
19static intptr_t background_thread_func()
20{
21 Vector<Function<void()>> actions;
22 while (true) {
23
24 pthread_mutex_lock(&s_mutex);
25
26 while (s_all_actions->is_empty())
27 pthread_cond_wait(&s_condition, &s_mutex);
28
29 while (!s_all_actions->is_empty())
30 actions.append(s_all_actions->dequeue());
31
32 pthread_mutex_unlock(&s_mutex);
33
34 for (auto& action : actions)
35 action();
36
37 actions.clear();
38 }
39}
40
41static void init()
42{
43 s_all_actions = new Queue<Function<void()>>;
44 s_background_thread = &Threading::Thread::construct(background_thread_func, "Background Thread"sv).leak_ref();
45 s_background_thread->start();
46}
47
48Threading::Thread& Threading::BackgroundActionBase::background_thread()
49{
50 if (s_background_thread == nullptr)
51 init();
52 return *s_background_thread;
53}
54
55void Threading::BackgroundActionBase::enqueue_work(Function<void()> work)
56{
57 if (s_all_actions == nullptr)
58 init();
59
60 pthread_mutex_lock(&s_mutex);
61 s_all_actions->enqueue(move(work));
62 pthread_cond_broadcast(&s_condition);
63 pthread_mutex_unlock(&s_mutex);
64}