PMDK C++ bindings  1.13.0-git23.gf49772ac
This is the C++ bindings documentation for PMDK's libpmemobj.
condition_variable.hpp
Go to the documentation of this file.
1 // SPDX-License-Identifier: BSD-3-Clause
2 /* Copyright 2016-2020, Intel Corporation */
3 
9 #ifndef LIBPMEMOBJ_CPP_CONDVARIABLE_HPP
10 #define LIBPMEMOBJ_CPP_CONDVARIABLE_HPP
11 
12 #include <chrono>
13 #include <condition_variable>
14 
16 #include <libpmemobj++/mutex.hpp>
17 #include <libpmemobj/thread.h>
18 
19 namespace pmem
20 {
21 
22 namespace obj
23 {
24 
34  typedef std::chrono::system_clock clock_type;
35 
36 public:
38  typedef PMEMcond *native_handle_type;
39 
47  {
48  PMEMobjpool *pop;
49  if ((pop = pmemobj_pool_by_ptr(&pcond)) == nullptr)
50  throw pmem::lock_error(
51  1, std::generic_category(),
52  "Persistent condition variable not from persistent memory.");
53 
54  pmemobj_cond_zero(pop, &pcond);
55  }
56 
60  ~condition_variable() = default;
61 
70  void
72  {
73  PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
74  if (int ret = pmemobj_cond_signal(pop, &this->pcond))
75  throw pmem::lock_error(
76  ret, std::system_category(),
77  "Error notifying one on a condition variable.")
78  .with_pmemobj_errormsg();
79  }
80 
86  void
88  {
89  PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
90  if (int ret = pmemobj_cond_broadcast(pop, &this->pcond))
91  throw pmem::lock_error(
92  ret, std::system_category(),
93  "Error notifying all on a condition variable.")
94  .with_pmemobj_errormsg();
95  }
96 
112  void
113  wait(mutex &lock)
114  {
115  this->wait_impl(lock);
116  }
117 
135  template <typename Lock>
136  void
137  wait(Lock &lock)
138  {
139  this->wait_impl(*lock.mutex());
140  }
141 
161  template <typename Predicate>
162  void
163  wait(mutex &lock, Predicate pred)
164  {
165  this->wait_impl(lock, std::move(pred));
166  }
167 
189  template <typename Lock, typename Predicate>
190  void
191  wait(Lock &lock, Predicate pred)
192  {
193  this->wait_impl(*lock.mutex(), std::move(pred));
194  }
195 
217  template <typename Clock, typename Duration>
218  std::cv_status
220  const std::chrono::time_point<Clock, Duration> &timeout)
221  {
222  return this->wait_until_impl(lock, timeout);
223  }
224 
248  template <typename Lock, typename Clock, typename Duration>
249  std::cv_status
250  wait_until(Lock &lock,
251  const std::chrono::time_point<Clock, Duration> &timeout)
252  {
253  return this->wait_until_impl(*lock.mutex(), timeout);
254  }
255 
278  template <typename Clock, typename Duration, typename Predicate>
279  bool
281  const std::chrono::time_point<Clock, Duration> &timeout,
282  Predicate pred)
283  {
284  return this->wait_until_impl(lock, timeout, std::move(pred));
285  }
286 
311  template <typename Lock, typename Clock, typename Duration,
312  typename Predicate>
313  bool
314  wait_until(Lock &lock,
315  const std::chrono::time_point<Clock, Duration> &timeout,
316  Predicate pred)
317  {
318  return this->wait_until_impl(*lock.mutex(), timeout,
319  std::move(pred));
320  }
321 
345  template <typename Lock, typename Rep, typename Period>
346  std::cv_status
347  wait_for(Lock &lock, const std::chrono::duration<Rep, Period> &rel_time)
348  {
349  return this->wait_until_impl(*lock.mutex(),
350  clock_type::now() + rel_time);
351  }
352 
377  template <typename Lock, typename Rep, typename Period,
378  typename Predicate>
379  bool
380  wait_for(Lock &lock, const std::chrono::duration<Rep, Period> &rel_time,
381  Predicate pred)
382  {
383  return this->wait_until_impl(*lock.mutex(),
384  clock_type::now() + rel_time,
385  std::move(pred));
386  }
387 
409  template <typename Rep, typename Period>
410  std::cv_status
412  const std::chrono::duration<Rep, Period> &rel_time)
413  {
414  return this->wait_until_impl(lock,
415  clock_type::now() + rel_time);
416  }
417 
440  template <typename Rep, typename Period, typename Predicate>
441  bool
443  const std::chrono::duration<Rep, Period> &rel_time,
444  Predicate pred)
445  {
446  return this->wait_until_impl(lock, clock_type::now() + rel_time,
447  std::move(pred));
448  }
449 
456  native_handle() noexcept
457  {
458  return &this->pcond;
459  }
460 
465 
470 
471 private:
475  void
477  {
478  PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
479  if (int ret = pmemobj_cond_wait(pop, &this->pcond,
480  lock.native_handle()))
481  throw pmem::lock_error(
482  ret, std::system_category(),
483  "Error waiting on a condition variable.")
484  .with_pmemobj_errormsg();
485  }
486 
490  template <typename Predicate>
491  void
492  wait_impl(mutex &lock, Predicate pred)
493  {
494  while (!pred())
495  this->wait(lock);
496  }
497 
501  template <typename Clock, typename Duration>
502  std::cv_status
504  mutex &lock,
505  const std::chrono::time_point<Clock, Duration> &abs_timeout)
506  {
507  PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
508 
509  /* convert to my clock */
510  const typename Clock::time_point their_now = Clock::now();
511  const clock_type::time_point my_now = clock_type::now();
512  const auto delta = abs_timeout - their_now;
513  const auto my_rel = my_now + delta;
514 
515  struct timespec ts = detail::timepoint_to_timespec(my_rel);
516 
517  auto ret = pmemobj_cond_timedwait(pop, &this->pcond,
518  lock.native_handle(), &ts);
519 
520  if (ret == 0)
521  return std::cv_status::no_timeout;
522  else if (ret == ETIMEDOUT)
523  return std::cv_status::timeout;
524  else
525  throw pmem::lock_error(
526  ret, std::system_category(),
527  "Error waiting on a condition variable.")
528  .with_pmemobj_errormsg();
529  }
530 
534  template <typename Clock, typename Duration, typename Predicate>
535  bool
537  mutex &lock,
538  const std::chrono::time_point<Clock, Duration> &abs_timeout,
539  Predicate pred)
540  {
541  while (!pred())
542  if (this->wait_until_impl(lock, abs_timeout) ==
543  std::cv_status::timeout)
544  return pred();
545  return true;
546  }
547 
549  PMEMcond pcond;
550 };
551 
552 } /* namespace obj */
553 
554 } /* namespace pmem */
555 
556 #endif /* LIBPMEMOBJ_CPP_CONDVARIABLE_HPP */
Custom lock error class.
Definition: pexceptions.hpp:100
Persistent memory resident condition variable.
Definition: condition_variable.hpp:33
~condition_variable()=default
Defaulted destructor.
void wait(Lock &lock, Predicate pred)
Makes the current thread block until the condition variable is notified.
Definition: condition_variable.hpp:191
condition_variable & operator=(const condition_variable &)=delete
Deleted assignment operator.
condition_variable(const condition_variable &)=delete
Deleted copy constructor.
PMEMcond pcond
A POSIX style PMEM-resident condition variable.
Definition: condition_variable.hpp:549
void wait_impl(mutex &lock, Predicate pred)
Internal implementation of the wait call.
Definition: condition_variable.hpp:492
condition_variable()
Default constructor.
Definition: condition_variable.hpp:46
native_handle_type native_handle() noexcept
Access a native handle to this condition variable.
Definition: condition_variable.hpp:456
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:536
PMEMcond * native_handle_type
The handle typedef to the underlying basic type.
Definition: condition_variable.hpp:38
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:380
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:347
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:442
void notify_all()
Notify and unblock all threads waiting on *this condition.
Definition: condition_variable.hpp:87
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:503
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:250
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:280
void wait(mutex &lock, Predicate pred)
Makes the current thread block until the condition variable is notified.
Definition: condition_variable.hpp:163
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:411
void notify_one()
Notify and unblock one thread waiting on *this condition.
Definition: condition_variable.hpp:71
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:137
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:113
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:314
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:219
void wait_impl(mutex &lock)
Internal implementation of the wait call.
Definition: condition_variable.hpp:476
Persistent memory resident mutex implementation.
Definition: mutex.hpp:31
native_handle_type native_handle() noexcept
Access a native handle to this condition variable.
Definition: mutex.hpp:132
Commonly used conversions.
Pmem-resident mutex.
timespec timepoint_to_timespec(const std::chrono::time_point< Clock, Duration > &timepoint)
Convert std::chrono::time_point to posix timespec.
Definition: conversions.hpp:30
Persistent memory namespace.
Definition: allocation_flag.hpp:15