PMDK C++ bindings  1.10.1
This is the C++ bindings documentation for PMDK's libpmemobj.
common.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_COMMON_HPP
10 #define LIBPMEMOBJ_CPP_COMMON_HPP
11 
13 #include <libpmemobj/tx_base.h>
14 #include <string>
15 #include <typeinfo>
16 
17 #if _MSC_VER
18 #include <intrin.h>
19 #include <windows.h>
20 #endif
21 
22 #if defined(__GNUC__) || defined(__clang__)
23 #define POBJ_CPP_DEPRECATED __attribute__((deprecated))
24 #elif defined(_MSC_VER)
25 #define POBJ_CPP_DEPRECATED __declspec(deprecated)
26 #else
27 #define POBJ_CPP_DEPRECATED
28 #endif
29 
30 #if LIBPMEMOBJ_CPP_VG_ENABLED
31 #undef LIBPMEMOBJ_CPP_VG_PMEMCHECK_ENABLED
32 #undef LIBPMEMOBJ_CPP_VG_MEMCHECK_ENABLED
33 #undef LIBPMEMOBJ_CPP_VG_HELGRIND_ENABLED
34 #undef LIBPMEMOBJ_CPP_VG_DRD_ENABLED
35 
36 #define LIBPMEMOBJ_CPP_VG_PMEMCHECK_ENABLED 1
37 #define LIBPMEMOBJ_CPP_VG_MEMCHECK_ENABLED 1
38 #define LIBPMEMOBJ_CPP_VG_HELGRIND_ENABLED 1
39 #define LIBPMEMOBJ_CPP_VG_DRD_ENABLED 1
40 #endif
41 
42 #if LIBPMEMOBJ_CPP_VG_PMEMCHECK_ENABLED || \
43  LIBPMEMOBJ_CPP_VG_MEMCHECK_ENABLED || \
44  LIBPMEMOBJ_CPP_VG_HELGRIND_ENABLED || LIBPMEMOBJ_CPP_VG_DRD_ENABLED
45 #define LIBPMEMOBJ_CPP_ANY_VG_TOOL_ENABLED 1
46 #endif
47 
48 #if LIBPMEMOBJ_CPP_ANY_VG_TOOL_ENABLED
49 #include <valgrind.h>
50 #endif
51 
52 #if LIBPMEMOBJ_CPP_VG_PMEMCHECK_ENABLED
53 #include <pmemcheck.h>
54 #endif
55 
56 #if LIBPMEMOBJ_CPP_VG_MEMCHECK_ENABLED
57 #include <memcheck.h>
58 #endif
59 
60 #if LIBPMEMOBJ_CPP_VG_HELGRIND_ENABLED
61 #include <helgrind.h>
62 #endif
63 
64 #if LIBPMEMOBJ_CPP_VG_DRD_ENABLED
65 #include <drd.h>
66 #endif
67 
68 /*
69  * Workaround for missing "is_trivially_copyable" in gcc < 5.0.
70  * Be aware of a difference between __has_trivial_copy and is_trivially_copyable
71  * e.g. for deleted copy constructors __has_trivial_copy(A) returns 1 in clang
72  * and 0 in gcc. It means that for gcc < 5 LIBPMEMOBJ_CPP_IS_TRIVIALLY_COPYABLE
73  * is more restrictive than is_trivially_copyable.
74  */
75 #if !defined(LIBPMEMOBJ_CPP_USE_HAS_TRIVIAL_COPY)
76 #if !defined(__clang__) && defined(__GNUG__) && __GNUC__ < 5
77 #define LIBPMEMOBJ_CPP_USE_HAS_TRIVIAL_COPY 1
78 #else
79 #define LIBPMEMOBJ_CPP_USE_HAS_TRIVIAL_COPY 0
80 #endif
81 #endif
82 
83 #if LIBPMEMOBJ_CPP_USE_HAS_TRIVIAL_COPY
84 #define LIBPMEMOBJ_CPP_IS_TRIVIALLY_COPYABLE(T) __has_trivial_copy(T)
85 #else
86 #define LIBPMEMOBJ_CPP_IS_TRIVIALLY_COPYABLE(T) \
87  std::is_trivially_copyable<T>::value
88 #endif
89 
97 namespace pmem
98 {
105 namespace obj
106 {
107 template <typename T>
108 class persistent_ptr;
109 
117 namespace experimental
118 {
119 }
120 }
121 
128 namespace detail
129 {
130 
131 /*
132  * Conditionally add 'count' objects to a transaction.
133  *
134  * Adds count objects starting from `that` to the transaction if '*that' is
135  * within a pmemobj pool and there is an active transaction.
136  * Does nothing otherwise.
137  *
138  * @param[in] that pointer to the first object being added to the transaction.
139  * @param[in] count number of elements to be added to the transaction.
140  * @param[in] flags is a bitmask of values which are described in libpmemobj
141  * manpage (pmemobj_tx_xadd_range method)
142  */
143 template <typename T>
144 inline void
145 conditional_add_to_tx(const T *that, std::size_t count = 1, uint64_t flags = 0)
146 {
147  if (count == 0)
148  return;
149 
150  if (pmemobj_tx_stage() != TX_STAGE_WORK)
151  return;
152 
153  /* 'that' is not in any open pool */
154  if (!pmemobj_pool_by_ptr(that))
155  return;
156 
157  if (pmemobj_tx_xadd_range_direct(that, sizeof(*that) * count, flags)) {
158  if (errno == ENOMEM)
160  "Could not add object(s) to the transaction.")
161  .with_pmemobj_errormsg();
162  else
164  "Could not add object(s) to the transaction.")
165  .with_pmemobj_errormsg();
166  }
167 }
168 
169 /*
170  * Return type number for given type.
171  */
172 template <typename T>
173 uint64_t
174 type_num()
175 {
176  return typeid(T).hash_code();
177 }
178 
182 inline uint64_t
183 next_pow_2(uint64_t v)
184 {
185  v--;
186  v |= v >> 1;
187  v |= v >> 2;
188  v |= v >> 4;
189  v |= v >> 8;
190  v |= v >> 16;
191  v |= v >> 32;
192  ++v;
193  return v + (v == 0);
194 }
195 
199 inline uint64_t
200 next_pow_2(uint32_t v)
201 {
202  v--;
203  v |= v >> 1;
204  v |= v >> 2;
205  v |= v >> 4;
206  v |= v >> 8;
207  v |= v >> 16;
208  ++v;
209  return v + (v == 0);
210 }
211 
212 #if _MSC_VER
213 static inline int
214 Log2(uint64_t x)
215 {
216  unsigned long j;
217  _BitScanReverse64(&j, x);
218  return static_cast<int>(j);
219 }
220 #elif __GNUC__ || __clang__
221 static inline int
222 Log2(uint64_t x)
223 {
224  // __builtin_clz builtin count _number_ of leading zeroes
225  return 8 * int(sizeof(x)) - __builtin_clzll(x) - 1;
226 }
227 #else
228 static inline int
229 Log2(uint64_t x)
230 {
231  x |= (x >> 1);
232  x |= (x >> 2);
233  x |= (x >> 4);
234  x |= (x >> 8);
235  x |= (x >> 16);
236  x |= (x >> 32);
237 
238  static const int table[64] = {
239  0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61,
240  51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, 62,
241  57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21, 56,
242  45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5, 63};
243 
244  return table[(x * 0x03f6eaf2cd271461) >> 58];
245 }
246 #endif
247 
248 } /* namespace detail */
249 
250 } /* namespace pmem */
251 
252 #endif /* LIBPMEMOBJ_CPP_COMMON_HPP */
pmem::detail::next_pow_2
uint64_t next_pow_2(uint64_t v)
Round up to the next lowest power of 2.
Definition: common.hpp:183
pmem::transaction_error
Custom transaction error class.
Definition: pexceptions.hpp:65
pmem
Persistent memory namespace.
Definition: allocation_flag.hpp:15
pmem::transaction_out_of_memory
Custom out of memory error class.
Definition: pexceptions.hpp:125
pexceptions.hpp
Custom exceptions.