Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
2db6fb8f9d38fec9bfa135db940246f768107cdc
[simgrid.git] / include / simgrid / s4u / conditionVariable.hpp
1 /* Copyright (c) 2006-2016. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #ifndef SIMGRID_S4U_COND_VARIABLE_HPP
7 #define SIMGRID_S4U_COND_VARIABLE_HPP
8
9 #include <chrono>
10 #include <condition_variable>
11 #include <future>
12 #include <mutex>
13 #include <utility> // std::swap
14
15 #include <boost/intrusive_ptr.hpp>
16
17 #include <xbt/base.h>
18
19 #include <simgrid/simix.h>
20 #include <simgrid/s4u/mutex.hpp>
21
22 namespace simgrid {
23 namespace s4u {
24
25 class Mutex;
26
27 /** A condition variable
28  *
29  *  This is based on std::condition_variable and should respect the same
30  *  semantic. But we currently use (only) double for both durations and
31  *  timestamp timeouts.
32  */
33 XBT_PUBLIC_CLASS ConditionVariable {
34 private:
35   friend s_smx_cond;
36   smx_cond_t cond_;
37   ConditionVariable(smx_cond_t cond) : cond_(cond) {}
38 public:
39
40   ConditionVariable(ConditionVariable const&) = delete;
41   ConditionVariable& operator=(ConditionVariable const&) = delete;
42
43   friend XBT_PUBLIC(void) intrusive_ptr_add_ref(ConditionVariable* cond);
44   friend XBT_PUBLIC(void) intrusive_ptr_release(ConditionVariable* cond);
45   using Ptr = boost::intrusive_ptr<ConditionVariable>;
46
47   static Ptr createConditionVariable();
48
49   //  Wait functions:
50
51   void wait(std::unique_lock<Mutex>& lock);
52   std::cv_status wait_until(std::unique_lock<Mutex>& lock, double timeout_time);
53   std::cv_status wait_for(std::unique_lock<Mutex>& lock, double duration);
54
55   /** Wait for a given duraiton
56    *
57    *  This version gives us the ability to do (in C++):
58    *
59    *  <code>
60    *  using namespace std::literals::chrono_literals;
61    *
62    *  cond->wait_for(lock, 1ms);
63    *  cond->wait_for(lock, 1s);
64    *  cond->wait_for(lock, 1min);
65    *  cond->wait_for(lock, 1h);
66    *  </code>
67    */
68   template<class Rep, class Period>
69   std::cv_status wait_for(std::unique_lock<Mutex>& lock, std::chrono::duration<Rep, Period> duration)
70   {
71     typedef std::chrono::duration<double> SecondsDouble;
72     auto seconds = std::chrono::duration_cast<SecondsDouble>(duration);
73     return this->wait_for(lock, duration.count());
74   }
75
76   // Variants which takes a predicate:
77
78   template<class P>
79   void wait(std::unique_lock<Mutex>& lock, P pred)
80   {
81     while (!pred())
82       wait(lock);
83   }
84   template<class P>
85   bool wait_until(std::unique_lock<Mutex>& lock, double timeout_time, P pred)
86   {
87     while (!pred())
88       if (this->wait_until(lock, timeout_time) == std::cv_status::timeout)
89         return pred();
90     return true;
91   }
92   template<class P>
93   bool wait_for(std::unique_lock<Mutex>& lock, double duration, P pred)
94   {
95     return this->wait_until(lock, SIMIX_get_clock() + duration, std::move(pred));
96   }
97   template<class Rep, class Period, class P>
98   bool wait_for(std::unique_lock<Mutex>& lock, std::chrono::duration<Rep, Period> duration, P pred)
99   {
100     typedef std::chrono::duration<double> SecondsDouble;
101     auto seconds = std::chrono::duration_cast<SecondsDouble>(duration);
102     return this->wait_for(lock, seconds.count(), pred);
103   }
104
105   // Notify functions
106
107   void notify_one();
108   void notify_all();
109
110   XBT_ATTRIB_DEPRECATED("Use notify_one() instead")
111   void notify() { notify_one(); }
112 };
113
114 using ConditionVariablePtr = ConditionVariable::Ptr;
115
116 }} // namespace simgrid::s4u
117
118 #endif /* SIMGRID_S4U_COND_VARIABLE_HPP */