PMDK C++ bindings 1.13.0
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-2021, 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#if LIBPMEMOBJ_CPP_VG_HELGRIND_ENABLED
69
70#define LIBPMEMOBJ_CPP_ANNOTATE_HAPPENS_BEFORE(order, ptr) \
71 if (order == std::memory_order_release || \
72 order == std::memory_order_acq_rel || \
73 order == std::memory_order_seq_cst) { \
74 ANNOTATE_HAPPENS_BEFORE(ptr); \
75 }
76
77#define LIBPMEMOBJ_CPP_ANNOTATE_HAPPENS_AFTER(order, ptr) \
78 if (order == std::memory_order_consume || \
79 order == std::memory_order_acquire || \
80 order == std::memory_order_acq_rel || \
81 order == std::memory_order_seq_cst) { \
82 ANNOTATE_HAPPENS_AFTER(ptr); \
83 }
84#else
85
86#define LIBPMEMOBJ_CPP_ANNOTATE_HAPPENS_BEFORE(order, ptr)
87#define LIBPMEMOBJ_CPP_ANNOTATE_HAPPENS_AFTER(order, ptr)
88
89#endif
90
91/*
92 * Workaround for missing "is_trivially_copyable" in gcc < 5.0.
93 * Be aware of a difference between __has_trivial_copy and is_trivially_copyable
94 * e.g. for deleted copy constructors __has_trivial_copy(A) returns 1 in clang
95 * and 0 in gcc. It means that for gcc < 5 LIBPMEMOBJ_CPP_IS_TRIVIALLY_COPYABLE
96 * is more restrictive than is_trivially_copyable.
97 */
98#if !defined(LIBPMEMOBJ_CPP_USE_HAS_TRIVIAL_COPY)
99#if !defined(__clang__) && defined(__GNUG__) && __GNUC__ < 5
100#define LIBPMEMOBJ_CPP_USE_HAS_TRIVIAL_COPY 1
101#else
102#define LIBPMEMOBJ_CPP_USE_HAS_TRIVIAL_COPY 0
103#endif
104#endif
105
106#if LIBPMEMOBJ_CPP_USE_HAS_TRIVIAL_COPY
107#define LIBPMEMOBJ_CPP_IS_TRIVIALLY_COPYABLE(T) __has_trivial_copy(T)
108#else
109#define LIBPMEMOBJ_CPP_IS_TRIVIALLY_COPYABLE(T) \
110 std::is_trivially_copyable<T>::value
111#endif
112
119namespace pmem
120{
127namespace obj
128{
129template <typename T>
130class persistent_ptr;
131
139namespace experimental
140{
141}
142}
143
150namespace detail
151{
152
153#if defined(__x86_64) || defined(_M_X64) || defined(__aarch64__) || \
154 defined(__riscv)
155static constexpr size_t CACHELINE_SIZE = 64ULL;
156#elif defined(__PPC64__)
157static constexpr size_t CACHELINE_SIZE = 128ULL;
158#else
159#error unable to recognize architecture at compile time
160#endif
161
162/*
163 * Conditionally add 'count' objects to a transaction.
164 *
165 * Adds count objects starting from `that` to the transaction if '*that' is
166 * within a pmemobj pool and there is an active transaction.
167 * Does nothing otherwise.
168 *
169 * @param[in] that pointer to the first object being added to the transaction.
170 * @param[in] count number of elements to be added to the transaction.
171 * @param[in] flags is a bitmask of values which are described in libpmemobj
172 * manpage (pmemobj_tx_xadd_range method)
173 */
174template <typename T>
175inline void
176conditional_add_to_tx(const T *that, std::size_t count = 1, uint64_t flags = 0)
177{
178 if (count == 0)
179 return;
180
181 if (pmemobj_tx_stage() != TX_STAGE_WORK)
182 return;
183
184 /* 'that' is not in any open pool */
185 if (!pmemobj_pool_by_ptr(that))
186 return;
187
188 if (pmemobj_tx_xadd_range_direct(that, sizeof(*that) * count, flags)) {
189 if (errno == ENOMEM)
191 "Could not add object(s) to the transaction.")
192 .with_pmemobj_errormsg();
193 else
195 "Could not add object(s) to the transaction.")
196 .with_pmemobj_errormsg();
197 }
198}
199
200/*
201 * Return type number for given type.
202 */
203template <typename T>
204uint64_t
205type_num()
206{
207 return typeid(T).hash_code();
208}
209
213inline uint64_t
214next_pow_2(uint64_t v)
215{
216 v--;
217 v |= v >> 1;
218 v |= v >> 2;
219 v |= v >> 4;
220 v |= v >> 8;
221 v |= v >> 16;
222 v |= v >> 32;
223 ++v;
224 return v + (v == 0);
225}
226
230inline uint64_t
231next_pow_2(uint32_t v)
232{
233 v--;
234 v |= v >> 1;
235 v |= v >> 2;
236 v |= v >> 4;
237 v |= v >> 8;
238 v |= v >> 16;
239 ++v;
240 return v + (v == 0);
241}
242
243#if _MSC_VER
244static inline int
245Log2(uint64_t x)
246{
247 unsigned long j;
248 _BitScanReverse64(&j, x);
249 return static_cast<int>(j);
250}
251#elif __GNUC__ || __clang__
252static inline int
253Log2(uint64_t x)
254{
255 // __builtin_clz builtin count _number_ of leading zeroes
256 return 8 * int(sizeof(x)) - __builtin_clzll(x) - 1;
257}
258#else
259static inline int
260Log2(uint64_t x)
261{
262 x |= (x >> 1);
263 x |= (x >> 2);
264 x |= (x >> 4);
265 x |= (x >> 8);
266 x |= (x >> 16);
267 x |= (x >> 32);
268
269 static const int table[64] = {
270 0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61,
271 51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, 62,
272 57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21, 56,
273 45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5, 63};
274
275 return table[(x * 0x03f6eaf2cd271461) >> 58];
276}
277#endif
278
279#ifndef _MSC_VER
280
282static inline uint8_t
283mssb_index64(unsigned long long value)
284{
285 return ((uint8_t)(63 - __builtin_clzll(value)));
286}
287
289static inline uint8_t
290mssb_index(unsigned int value)
291{
292 return ((uint8_t)(31 - __builtin_clz(value)));
293}
294
295#else
296
297static __inline uint8_t
298mssb_index(unsigned long value)
299{
300 unsigned long ret;
301 _BitScanReverse(&ret, value);
302 return (uint8_t)ret;
303}
304
305static __inline uint8_t
306mssb_index64(uint64_t value)
307{
308 unsigned long ret;
309 _BitScanReverse64(&ret, value);
310 return (uint8_t)ret;
311}
312
313#endif
314
315static constexpr size_t
316align_up(size_t size, size_t align)
317{
318 return ((size) + (align)-1) & ~((align)-1);
319}
320
321static constexpr size_t
322align_down(size_t size, size_t align)
323{
324 return (size) & ~((align)-1);
325}
326
327} /* namespace detail */
328
329} /* namespace pmem */
330
331#endif /* LIBPMEMOBJ_CPP_COMMON_HPP */
Custom transaction error class.
Definition: pexceptions.hpp:81
Custom out of memory error class.
Definition: pexceptions.hpp:138
uint64_t next_pow_2(uint64_t v)
Round up to the next lowest power of 2.
Definition: common.hpp:214
Persistent memory namespace.
Definition: allocation_flag.hpp:15
Custom exceptions.