]> git.sesse.net Git - nageru/blob - nageru/quittable_sleeper.h
Fix a comment typo.
[nageru] / nageru / quittable_sleeper.h
1 #ifndef _QUITTABLE_SLEEPER
2 #define _QUITTABLE_SLEEPER 1
3
4 // A class that assists with fast shutdown of threads. You can set
5 // a flag that says the thread should quit, which it can then check
6 // in a loop -- and if the thread sleeps (using the sleep_* functions
7 // on the class), that sleep will immediately be aborted.
8 //
9 // All member functions on this class are thread-safe.
10
11 #include <chrono>
12 #include <condition_variable>
13 #include <mutex>
14
15 class QuittableSleeper {
16 public:
17         void quit()
18         {
19                 std::lock_guard<std::mutex> l(mu);
20                 should_quit_var = true;
21                 quit_cond.notify_all();
22         }
23
24         void unquit()
25         {
26                 std::lock_guard<std::mutex> l(mu);
27                 should_quit_var = false;
28         }
29
30         void wakeup()
31         {
32                 std::lock_guard<std::mutex> l(mu);
33                 should_wakeup_var = true;
34                 quit_cond.notify_all();
35         }
36
37         bool should_quit() const
38         {
39                 std::lock_guard<std::mutex> l(mu);
40                 return should_quit_var;
41         }
42
43         // Returns false if woken up early.
44         template<class Rep, class Period>
45         bool sleep_for(const std::chrono::duration<Rep, Period> &duration)
46         {
47                 std::chrono::steady_clock::time_point t =
48                         std::chrono::steady_clock::now() +
49                         std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration);
50                 return sleep_until(t);
51         }
52
53         // Returns false if woken up early.
54         template<class Clock, class Duration>
55         bool sleep_until(const std::chrono::time_point<Clock, Duration> &t)
56         {
57                 std::unique_lock<std::mutex> lock(mu);
58                 quit_cond.wait_until(lock, t, [this]{
59                         return should_quit_var || should_wakeup_var;
60                 });
61                 if (should_wakeup_var) {
62                         should_wakeup_var = false;
63                         return false;
64                 }
65                 return !should_quit_var;
66         }
67
68 private:
69         mutable std::mutex mu;
70         bool should_quit_var = false, should_wakeup_var = false;
71         std::condition_variable quit_cond;
72 };
73
74 #endif  // !defined(_QUITTABLE_SLEEPER)