blob: 05742365890472f8009ac859278ed08713f10094 [file] [log] [blame]
Eric3e7f4b02023-05-23 12:50:25 +02001#pragma once
2/*
3 * (C) 2023 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
4 * All Rights Reserved
5 *
6 * Author: Eric Wild <ewild@sysmocom.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
Eric3e7f4b02023-05-23 12:50:25 +020023#include <atomic>
Eric3e7f4b02023-05-23 12:50:25 +020024#include <future>
25#include <mutex>
26#include <queue>
Eric989fe752023-10-06 16:06:13 +020027#include "threadsched.h"
Eric3e7f4b02023-05-23 12:50:25 +020028
29struct single_thread_pool {
30 std::mutex m;
31 std::condition_variable cv;
32 std::atomic<bool> stop_flag;
33 std::atomic<bool> is_ready;
34 std::deque<std::function<void()>> wq;
Eric989fe752023-10-06 16:06:13 +020035 pthread_t worker_thread;
Eric3e7f4b02023-05-23 12:50:25 +020036
37 template <class F>
38 void add_task(F &&f)
39 {
40 std::unique_lock<std::mutex> l(m);
41 wq.emplace_back(std::forward<F>(f));
42 cv.notify_one();
43 return;
44 }
45
Eric989fe752023-10-06 16:06:13 +020046 single_thread_pool() : stop_flag(false), is_ready(false)
Eric3e7f4b02023-05-23 12:50:25 +020047 {
Eric989fe752023-10-06 16:06:13 +020048 worker_thread = spawn_worker_thread(
49 sched_params::thread_names::SCH_SEARCH,
50 [](void *args) -> void * {
51 using thist = decltype(this);
52 thist t = reinterpret_cast<thist>(args);
53 t->thread_loop();
54 return 0;
55 },
56 this);
Eric3e7f4b02023-05-23 12:50:25 +020057 }
58 ~single_thread_pool()
59 {
60 stop();
61 }
62
Eric3e7f4b02023-05-23 12:50:25 +020063 private:
64 void stop()
65 {
66 {
67 std::unique_lock<std::mutex> l(m);
68 wq.clear();
69 stop_flag = true;
70 cv.notify_one();
71 }
Eric989fe752023-10-06 16:06:13 +020072 pthread_join(worker_thread, nullptr);
Eric3e7f4b02023-05-23 12:50:25 +020073 }
74
75 void thread_loop()
76 {
77 while (true) {
78 is_ready = true;
79 std::function<void()> f;
80 {
81 std::unique_lock<std::mutex> l(m);
82 if (wq.empty()) {
83 cv.wait(l, [&] { return !wq.empty() || stop_flag; });
84 }
85 if (stop_flag)
86 return;
87 is_ready = false;
88 f = std::move(wq.front());
89 wq.pop_front();
90 }
91 f();
92 }
93 }
94};