Ring Daemon 16.0.0
Loading...
Searching...
No Matches
threadloop.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2004-2025 Savoir-faire Linux Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17#pragma once
18
19#include <atomic>
20#include <thread>
21#include <functional>
22#include <stdexcept>
23#include <condition_variable>
24#include <mutex>
25
26namespace jami {
27
28struct ThreadLoopException : public std::runtime_error
29{
31 : std::runtime_error("ThreadLoopException")
32 {}
33};
34
36{
37public:
39
40 ThreadLoop(const std::function<bool()>& setup,
41 const std::function<void()>& process,
42 const std::function<void()>& cleanup);
43 virtual ~ThreadLoop();
44
45 void start();
46 void exit();
47 virtual void stop();
48 void join();
49 void waitForCompletion(); // thread will stop itself
50
52 bool isStopping() const noexcept { return state_ == ThreadState::STOPPING; }
53 std::thread::id get_id() const noexcept { return threadId_; }
54
55private:
56 ThreadLoop(const ThreadLoop&) = delete;
60
61 // These must be provided by users of ThreadLoop
62 std::function<bool()> setup_;
63 std::function<void()> process_;
64 std::function<void()> cleanup_;
65
66 void mainloop(std::thread::id& tid,
67 const std::function<bool()> setup,
68 const std::function<void()> process,
69 const std::function<void()> cleanup);
70
72 std::thread::id threadId_;
73 std::thread thread_;
74};
75
77{
78public:
79 InterruptedThreadLoop(const std::function<bool()>& setup,
80 const std::function<void()>& process,
81 const std::function<void()>& cleanup)
82 : ThreadLoop::ThreadLoop(setup, process, cleanup)
83 {}
84
85 void stop() override;
86
87 void interrupt() noexcept { cv_.notify_one(); }
88
89 template<typename Rep, typename Period>
90 void wait_for(const std::chrono::duration<Rep, Period>& rel_time)
91 {
92 if (std::this_thread::get_id() != get_id())
93 throw std::runtime_error("Unable to call wait_for outside thread context");
94
95 std::unique_lock lk(mutex_);
96 cv_.wait_for(lk, rel_time, [this]() { return isStopping(); });
97 }
98
99 template<typename Rep, typename Period, typename Pred>
100 bool wait_for(const std::chrono::duration<Rep, Period>& rel_time, Pred&& pred)
101 {
102 if (std::this_thread::get_id() != get_id())
103 throw std::runtime_error("Unable to call wait_for outside thread context");
104
105 std::unique_lock lk(mutex_);
106 return cv_.wait_for(lk, rel_time, [this, pred] { return isStopping() || pred(); });
107 }
108
109 template<typename Pred>
110 void wait(Pred&& pred)
111 {
112 if (std::this_thread::get_id() != get_id())
113 throw std::runtime_error("Unable to call wait outside thread context");
114
115 std::unique_lock lk(mutex_);
116 cv_.wait(lk, [this, p = std::forward<Pred>(pred)] { return isStopping() || p(); });
117 }
118
119private:
120 std::mutex mutex_;
121 std::condition_variable cv_;
122};
123
124} // namespace jami
void wait(Pred &&pred)
Definition threadloop.h:110
bool wait_for(const std::chrono::duration< Rep, Period > &rel_time, Pred &&pred)
Definition threadloop.h:100
void interrupt() noexcept
Definition threadloop.h:87
void wait_for(const std::chrono::duration< Rep, Period > &rel_time)
Definition threadloop.h:90
InterruptedThreadLoop(const std::function< bool()> &setup, const std::function< void()> &process, const std::function< void()> &cleanup)
Definition threadloop.h:79
bool isStopping() const noexcept
Definition threadloop.h:52
bool isRunning() const noexcept
virtual ~ThreadLoop()
std::thread::id get_id() const noexcept
Definition threadloop.h:53
virtual void stop()
void emitSignal(Args... args)
Definition ring_signal.h:64