blob: 4b1eefd51624b019fe2850e3cfdc22084f24ee9e [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>
24#include <vector>
25#include <future>
26#include <mutex>
27#include <queue>
Eric989fe752023-10-06 16:06:13 +020028#include "threadsched.h"
Eric3e7f4b02023-05-23 12:50:25 +020029
30struct single_thread_pool {
31 std::mutex m;
32 std::condition_variable cv;
33 std::atomic<bool> stop_flag;
34 std::atomic<bool> is_ready;
35 std::deque<std::function<void()>> wq;
Eric989fe752023-10-06 16:06:13 +020036 pthread_t worker_thread;
Eric3e7f4b02023-05-23 12:50:25 +020037
38 template <class F>
39 void add_task(F &&f)
40 {
41 std::unique_lock<std::mutex> l(m);
42 wq.emplace_back(std::forward<F>(f));
43 cv.notify_one();
44 return;
45 }
46
Eric989fe752023-10-06 16:06:13 +020047 single_thread_pool() : stop_flag(false), is_ready(false)
Eric3e7f4b02023-05-23 12:50:25 +020048 {
Eric989fe752023-10-06 16:06:13 +020049 worker_thread = spawn_worker_thread(
50 sched_params::thread_names::SCH_SEARCH,
51 [](void *args) -> void * {
52 using thist = decltype(this);
53 thist t = reinterpret_cast<thist>(args);
54 t->thread_loop();
55 return 0;
56 },
57 this);
Eric3e7f4b02023-05-23 12:50:25 +020058 }
59 ~single_thread_pool()
60 {
61 stop();
62 }
63
Eric3e7f4b02023-05-23 12:50:25 +020064 private:
65 void stop()
66 {
67 {
68 std::unique_lock<std::mutex> l(m);
69 wq.clear();
70 stop_flag = true;
71 cv.notify_one();
72 }
Eric989fe752023-10-06 16:06:13 +020073 pthread_join(worker_thread, nullptr);
Eric3e7f4b02023-05-23 12:50:25 +020074 }
75
76 void thread_loop()
77 {
78 while (true) {
79 is_ready = true;
80 std::function<void()> f;
81 {
82 std::unique_lock<std::mutex> l(m);
83 if (wq.empty()) {
84 cv.wait(l, [&] { return !wq.empty() || stop_flag; });
85 }
86 if (stop_flag)
87 return;
88 is_ready = false;
89 f = std::move(wq.front());
90 wq.pop_front();
91 }
92 f();
93 }
94 }
95};