CUBRID Engine  latest
thread_waiter.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * thread_waiter - interface of suspending/waking threads
21  */
22 
23 #ifndef _THREAD_WAITER_HPP_
24 #define _THREAD_WAITER_HPP_
25 
26 #include "perf_def.hpp"
27 
28 #include <atomic>
29 #include <chrono>
30 #include <condition_variable>
31 #include <mutex>
32 #include <thread>
33 
34 #include <cassert>
35 #include <cinttypes>
36 
37 namespace cubthread
38 {
39  // cubthread::waiter
40  //
41  // description:
42  // usable to suspend thread and wait for a time or for wakeup request
43  //
44  // how to use:
45  //
46  // // Thread 1
47  // // this thread wants to wait indefinitely
48  // waiter_shared_variable->wait_inf ();
49  //
50  // // Thread 2
51  // // wake Thread 1
52  // waiter_shared_variable->wakeup ();
53  //
54  // // similarly, first thread can wait with timeout using wait_for or wait_until functions
55  //
56  class waiter
57  {
58  public:
59  waiter ();
60  ~waiter();
61 
62  void wakeup (void); // wakeup waiter thread
63 
64  void wait_inf (void); // wait until wakeup
65  bool wait_for (const std::chrono::system_clock::duration &delta); // wait for period of time or until wakeup
66  // returns true if woke up before timeout
67  bool wait_until (const std::chrono::system_clock::time_point &timeout_time); // wait until time or until wakeup
68  // returns true if woke up before timeout
69 
70  // statistics
71  static std::size_t get_stats_value_count (void);
72  static const char *get_stat_name (std::size_t stat_index);
73  void get_stats (cubperf::stat_value *stats_out);
74 
75  bool is_running (); // true, if running
76 
77  private:
78 
79  enum status // waiter status
80  {
84  };
85 
86  inline bool check_wake (void); // check wake condition; used to avoid spurious wakeups
87  void goto_sleep (void);
88  inline void awake (void);
89  void run (void);
90 
91  std::mutex m_mutex; // mutex used to synchronize waiter states
92  std::condition_variable m_condvar; // condition variable used to wait/wakeup
93  status m_status; // current status
94 
95  // stats
98  bool m_was_awaken; // used for statistics
99  };
100 
101  // cubthread::wait_duration
102  //
103  // description:
104  template <class D>
106  {
109 
111  : m_duration (0)
112  , m_infinite (true)
113  {
114  //
115  }
116 
118  : m_duration (duration)
119  , m_infinite (false)
120  {
121  //
122  }
123 
124  const wait_duration &operator= (const D &duration)
125  {
126  m_duration = duration;
127  m_infinite = false;
128  }
129 
130  void set_infinite_wait ();
131  void set_duration (const D &duration);
132  };
134 
135  template <typename D>
136  void condvar_wait (std::condition_variable &condvar, std::unique_lock<std::mutex> &lock,
137  const wait_duration<D> &duration);
138  template <typename D, typename P>
139  bool condvar_wait (std::condition_variable &condvar, std::unique_lock<std::mutex> &lock,
140  const wait_duration<D> &duration, P pred);
141 
143  // template/inline implementation
145 
146  template <typename D>
147  void
148  condvar_wait (std::condition_variable &condvar, std::unique_lock<std::mutex> &lock,
149  const wait_duration<D> &duration)
150  {
151  if (duration.m_infinite)
152  {
153  condvar.wait (lock);
154  }
155  else
156  {
157  (void) condvar.wait_for (lock, duration.m_duration);
158  }
159  }
160 
161  template <typename D, typename P>
162  bool
163  condvar_wait (std::condition_variable &condvar, std::unique_lock<std::mutex> &lock,
164  const wait_duration<D> &duration, P pred)
165  {
166  if (duration.m_infinite)
167  {
168  condvar.wait (lock, pred);
169  return true;
170  }
171  else
172  {
173  return condvar.wait_for (lock, duration.m_duration, pred);
174  }
175  }
176 
177  template <class D>
178  void
180  {
181  m_infinite = true;
182  }
183 
184  template <class D>
185  void
187  {
188  m_duration = duration;
189  m_infinite = false;
190  }
191 
192 } // namespace cubthread
193 
194 #endif // _THREAD_WAITER_HPP_
cubperf::statset & m_stats
static API_MUTEX mutex
Definition: api_util.c:72
generic_value< false > stat_value
Definition: perf_def.hpp:46
wait_duration(const D &duration)
cubperf::atomic_stat_counter m_wakeup_calls
clock::time_point time_point
Definition: perf_def.hpp:40
void condvar_wait(std::condition_variable &condvar, std::unique_lock< std::mutex > &lock, const wait_duration< D > &duration)
void get_stats(cubperf::stat_value *stats_out)
clock::duration duration
Definition: perf_def.hpp:41
void set_duration(const D &duration)
static std::size_t get_stats_value_count(void)
bool wait_for(const std::chrono::system_clock::duration &delta)
static const char * get_stat_name(std::size_t stat_index)
std::condition_variable m_condvar
bool wait_until(const std::chrono::system_clock::time_point &timeout_time)