1 // Copyright (c) 2023 The Limenka developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 5 #ifndef LIMENKA_UTIL_SIGNALINTERRUPT_H
6 #define LIMENKA_UTIL_SIGNALINTERRUPT_H
7 8 #ifdef WIN32
9 #include <condition_variable>
10 #include <mutex>
11 #else
12 #include <util/tokenpipe.h>
13 #endif
14 15 #include <atomic>
16 #include <cstdlib>
17 18 namespace util {
19 /**
20 * Helper class that manages an interrupt flag, and allows a thread or
21 * signal to interrupt another thread.
22 *
23 * This class is safe to be used in a signal handler. If sending an interrupt
24 * from a signal handler is not necessary, the more lightweight \ref
25 * CThreadInterrupt class can be used instead.
26 */
27 28 class SignalInterrupt
29 {
30 public:
31 SignalInterrupt();
32 explicit operator bool() const;
33 [[nodiscard]] bool operator()();
34 [[nodiscard]] bool reset();
35 [[nodiscard]] bool wait();
36 37 private:
38 std::atomic<bool> m_flag;
39 40 #ifndef WIN32
41 // On UNIX-like operating systems use the self-pipe trick.
42 TokenPipeEnd m_pipe_r;
43 TokenPipeEnd m_pipe_w;
44 #else
45 // On windows use a condition variable, since we don't have any signals there
46 std::mutex m_mutex;
47 std::condition_variable m_cv;
48 #endif
49 };
50 } // namespace util
51 52 #endif // LIMENKA_UTIL_SIGNALINTERRUPT_H
53