NVML C++ bindings  0.1 experimental
This is the C++ bindings documentation for NVML's libpmemobj.
condition_variable.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2016, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  *
16  * * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
38 #ifndef PMEMOBJ_CONDVARIABLE_HPP
39 #define PMEMOBJ_CONDVARIABLE_HPP
40 
41 #include <chrono>
42 #include <condition_variable>
43 
45 #include "libpmemobj++/mutex.hpp"
46 #include "libpmemobj/thread.h"
47 
48 namespace nvml
49 {
50 
51 namespace obj
52 {
53 
63  typedef std::chrono::system_clock clock_type;
64 
65 public:
67  typedef PMEMcond *native_handle_type;
68 
72  condition_variable() noexcept = default;
73 
77  ~condition_variable() = default;
78 
87  void
89  {
90  PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
91  if (int ret = pmemobj_cond_signal(pop, &this->pcond))
92  throw lock_error(ret, std::system_category(),
93  "Error notifying one on "
94  "a condition variable.");
95  }
96 
102  void
104  {
105  PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
106  if (int ret = pmemobj_cond_broadcast(pop, &this->pcond))
107  throw lock_error(ret, std::system_category(),
108  "Error notifying all on "
109  "a condition variable.");
110  }
111 
127  void
128  wait(mutex &lock)
129  {
130  this->wait_impl(lock);
131  }
132 
150  template <typename Lock>
151  void
152  wait(Lock &lock)
153  {
154  this->wait_impl(*lock.mutex());
155  }
156 
176  template <typename Predicate>
177  void
178  wait(mutex &lock, Predicate pred)
179  {
180  this->wait_impl(lock, std::move(pred));
181  }
182 
204  template <typename Lock, typename Predicate>
205  void
206  wait(Lock &lock, Predicate pred)
207  {
208  this->wait_impl(*lock.mutex(), std::move(pred));
209  }
210 
232  template <typename Clock, typename Duration>
233  std::cv_status
235  const std::chrono::time_point<Clock, Duration> &timeout)
236  {
237  return this->wait_until_impl(lock, timeout);
238  }
239 
263  template <typename Lock, typename Clock, typename Duration>
264  std::cv_status
265  wait_until(Lock &lock,
266  const std::chrono::time_point<Clock, Duration> &timeout)
267  {
268  return this->wait_until_impl(*lock.mutex(), timeout);
269  }
270 
293  template <typename Clock, typename Duration, typename Predicate>
294  bool
296  const std::chrono::time_point<Clock, Duration> &timeout,
297  Predicate pred)
298  {
299  return this->wait_until_impl(lock, timeout, std::move(pred));
300  }
301 
326  template <typename Lock, typename Clock, typename Duration,
327  typename Predicate>
328  bool
329  wait_until(Lock &lock,
330  const std::chrono::time_point<Clock, Duration> &timeout,
331  Predicate pred)
332  {
333  return this->wait_until_impl(*lock.mutex(), timeout,
334  std::move(pred));
335  }
336 
360  template <typename Lock, typename Rep, typename Period>
361  std::cv_status
362  wait_for(Lock &lock, const std::chrono::duration<Rep, Period> &rel_time)
363  {
364  return this->wait_until_impl(*lock.mutex(),
365  clock_type::now() + rel_time);
366  }
367 
392  template <typename Lock, typename Rep, typename Period,
393  typename Predicate>
394  bool
395  wait_for(Lock &lock, const std::chrono::duration<Rep, Period> &rel_time,
396  Predicate pred)
397  {
398  return this->wait_until_impl(*lock.mutex(),
399  clock_type::now() + rel_time,
400  std::move(pred));
401  }
402 
424  template <typename Rep, typename Period>
425  std::cv_status
427  const std::chrono::duration<Rep, Period> &rel_time)
428  {
429  return this->wait_until_impl(lock,
430  clock_type::now() + rel_time);
431  }
432 
455  template <typename Rep, typename Period, typename Predicate>
456  bool
458  const std::chrono::duration<Rep, Period> &rel_time,
459  Predicate pred)
460  {
461  return this->wait_until_impl(lock, clock_type::now() + rel_time,
462  std::move(pred));
463  }
464 
470  native_handle_type
471  native_handle() noexcept
472  {
473  return &this->pcond;
474  }
475 
480 
484  condition_variable(const condition_variable &) = delete;
485 
486 private:
490  void
492  {
493  PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
494  if (int ret = pmemobj_cond_wait(pop, &this->pcond,
495  lock.native_handle()))
496  throw lock_error(ret, std::system_category(),
497  "Error waiting on a condition "
498  "variable.");
499  }
500 
504  template <typename Predicate>
505  void
506  wait_impl(mutex &lock, Predicate pred)
507  {
508  while (!pred())
509  this->wait(lock);
510  }
511 
515  template <typename Clock, typename Duration>
516  std::cv_status
518  mutex &lock,
519  const std::chrono::time_point<Clock, Duration> &abs_timeout)
520  {
521  PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
522 
523  /* convert to my clock */
524  const typename Clock::time_point their_now = Clock::now();
525  const clock_type::time_point my_now = clock_type::now();
526  const auto delta = abs_timeout - their_now;
527  const auto my_rel = my_now + delta;
528 
529  struct timespec ts = detail::timepoint_to_timespec(my_rel);
530 
531  auto ret = pmemobj_cond_timedwait(pop, &this->pcond,
532  lock.native_handle(), &ts);
533 
534  if (ret == 0)
535  return std::cv_status::no_timeout;
536  else if (ret == ETIMEDOUT)
537  return std::cv_status::timeout;
538  else
539  throw lock_error(ret, std::system_category(),
540  "Error waiting on a condition "
541  "variable.");
542  }
543 
547  template <typename Clock, typename Duration, typename Predicate>
548  bool
550  mutex &lock,
551  const std::chrono::time_point<Clock, Duration> &abs_timeout,
552  Predicate pred)
553  {
554  while (!pred())
555  if (this->wait_until_impl(lock, abs_timeout) ==
556  std::cv_status::timeout)
557  return pred();
558  return true;
559  }
560 
562  PMEMcond pcond;
563 };
564 
565 } /* namespace obj */
566 
567 } /* namespace nvml */
568 
569 #endif /* PMEMOBJ_CONDVARIABLE_HPP */
bool wait_until_impl(mutex &lock, const std::chrono::time_point< Clock, Duration > &abs_timeout, Predicate pred)
Internal implementation of the wait_until call.
Definition: condition_variable.hpp:549
native_handle_type native_handle() noexcept
Access a native handle to this condition variable.
Definition: condition_variable.hpp:471
Persistent memory resident condition variable.
Definition: condition_variable.hpp:62
Pmem-resident mutex.
native_handle_type native_handle() noexcept
Access a native handle to this condition variable.
Definition: mutex.hpp:150
std::cv_status wait_for(Lock &lock, const std::chrono::duration< Rep, Period > &rel_time)
Makes the current thread block until the condition variable is notified, the specified amount of time...
Definition: condition_variable.hpp:362
std::cv_status wait_until_impl(mutex &lock, const std::chrono::time_point< Clock, Duration > &abs_timeout)
Internal implementation of the wait_until call.
Definition: condition_variable.hpp:517
Persistent memory resident mutex implementation.
Definition: mutex.hpp:60
condition_variable() noexcept=default
Defaulted constructor.
void wait_impl(mutex &lock, Predicate pred)
Internal implementation of the wait call.
Definition: condition_variable.hpp:506
void wait(mutex &lock, Predicate pred)
Makes the current thread block until the condition variable is notified.
Definition: condition_variable.hpp:178
bool wait_for(Lock &lock, const std::chrono::duration< Rep, Period > &rel_time, Predicate pred)
Makes the current thread block until the condition variable is notified or the specified amount of ti...
Definition: condition_variable.hpp:395
bool wait_for(mutex &lock, const std::chrono::duration< Rep, Period > &rel_time, Predicate pred)
Makes the current thread block until the condition variable is notified or the specified amount of ti...
Definition: condition_variable.hpp:457
void wait(Lock &lock, Predicate pred)
Makes the current thread block until the condition variable is notified.
Definition: condition_variable.hpp:206
std::cv_status wait_until(mutex &lock, const std::chrono::time_point< Clock, Duration > &timeout)
Makes the current thread block until the condition variable is notified, a specific time is reached o...
Definition: condition_variable.hpp:234
void notify_all()
Notify and unblock all threads waiting on *this condition.
Definition: condition_variable.hpp:103
Commonly used conversions.
bool wait_until(mutex &lock, const std::chrono::time_point< Clock, Duration > &timeout, Predicate pred)
Makes the current thread block until the condition variable is notified or a specific time is reached...
Definition: condition_variable.hpp:295
void wait(Lock &lock)
Makes the current thread block until the condition variable is notified or it is woken up by some oth...
Definition: condition_variable.hpp:152
PMEMcond pcond
A POSIX style PMEM-resident condition variable.
Definition: condition_variable.hpp:562
Custom lock error class.
Definition: pexceptions.hpp:74
condition_variable & operator=(const condition_variable &)=delete
Deleted assignment operator.
bool wait_until(Lock &lock, const std::chrono::time_point< Clock, Duration > &timeout, Predicate pred)
Makes the current thread block until the condition variable is notified or a specific time is reached...
Definition: condition_variable.hpp:329
Definition: condition_variable.hpp:48
std::cv_status wait_until(Lock &lock, const std::chrono::time_point< Clock, Duration > &timeout)
Makes the current thread block until the condition variable is notified, a specific time is reached o...
Definition: condition_variable.hpp:265
void notify_one()
Notify and unblock one thread waiting on *this condition.
Definition: condition_variable.hpp:88
std::cv_status wait_for(mutex &lock, const std::chrono::duration< Rep, Period > &rel_time)
Makes the current thread block until the condition variable is notified, the specified amount of time...
Definition: condition_variable.hpp:426
void wait(mutex &lock)
Makes the current thread block until the condition variable is notified or it is woken up by some oth...
Definition: condition_variable.hpp:128
void wait_impl(mutex &lock)
Internal implementation of the wait call.
Definition: condition_variable.hpp:491
PMEMcond * native_handle_type
The handle typedef to the underlying basic type.
Definition: condition_variable.hpp:67