PMDK C++ bindings  1.9.1
This is the C++ bindings documentation for PMDK's libpmemobj.
condition_variable.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2016-2019, 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 LIBPMEMOBJ_CPP_CONDVARIABLE_HPP
39 #define LIBPMEMOBJ_CPP_CONDVARIABLE_HPP
40 
41 #include <chrono>
42 #include <condition_variable>
43 
45 #include <libpmemobj++/mutex.hpp>
46 #include <libpmemobj/thread.h>
47 
48 namespace pmem
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 
76  {
77  PMEMobjpool *pop;
78  if ((pop = pmemobj_pool_by_ptr(&pcond)) == nullptr)
79  throw pmem::lock_error(
80  1, std::generic_category(),
81  "Persistent condition variable not from persistent memory.");
82 
83  pmemobj_cond_zero(pop, &pcond);
84  }
85 
89  ~condition_variable() = default;
90 
99  void
101  {
102  PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
103  if (int ret = pmemobj_cond_signal(pop, &this->pcond))
104  throw pmem::lock_error(
105  ret, std::system_category(),
106  "Error notifying one on a condition variable.")
107  .with_pmemobj_errormsg();
108  }
109 
115  void
117  {
118  PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
119  if (int ret = pmemobj_cond_broadcast(pop, &this->pcond))
120  throw pmem::lock_error(
121  ret, std::system_category(),
122  "Error notifying all on a condition variable.")
123  .with_pmemobj_errormsg();
124  }
125 
141  void
142  wait(mutex &lock)
143  {
144  this->wait_impl(lock);
145  }
146 
164  template <typename Lock>
165  void
166  wait(Lock &lock)
167  {
168  this->wait_impl(*lock.mutex());
169  }
170 
190  template <typename Predicate>
191  void
192  wait(mutex &lock, Predicate pred)
193  {
194  this->wait_impl(lock, std::move(pred));
195  }
196 
218  template <typename Lock, typename Predicate>
219  void
220  wait(Lock &lock, Predicate pred)
221  {
222  this->wait_impl(*lock.mutex(), std::move(pred));
223  }
224 
246  template <typename Clock, typename Duration>
247  std::cv_status
249  const std::chrono::time_point<Clock, Duration> &timeout)
250  {
251  return this->wait_until_impl(lock, timeout);
252  }
253 
277  template <typename Lock, typename Clock, typename Duration>
278  std::cv_status
279  wait_until(Lock &lock,
280  const std::chrono::time_point<Clock, Duration> &timeout)
281  {
282  return this->wait_until_impl(*lock.mutex(), timeout);
283  }
284 
307  template <typename Clock, typename Duration, typename Predicate>
308  bool
310  const std::chrono::time_point<Clock, Duration> &timeout,
311  Predicate pred)
312  {
313  return this->wait_until_impl(lock, timeout, std::move(pred));
314  }
315 
340  template <typename Lock, typename Clock, typename Duration,
341  typename Predicate>
342  bool
343  wait_until(Lock &lock,
344  const std::chrono::time_point<Clock, Duration> &timeout,
345  Predicate pred)
346  {
347  return this->wait_until_impl(*lock.mutex(), timeout,
348  std::move(pred));
349  }
350 
374  template <typename Lock, typename Rep, typename Period>
375  std::cv_status
376  wait_for(Lock &lock, const std::chrono::duration<Rep, Period> &rel_time)
377  {
378  return this->wait_until_impl(*lock.mutex(),
379  clock_type::now() + rel_time);
380  }
381 
406  template <typename Lock, typename Rep, typename Period,
407  typename Predicate>
408  bool
409  wait_for(Lock &lock, const std::chrono::duration<Rep, Period> &rel_time,
410  Predicate pred)
411  {
412  return this->wait_until_impl(*lock.mutex(),
413  clock_type::now() + rel_time,
414  std::move(pred));
415  }
416 
438  template <typename Rep, typename Period>
439  std::cv_status
441  const std::chrono::duration<Rep, Period> &rel_time)
442  {
443  return this->wait_until_impl(lock,
444  clock_type::now() + rel_time);
445  }
446 
469  template <typename Rep, typename Period, typename Predicate>
470  bool
472  const std::chrono::duration<Rep, Period> &rel_time,
473  Predicate pred)
474  {
475  return this->wait_until_impl(lock, clock_type::now() + rel_time,
476  std::move(pred));
477  }
478 
485  native_handle() noexcept
486  {
487  return &this->pcond;
488  }
489 
494 
499 
500 private:
504  void
506  {
507  PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
508  if (int ret = pmemobj_cond_wait(pop, &this->pcond,
509  lock.native_handle()))
510  throw pmem::lock_error(
511  ret, std::system_category(),
512  "Error waiting on a condition variable.")
513  .with_pmemobj_errormsg();
514  }
515 
519  template <typename Predicate>
520  void
521  wait_impl(mutex &lock, Predicate pred)
522  {
523  while (!pred())
524  this->wait(lock);
525  }
526 
530  template <typename Clock, typename Duration>
531  std::cv_status
533  mutex &lock,
534  const std::chrono::time_point<Clock, Duration> &abs_timeout)
535  {
536  PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
537 
538  /* convert to my clock */
539  const typename Clock::time_point their_now = Clock::now();
540  const clock_type::time_point my_now = clock_type::now();
541  const auto delta = abs_timeout - their_now;
542  const auto my_rel = my_now + delta;
543 
544  struct timespec ts = detail::timepoint_to_timespec(my_rel);
545 
546  auto ret = pmemobj_cond_timedwait(pop, &this->pcond,
547  lock.native_handle(), &ts);
548 
549  if (ret == 0)
550  return std::cv_status::no_timeout;
551  else if (ret == ETIMEDOUT)
552  return std::cv_status::timeout;
553  else
554  throw pmem::lock_error(
555  ret, std::system_category(),
556  "Error waiting on a condition variable.")
557  .with_pmemobj_errormsg();
558  }
559 
563  template <typename Clock, typename Duration, typename Predicate>
564  bool
566  mutex &lock,
567  const std::chrono::time_point<Clock, Duration> &abs_timeout,
568  Predicate pred)
569  {
570  while (!pred())
571  if (this->wait_until_impl(lock, abs_timeout) ==
572  std::cv_status::timeout)
573  return pred();
574  return true;
575  }
576 
578  PMEMcond pcond;
579 };
580 
581 } /* namespace obj */
582 
583 } /* namespace pmem */
584 
585 #endif /* LIBPMEMOBJ_CPP_CONDVARIABLE_HPP */
pmem::obj::condition_variable::wait_until
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:248
pmem::obj::condition_variable::wait_for
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:440
pmem::detail::timepoint_to_timespec
timespec timepoint_to_timespec(const std::chrono::time_point< Clock, Duration > &timepoint)
Convert std::chrono::time_point to posix timespec.
Definition: conversions.hpp:59
pmem::obj::condition_variable::wait_for
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:376
pmem::obj::mutex
Persistent memory resident mutex implementation.
Definition: mutex.hpp:60
pmem::obj::condition_variable::wait_for
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:471
pmem
Persistent memory namespace.
Definition: allocation_flag.hpp:44
pmem::obj::condition_variable::pcond
PMEMcond pcond
A POSIX style PMEM-resident condition variable.
Definition: condition_variable.hpp:578
pmem::obj::mutex::native_handle
native_handle_type native_handle() noexcept
Access a native handle to this condition variable.
Definition: mutex.hpp:161
conversions.hpp
Commonly used conversions.
pmem::obj::condition_variable::condition_variable
condition_variable()
Default constructor.
Definition: condition_variable.hpp:75
pmem::obj::condition_variable::wait_until_impl
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:532
pmem::obj::condition_variable::wait
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:142
pmem::obj::condition_variable::notify_one
void notify_one()
Notify and unblock one thread waiting on *this condition.
Definition: condition_variable.hpp:100
pmem::obj::condition_variable::operator=
condition_variable & operator=(const condition_variable &)=delete
Deleted assignment operator.
pmem::obj::condition_variable::wait
void wait(mutex &lock, Predicate pred)
Makes the current thread block until the condition variable is notified.
Definition: condition_variable.hpp:192
pmem::obj::condition_variable::wait_impl
void wait_impl(mutex &lock, Predicate pred)
Internal implementation of the wait call.
Definition: condition_variable.hpp:521
pmem::lock_error
Custom lock error class.
Definition: pexceptions.hpp:113
pmem::obj::condition_variable::wait
void wait(Lock &lock, Predicate pred)
Makes the current thread block until the condition variable is notified.
Definition: condition_variable.hpp:220
pmem::obj::condition_variable::wait_until
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:279
pmem::obj::condition_variable::native_handle
native_handle_type native_handle() noexcept
Access a native handle to this condition variable.
Definition: condition_variable.hpp:485
pmem::obj::condition_variable::condition_variable
condition_variable(const condition_variable &)=delete
Deleted copy constructor.
pmem::obj::condition_variable::native_handle_type
PMEMcond * native_handle_type
The handle typedef to the underlying basic type.
Definition: condition_variable.hpp:67
pmem::obj::condition_variable::wait_impl
void wait_impl(mutex &lock)
Internal implementation of the wait call.
Definition: condition_variable.hpp:505
pmem::obj::condition_variable
Persistent memory resident condition variable.
Definition: condition_variable.hpp:62
pmem::obj::condition_variable::~condition_variable
~condition_variable()=default
Defaulted destructor.
pmem::obj::condition_variable::wait_until_impl
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:565
pmem::obj::condition_variable::notify_all
void notify_all()
Notify and unblock all threads waiting on *this condition.
Definition: condition_variable.hpp:116
pmem::obj::condition_variable::wait_until
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:309
pmem::obj::condition_variable::wait_for
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:409
mutex.hpp
Pmem-resident mutex.
pmem::obj::condition_variable::wait_until
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:343
pmem::obj::condition_variable::wait
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:166