PMDK C++ bindings 1.13.0
This is the C++ bindings documentation for PMDK's libpmemobj.
life.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2/* Copyright 2016-2021, Intel Corporation */
3
9#ifndef LIBPMEMOBJ_CPP_DESTROYER_HPP
10#define LIBPMEMOBJ_CPP_DESTROYER_HPP
11
12#include <cstddef>
13#include <tuple>
14#include <type_traits>
15#include <utility>
16
19
20namespace pmem
21{
22
23namespace detail
24{
25
26/*
27 * Template for checking if T is not an array.
28 */
29template <typename T>
30struct if_not_array {
31 typedef T type;
32};
33
34/*
35 * Template for checking if T is not an array.
36 */
37template <typename T>
38struct if_not_array<T[]>;
39
40/*
41 * Template for checking if T is not an array.
42 */
43template <typename T, size_t N>
44struct if_not_array<T[N]>;
45
46/*
47 * Template for checking if T is an array.
48 */
49template <typename T>
50struct if_size_array;
51
52/*
53 * Template for checking if T is an array.
54 */
55template <typename T>
56struct if_size_array<T[]>;
57
58/*
59 * Template for checking if T is an array.
60 */
61template <typename T, size_t N>
62struct if_size_array<T[N]> {
63 typedef T type[N];
64};
65
66/*
67 * Calls object's constructor.
68 *
69 * Supports aggregate initialization since C++17
70 */
71template <typename T, typename... Args>
72void
73create(typename if_not_array<T>::type *ptr, Args &&... args)
74{
75#if __cpp_lib_is_aggregate
76 if constexpr (std::is_aggregate_v<T>)
77 new (static_cast<void *>(ptr)) T{std::forward<Args>(args)...};
78 else
79 new (static_cast<void *>(ptr)) T(std::forward<Args>(args)...);
80#else
81 new (static_cast<void *>(ptr)) T(std::forward<Args>(args)...);
82#endif
83}
84
85/*
86 * Recursively calls array's elements' constructors.
87 */
88template <typename T, typename... Args>
89void
90create(typename if_size_array<T>::type *ptr, Args &&... args)
91{
92 typedef typename detail::pp_array_type<T>::type I;
93 enum { N = pp_array_elems<T>::elems };
94
95 for (std::size_t i = 0; i < N; ++i)
96 create<I>(&(*ptr)[i], std::forward<Args>(args)...);
97}
98
99/*
100 * Calls the objects constructor.
101 *
102 * Unpacks the tuple to get constructor's parameters.
103 */
104template <typename T, size_t... Indices, typename Tuple>
105void
106create_from_tuple(void *ptr, index_sequence<Indices...>, Tuple tuple)
107{
108 new (ptr) T(std::get<Indices>(std::move(tuple))...);
109}
110
111/*
112 * C-style function which calls T constructor with arguments packed in a tuple.
113 *
114 * The arg is a tuple containing constructor parameters.
115 */
116template <typename T, typename Tuple, typename... Args>
117int
118c_style_construct(void *ptr, void *arg)
119{
120 auto *arg_pack = static_cast<Tuple *>(arg);
121
122 typedef typename make_index_sequence<Args...>::type index;
123 try {
124 create_from_tuple<T>(ptr, index(), std::move(*arg_pack));
125 } catch (...) {
126 return -1;
127 }
128
129 return 0;
130}
131
132/*
133 * Calls object's destructor.
134 */
135template <typename T,
136 typename = typename std::enable_if<
137 !std::is_trivially_destructible<T>::value>::type>
138void
139destroy(typename if_not_array<T>::type &arg)
140{
141 arg.~T();
142}
143
144/*
145 * Don't call destructors for POD types.
146 */
147template <typename T, typename dummy = void,
148 typename = typename std::enable_if<
149 std::is_trivially_destructible<T>::value>::type>
150void
151destroy(typename if_not_array<T>::type &)
152{
153}
154
155/*
156 * Recursively calls array's elements' destructors.
157 */
158template <typename T>
159void
160destroy(typename if_size_array<T>::type &arg)
161{
162 typedef typename detail::pp_array_type<T>::type I;
163 enum { N = pp_array_elems<T>::elems };
164
165 for (std::size_t i = 0; i < N; ++i)
166 destroy<I>(arg[N - 1 - i]);
167}
168
169} /* namespace detail */
170
171} /* namespace pmem */
172
173#endif /* LIBPMEMOBJ_CPP_DESTROYER_HPP */
Common array traits.
Create c++14 style index sequence.
Persistent memory namespace.
Definition: allocation_flag.hpp:15