PMDK C++ bindings  1.8.1
This is the C++ bindings documentation for PMDK's libpmemobj.
common.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2016-2019, 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 LIBPMEMOBJ_CPP_COMMON_HPP
39 #define LIBPMEMOBJ_CPP_COMMON_HPP
40 
42 #include <libpmemobj/tx_base.h>
43 #include <string>
44 #include <typeinfo>
45 
46 #if _MSC_VER
47 #include <intrin.h>
48 #include <windows.h>
49 #endif
50 
51 #if defined(__GNUC__) || defined(__clang__)
52 #define POBJ_CPP_DEPRECATED __attribute__((deprecated))
53 #elif defined(_MSC_VER)
54 #define POBJ_CPP_DEPRECATED __declspec(deprecated)
55 #else
56 #define POBJ_CPP_DEPRECATED
57 #endif
58 
59 #if LIBPMEMOBJ_CPP_VG_ENABLED
60 #undef LIBPMEMOBJ_CPP_VG_PMEMCHECK_ENABLED
61 #undef LIBPMEMOBJ_CPP_VG_MEMCHECK_ENABLED
62 #undef LIBPMEMOBJ_CPP_VG_HELGRIND_ENABLED
63 #undef LIBPMEMOBJ_CPP_VG_DRD_ENABLED
64 
65 #define LIBPMEMOBJ_CPP_VG_PMEMCHECK_ENABLED 1
66 #define LIBPMEMOBJ_CPP_VG_MEMCHECK_ENABLED 1
67 #define LIBPMEMOBJ_CPP_VG_HELGRIND_ENABLED 1
68 #define LIBPMEMOBJ_CPP_VG_DRD_ENABLED 1
69 #endif
70 
71 #if LIBPMEMOBJ_CPP_VG_PMEMCHECK_ENABLED || \
72  LIBPMEMOBJ_CPP_VG_MEMCHECK_ENABLED || \
73  LIBPMEMOBJ_CPP_VG_HELGRIND_ENABLED || LIBPMEMOBJ_CPP_VG_DRD_ENABLED
74 #define LIBPMEMOBJ_CPP_ANY_VG_TOOL_ENABLED 1
75 #endif
76 
77 #if LIBPMEMOBJ_CPP_ANY_VG_TOOL_ENABLED
78 #include <valgrind.h>
79 #endif
80 
81 #if LIBPMEMOBJ_CPP_VG_PMEMCHECK_ENABLED
82 #include <pmemcheck.h>
83 #endif
84 
85 #if LIBPMEMOBJ_CPP_VG_MEMCHECK_ENABLED
86 #include <memcheck.h>
87 #endif
88 
89 #if LIBPMEMOBJ_CPP_VG_HELGRIND_ENABLED
90 #include <helgrind.h>
91 #endif
92 
93 #if LIBPMEMOBJ_CPP_VG_DRD_ENABLED
94 #include <drd.h>
95 #endif
96 
97 /*
98  * Workaround for missing "is_trivially_copyable" in gcc < 5.0.
99  * Be aware of a difference between __has_trivial_copy and is_trivially_copyable
100  * e.g. for deleted copy constructors __has_trivial_copy(A) returns 1 in clang
101  * and 0 in gcc. It means that for gcc < 5 LIBPMEMOBJ_CPP_IS_TRIVIALLY_COPYABLE
102  * is more restrictive than is_trivially_copyable.
103  */
104 #if !defined(LIBPMEMOBJ_CPP_USE_HAS_TRIVIAL_COPY)
105 #if !defined(__clang__) && defined(__GNUG__) && __GNUC__ < 5
106 #define LIBPMEMOBJ_CPP_USE_HAS_TRIVIAL_COPY 1
107 #else
108 #define LIBPMEMOBJ_CPP_USE_HAS_TRIVIAL_COPY 0
109 #endif
110 #endif
111 
112 #if LIBPMEMOBJ_CPP_USE_HAS_TRIVIAL_COPY
113 #define LIBPMEMOBJ_CPP_IS_TRIVIALLY_COPYABLE(T) __has_trivial_copy(T)
114 #else
115 #define LIBPMEMOBJ_CPP_IS_TRIVIALLY_COPYABLE(T) \
116  std::is_trivially_copyable<T>::value
117 #endif
118 
119 namespace pmem
120 {
121 
122 namespace obj
123 {
124 template <typename T>
125 class persistent_ptr;
126 }
127 
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::transaction_error
Custom transaction error class.
Definition: pexceptions.hpp:90
pmem
A persistent version of concurrent hash map implementation Ref: https://arxiv.org/abs/1509....
Definition: allocation_flag.hpp:44
pmem::transaction_out_of_memory
Custom out of memory error class.
Definition: pexceptions.hpp:147
pexceptions.hpp
Custom exceptions.
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