PMDK C++ bindings 1.2.0
This is the C++ bindings documentation for PMDK's libpmemobj.
condition_variable.hpp
Go to the documentation of this file.
1/*
2 * Copyright 2016-2017, 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
46#include "libpmemobj/thread.h"
47
48namespace pmem
49{
50
51namespace obj
52{
53
63 typedef std::chrono::system_clock clock_type;
64
65public:
67 typedef PMEMcond *native_handle_type;
68
76 {
77 PMEMobjpool *pop;
78 if ((pop = pmemobj_pool_by_ptr(&pcond)) == nullptr)
79 throw lock_error(
80 1, std::generic_category(),
81 "Persistent condition variable not from"
82 " persistent memory.");
83
84 pmemobj_cond_zero(pop, &pcond);
85 }
86
91
100 void
102 {
103 PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
104 if (int ret = pmemobj_cond_signal(pop, &this->pcond))
105 throw lock_error(ret, std::system_category(),
106 "Error notifying one on "
107 "a condition variable.");
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 lock_error(ret, std::system_category(),
121 "Error notifying all on "
122 "a condition variable.");
123 }
124
140 void
141 wait(mutex &lock)
142 {
143 this->wait_impl(lock);
144 }
145
163 template <typename Lock>
164 void
165 wait(Lock &lock)
166 {
167 this->wait_impl(*lock.mutex());
168 }
169
189 template <typename Predicate>
190 void
191 wait(mutex &lock, Predicate pred)
192 {
193 this->wait_impl(lock, std::move(pred));
194 }
195
217 template <typename Lock, typename Predicate>
218 void
219 wait(Lock &lock, Predicate pred)
220 {
221 this->wait_impl(*lock.mutex(), std::move(pred));
222 }
223
245 template <typename Clock, typename Duration>
246 std::cv_status
248 const std::chrono::time_point<Clock, Duration> &timeout)
249 {
250 return this->wait_until_impl(lock, timeout);
251 }
252
276 template <typename Lock, typename Clock, typename Duration>
277 std::cv_status
278 wait_until(Lock &lock,
279 const std::chrono::time_point<Clock, Duration> &timeout)
280 {
281 return this->wait_until_impl(*lock.mutex(), timeout);
282 }
283
306 template <typename Clock, typename Duration, typename Predicate>
307 bool
309 const std::chrono::time_point<Clock, Duration> &timeout,
310 Predicate pred)
311 {
312 return this->wait_until_impl(lock, timeout, std::move(pred));
313 }
314
339 template <typename Lock, typename Clock, typename Duration,
340 typename Predicate>
341 bool
342 wait_until(Lock &lock,
343 const std::chrono::time_point<Clock, Duration> &timeout,
344 Predicate pred)
345 {
346 return this->wait_until_impl(*lock.mutex(), timeout,
347 std::move(pred));
348 }
349
373 template <typename Lock, typename Rep, typename Period>
374 std::cv_status
375 wait_for(Lock &lock, const std::chrono::duration<Rep, Period> &rel_time)
376 {
377 return this->wait_until_impl(*lock.mutex(),
378 clock_type::now() + rel_time);
379 }
380
405 template <typename Lock, typename Rep, typename Period,
406 typename Predicate>
407 bool
408 wait_for(Lock &lock, const std::chrono::duration<Rep, Period> &rel_time,
409 Predicate pred)
410 {
411 return this->wait_until_impl(*lock.mutex(),
412 clock_type::now() + rel_time,
413 std::move(pred));
414 }
415
437 template <typename Rep, typename Period>
438 std::cv_status
440 const std::chrono::duration<Rep, Period> &rel_time)
441 {
442 return this->wait_until_impl(lock,
443 clock_type::now() + rel_time);
444 }
445
468 template <typename Rep, typename Period, typename Predicate>
469 bool
471 const std::chrono::duration<Rep, Period> &rel_time,
472 Predicate pred)
473 {
474 return this->wait_until_impl(lock, clock_type::now() + rel_time,
475 std::move(pred));
476 }
477
484 native_handle() noexcept
485 {
486 return &this->pcond;
487 }
488
493
498
499private:
503 void
505 {
506 PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
507 if (int ret = pmemobj_cond_wait(pop, &this->pcond,
508 lock.native_handle()))
509 throw lock_error(ret, std::system_category(),
510 "Error waiting on a condition "
511 "variable.");
512 }
513
517 template <typename Predicate>
518 void
519 wait_impl(mutex &lock, Predicate pred)
520 {
521 while (!pred())
522 this->wait(lock);
523 }
524
528 template <typename Clock, typename Duration>
529 std::cv_status
531 mutex &lock,
532 const std::chrono::time_point<Clock, Duration> &abs_timeout)
533 {
534 PMEMobjpool *pop = pmemobj_pool_by_ptr(this);
535
536 /* convert to my clock */
537 const typename Clock::time_point their_now = Clock::now();
538 const clock_type::time_point my_now = clock_type::now();
539 const auto delta = abs_timeout - their_now;
540 const auto my_rel = my_now + delta;
541
542 struct timespec ts = detail::timepoint_to_timespec(my_rel);
543
544 auto ret = pmemobj_cond_timedwait(pop, &this->pcond,
545 lock.native_handle(), &ts);
546
547 if (ret == 0)
548 return std::cv_status::no_timeout;
549 else if (ret == ETIMEDOUT)
550 return std::cv_status::timeout;
551 else
552 throw lock_error(ret, std::system_category(),
553 "Error waiting on a condition "
554 "variable.");
555 }
556
560 template <typename Clock, typename Duration, typename Predicate>
561 bool
563 mutex &lock,
564 const std::chrono::time_point<Clock, Duration> &abs_timeout,
565 Predicate pred)
566 {
567 while (!pred())
568 if (this->wait_until_impl(lock, abs_timeout) ==
569 std::cv_status::timeout)
570 return pred();
571 return true;
572 }
573
575 PMEMcond pcond;
576};
577
578} /* namespace obj */
579
580} /* namespace pmem */
581
582#endif /* PMEMOBJ_CONDVARIABLE_HPP */
Custom lock error class.
Definition: pexceptions.hpp:74
Persistent memory resident condition variable.
Definition: condition_variable.hpp:62
~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:219
condition_variable(const condition_variable &)=delete
Deleted copy constructor.
PMEMcond pcond
A POSIX style PMEM-resident condition variable.
Definition: condition_variable.hpp:575
void wait_impl(mutex &lock, Predicate pred)
Internal implementation of the wait call.
Definition: condition_variable.hpp:519
condition_variable()
Default constructor.
Definition: condition_variable.hpp:75
native_handle_type native_handle() noexcept
Access a native handle to this condition variable.
Definition: condition_variable.hpp:484
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:562
PMEMcond * native_handle_type
The handle typedef to the underlying basic type.
Definition: condition_variable.hpp:67
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:408
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:375
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:470
void notify_all()
Notify and unblock all threads waiting on *this condition.
Definition: condition_variable.hpp:116
condition_variable & operator=(const condition_variable &)=delete
Deleted assignment operator.
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:530
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:278
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:308
void wait(mutex &lock, Predicate pred)
Makes the current thread block until the condition variable is notified.
Definition: condition_variable.hpp:191
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:439
void notify_one()
Notify and unblock one thread waiting on *this condition.
Definition: condition_variable.hpp:101
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:165
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:141
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:342
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:247
void wait_impl(mutex &lock)
Internal implementation of the wait call.
Definition: condition_variable.hpp:504
Persistent memory resident mutex implementation.
Definition: mutex.hpp:60
native_handle_type native_handle() noexcept
Access a native handle to this condition variable.
Definition: mutex.hpp:155
Commonly used conversions.
Pmem-resident mutex.