WPILibC++  2018.4.1-20180921134745-1191-g456d3e1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
priority_condition_variable.h
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
3 /* Open Source Software - may be modified and shared by FRC teams. The code */
4 /* must be accompanied by the FIRST BSD license file in the root directory of */
5 /* the project. */
6 /*----------------------------------------------------------------------------*/
7 
8 #pragma once
9 
10 #ifdef __linux__
11 #include <pthread.h>
12 #endif
13 
14 #include <condition_variable>
15 #include <memory>
16 #include <utility>
17 
18 #include "priority_mutex.h"
19 
20 namespace wpi {
21 
22 #if defined(__linux__) && defined(WPI_HAVE_PRIORITY_MUTEX)
23 
24 #define WPI_HAVE_PRIORITY_CONDITION_VARIABLE 1
25 
26 class priority_condition_variable {
27  typedef std::chrono::system_clock clock;
28 
29  public:
30  typedef pthread_cond_t* native_handle_type;
31 
32  priority_condition_variable() noexcept = default;
33  ~priority_condition_variable() noexcept { pthread_cond_destroy(&m_cond); }
34 
35  priority_condition_variable(const priority_condition_variable&) = delete;
36  priority_condition_variable& operator=(const priority_condition_variable&) =
37  delete;
38 
39  void notify_one() noexcept { pthread_cond_signal(&m_cond); }
40 
41  void notify_all() noexcept { pthread_cond_broadcast(&m_cond); }
42 
43  void wait(std::unique_lock<priority_mutex>& lock) noexcept {
44  int e = pthread_cond_wait(&m_cond, lock.mutex()->native_handle());
45  if (e) std::terminate();
46  }
47 
48  template <typename Predicate>
49  void wait(std::unique_lock<priority_mutex>& lock, Predicate p) {
50  while (!p()) {
51  wait(lock);
52  }
53  }
54 
55  template <typename Duration>
56  std::cv_status wait_until(
57  std::unique_lock<priority_mutex>& lock,
58  const std::chrono::time_point<clock, Duration>& atime) {
59  return wait_until_impl(lock, atime);
60  }
61 
62  template <typename Clock, typename Duration>
63  std::cv_status wait_until(
64  std::unique_lock<priority_mutex>& lock,
65  const std::chrono::time_point<Clock, Duration>& atime) {
66  const typename Clock::time_point c_entry = Clock::now();
67  const clock::time_point s_entry = clock::now();
68  const auto delta = atime - c_entry;
69  const auto s_atime = s_entry + delta;
70 
71  return wait_until_impl(lock, s_atime);
72  }
73 
74  template <typename Clock, typename Duration, typename Predicate>
75  bool wait_until(std::unique_lock<priority_mutex>& lock,
76  const std::chrono::time_point<Clock, Duration>& atime,
77  Predicate p) {
78  while (!p()) {
79  if (wait_until(lock, atime) == std::cv_status::timeout) {
80  return p();
81  }
82  }
83  return true;
84  }
85 
86  template <typename Rep, typename Period>
87  std::cv_status wait_for(std::unique_lock<priority_mutex>& lock,
88  const std::chrono::duration<Rep, Period>& rtime) {
89  return wait_until(lock, clock::now() + rtime);
90  }
91 
92  template <typename Rep, typename Period, typename Predicate>
93  bool wait_for(std::unique_lock<priority_mutex>& lock,
94  const std::chrono::duration<Rep, Period>& rtime, Predicate p) {
95  return wait_until(lock, clock::now() + rtime, std::move(p));
96  }
97 
98  native_handle_type native_handle() { return &m_cond; }
99 
100  private:
101  pthread_cond_t m_cond = PTHREAD_COND_INITIALIZER;
102 
103  template <typename Dur>
104  std::cv_status wait_until_impl(
105  std::unique_lock<priority_mutex>& lock,
106  const std::chrono::time_point<clock, Dur>& atime) {
107  auto s = std::chrono::time_point_cast<std::chrono::seconds>(atime);
108  auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(atime - s);
109 
110  struct timespec ts = {
111  static_cast<std::time_t>(s.time_since_epoch().count()),
112  static_cast<long>(ns.count())}; // NOLINT(runtime/int)
113 
114  pthread_cond_timedwait(&m_cond, lock.mutex()->native_handle(), &ts);
115 
116  return (clock::now() < atime ? std::cv_status::no_timeout
117  : std::cv_status::timeout);
118  }
119 };
120 #endif
121 
122 } // namespace wpi
WPILib C++ utilities (wpiutil) namespace.
Definition: SmallString.h:21