PMDK C++ bindings  1.12-git53.g67ba2be4
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 
96 namespace pmem
97 {
104 namespace obj
105 {
106 template <typename T>
107 class persistent_ptr;
108 
116 namespace experimental
117 {
118 }
119 }
120 
127 namespace detail
128 {
129 
130 /*
131  * Conditionally add 'count' objects to a transaction.
132  *
133  * Adds count objects starting from `that` to the transaction if '*that' is
134  * within a pmemobj pool and there is an active transaction.
135  * Does nothing otherwise.
136  *
137  * @param[in] that pointer to the first object being added to the transaction.
138  * @param[in] count number of elements to be added to the transaction.
139  * @param[in] flags is a bitmask of values which are described in libpmemobj
140  * manpage (pmemobj_tx_xadd_range method)
141  */
142 template <typename T>
143 inline void
144 conditional_add_to_tx(const T *that, std::size_t count = 1, uint64_t flags = 0)
145 {
146  if (count == 0)
147  return;
148 
149  if (pmemobj_tx_stage() != TX_STAGE_WORK)
150  return;
151 
152  /* 'that' is not in any open pool */
153  if (!pmemobj_pool_by_ptr(that))
154  return;
155 
156  if (pmemobj_tx_xadd_range_direct(that, sizeof(*that) * count, flags)) {
157  if (errno == ENOMEM)
159  "Could not add object(s) to the transaction.")
160  .with_pmemobj_errormsg();
161  else
163  "Could not add object(s) to the transaction.")
164  .with_pmemobj_errormsg();
165  }
166 }
167 
168 /*
169  * Return type number for given type.
170  */
171 template <typename T>
172 uint64_t
173 type_num()
174 {
175  return typeid(T).hash_code();
176 }
177 
181 inline uint64_t
182 next_pow_2(uint64_t v)
183 {
184  v--;
185  v |= v >> 1;
186  v |= v >> 2;
187  v |= v >> 4;
188  v |= v >> 8;
189  v |= v >> 16;
190  v |= v >> 32;
191  ++v;
192  return v + (v == 0);
193 }
194 
198 inline uint64_t
199 next_pow_2(uint32_t v)
200 {
201  v--;
202  v |= v >> 1;
203  v |= v >> 2;
204  v |= v >> 4;
205  v |= v >> 8;
206  v |= v >> 16;
207  ++v;
208  return v + (v == 0);
209 }
210 
211 #if _MSC_VER
212 static inline int
213 Log2(uint64_t x)
214 {
215  unsigned long j;
216  _BitScanReverse64(&j, x);
217  return static_cast<int>(j);
218 }
219 #elif __GNUC__ || __clang__
220 static inline int
221 Log2(uint64_t x)
222 {
223  // __builtin_clz builtin count _number_ of leading zeroes
224  return 8 * int(sizeof(x)) - __builtin_clzll(x) - 1;
225 }
226 #else
227 static inline int
228 Log2(uint64_t x)
229 {
230  x |= (x >> 1);
231  x |= (x >> 2);
232  x |= (x >> 4);
233  x |= (x >> 8);
234  x |= (x >> 16);
235  x |= (x >> 32);
236 
237  static const int table[64] = {
238  0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61,
239  51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, 62,
240  57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21, 56,
241  45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5, 63};
242 
243  return table[(x * 0x03f6eaf2cd271461) >> 58];
244 }
245 #endif
246 
247 #ifndef _MSC_VER
248 
250 static inline uint8_t
251 mssb_index64(unsigned long long value)
252 {
253  return ((uint8_t)(63 - __builtin_clzll(value)));
254 }
255 
257 static inline uint8_t
258 mssb_index(unsigned int value)
259 {
260  return ((uint8_t)(31 - __builtin_clz(value)));
261 }
262 
263 #else
264 
265 static __inline uint8_t
266 mssb_index(unsigned long value)
267 {
268  unsigned long ret;
269  _BitScanReverse(&ret, value);
270  return (uint8_t)ret;
271 }
272 
273 static __inline uint8_t
274 mssb_index64(uint64_t value)
275 {
276  unsigned long ret;
277  _BitScanReverse64(&ret, value);
278  return (uint8_t)ret;
279 }
280 
281 #endif
282 
283 } /* namespace detail */
284 
285 } /* namespace pmem */
286 
287 #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:182
pmem::transaction_error
Custom transaction error class.
Definition: pexceptions.hpp:63
pmem
Persistent memory namespace.
Definition: allocation_flag.hpp:15
pmem::transaction_out_of_memory
Custom out of memory error class.
Definition: pexceptions.hpp:120
pexceptions.hpp
Custom exceptions.