00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_
00016 #define ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_
00017
00018 #ifdef ADDRESS_SANITIZER
00019 #include <sanitizer/asan_interface.h>
00020 #endif
00021
00022 #ifdef MEMORY_SANITIZER
00023 #include <sanitizer/msan_interface.h>
00024 #endif
00025
00026 #include <cassert>
00027 #include <cstddef>
00028 #include <memory>
00029 #include <tuple>
00030 #include <type_traits>
00031 #include <utility>
00032
00033 #include "absl/memory/memory.h"
00034 #include "absl/utility/utility.h"
00035
00036 namespace absl {
00037 namespace container_internal {
00038
00039
00040
00041
00042
00043
00044
00045
00046 template <size_t Alignment, class Alloc>
00047 void* Allocate(Alloc* alloc, size_t n) {
00048 static_assert(Alignment > 0, "");
00049 assert(n && "n must be positive");
00050 struct alignas(Alignment) M {};
00051 using A = typename absl::allocator_traits<Alloc>::template rebind_alloc<M>;
00052 using AT = typename absl::allocator_traits<Alloc>::template rebind_traits<M>;
00053 A mem_alloc(*alloc);
00054 void* p = AT::allocate(mem_alloc, (n + sizeof(M) - 1) / sizeof(M));
00055 assert(reinterpret_cast<uintptr_t>(p) % Alignment == 0 &&
00056 "allocator does not respect alignment");
00057 return p;
00058 }
00059
00060
00061
00062 template <size_t Alignment, class Alloc>
00063 void Deallocate(Alloc* alloc, void* p, size_t n) {
00064 static_assert(Alignment > 0, "");
00065 assert(n && "n must be positive");
00066 struct alignas(Alignment) M {};
00067 using A = typename absl::allocator_traits<Alloc>::template rebind_alloc<M>;
00068 using AT = typename absl::allocator_traits<Alloc>::template rebind_traits<M>;
00069 A mem_alloc(*alloc);
00070 AT::deallocate(mem_alloc, static_cast<M*>(p),
00071 (n + sizeof(M) - 1) / sizeof(M));
00072 }
00073
00074 namespace memory_internal {
00075
00076
00077
00078 template <class Alloc, class T, class Tuple, size_t... I>
00079 void ConstructFromTupleImpl(Alloc* alloc, T* ptr, Tuple&& t,
00080 absl::index_sequence<I...>) {
00081 absl::allocator_traits<Alloc>::construct(
00082 *alloc, ptr, std::get<I>(std::forward<Tuple>(t))...);
00083 }
00084
00085 template <class T, class F>
00086 struct WithConstructedImplF {
00087 template <class... Args>
00088 decltype(std::declval<F>()(std::declval<T>())) operator()(
00089 Args&&... args) const {
00090 return std::forward<F>(f)(T(std::forward<Args>(args)...));
00091 }
00092 F&& f;
00093 };
00094
00095 template <class T, class Tuple, size_t... Is, class F>
00096 decltype(std::declval<F>()(std::declval<T>())) WithConstructedImpl(
00097 Tuple&& t, absl::index_sequence<Is...>, F&& f) {
00098 return WithConstructedImplF<T, F>{std::forward<F>(f)}(
00099 std::get<Is>(std::forward<Tuple>(t))...);
00100 }
00101
00102 template <class T, size_t... Is>
00103 auto TupleRefImpl(T&& t, absl::index_sequence<Is...>)
00104 -> decltype(std::forward_as_tuple(std::get<Is>(std::forward<T>(t))...)) {
00105 return std::forward_as_tuple(std::get<Is>(std::forward<T>(t))...);
00106 }
00107
00108
00109
00110 template <class T>
00111 auto TupleRef(T&& t) -> decltype(
00112 TupleRefImpl(std::forward<T>(t),
00113 absl::make_index_sequence<
00114 std::tuple_size<typename std::decay<T>::type>::value>())) {
00115 return TupleRefImpl(
00116 std::forward<T>(t),
00117 absl::make_index_sequence<
00118 std::tuple_size<typename std::decay<T>::type>::value>());
00119 }
00120
00121 template <class F, class K, class V>
00122 decltype(std::declval<F>()(std::declval<const K&>(), std::piecewise_construct,
00123 std::declval<std::tuple<K>>(), std::declval<V>()))
00124 DecomposePairImpl(F&& f, std::pair<std::tuple<K>, V> p) {
00125 const auto& key = std::get<0>(p.first);
00126 return std::forward<F>(f)(key, std::piecewise_construct, std::move(p.first),
00127 std::move(p.second));
00128 }
00129
00130 }
00131
00132
00133
00134 template <class Alloc, class T, class Tuple>
00135 void ConstructFromTuple(Alloc* alloc, T* ptr, Tuple&& t) {
00136 memory_internal::ConstructFromTupleImpl(
00137 alloc, ptr, std::forward<Tuple>(t),
00138 absl::make_index_sequence<
00139 std::tuple_size<typename std::decay<Tuple>::type>::value>());
00140 }
00141
00142
00143
00144 template <class T, class Tuple, class F>
00145 decltype(std::declval<F>()(std::declval<T>())) WithConstructed(
00146 Tuple&& t, F&& f) {
00147 return memory_internal::WithConstructedImpl<T>(
00148 std::forward<Tuple>(t),
00149 absl::make_index_sequence<
00150 std::tuple_size<typename std::decay<Tuple>::type>::value>(),
00151 std::forward<F>(f));
00152 }
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 inline std::pair<std::tuple<>, std::tuple<>> PairArgs() { return {}; }
00166 template <class F, class S>
00167 std::pair<std::tuple<F&&>, std::tuple<S&&>> PairArgs(F&& f, S&& s) {
00168 return {std::piecewise_construct, std::forward_as_tuple(std::forward<F>(f)),
00169 std::forward_as_tuple(std::forward<S>(s))};
00170 }
00171 template <class F, class S>
00172 std::pair<std::tuple<const F&>, std::tuple<const S&>> PairArgs(
00173 const std::pair<F, S>& p) {
00174 return PairArgs(p.first, p.second);
00175 }
00176 template <class F, class S>
00177 std::pair<std::tuple<F&&>, std::tuple<S&&>> PairArgs(std::pair<F, S>&& p) {
00178 return PairArgs(std::forward<F>(p.first), std::forward<S>(p.second));
00179 }
00180 template <class F, class S>
00181 auto PairArgs(std::piecewise_construct_t, F&& f, S&& s)
00182 -> decltype(std::make_pair(memory_internal::TupleRef(std::forward<F>(f)),
00183 memory_internal::TupleRef(std::forward<S>(s)))) {
00184 return std::make_pair(memory_internal::TupleRef(std::forward<F>(f)),
00185 memory_internal::TupleRef(std::forward<S>(s)));
00186 }
00187
00188
00189 template <class F, class... Args>
00190 auto DecomposePair(F&& f, Args&&... args)
00191 -> decltype(memory_internal::DecomposePairImpl(
00192 std::forward<F>(f), PairArgs(std::forward<Args>(args)...))) {
00193 return memory_internal::DecomposePairImpl(
00194 std::forward<F>(f), PairArgs(std::forward<Args>(args)...));
00195 }
00196
00197
00198 template <class F, class Arg>
00199 decltype(std::declval<F>()(std::declval<const Arg&>(), std::declval<Arg>()))
00200 DecomposeValue(F&& f, Arg&& arg) {
00201 const auto& key = arg;
00202 return std::forward<F>(f)(key, std::forward<Arg>(arg));
00203 }
00204
00205
00206 inline void SanitizerPoisonMemoryRegion(const void* m, size_t s) {
00207 #ifdef ADDRESS_SANITIZER
00208 ASAN_POISON_MEMORY_REGION(m, s);
00209 #endif
00210 #ifdef MEMORY_SANITIZER
00211 __msan_poison(m, s);
00212 #endif
00213 (void)m;
00214 (void)s;
00215 }
00216
00217 inline void SanitizerUnpoisonMemoryRegion(const void* m, size_t s) {
00218 #ifdef ADDRESS_SANITIZER
00219 ASAN_UNPOISON_MEMORY_REGION(m, s);
00220 #endif
00221 #ifdef MEMORY_SANITIZER
00222 __msan_unpoison(m, s);
00223 #endif
00224 (void)m;
00225 (void)s;
00226 }
00227
00228 template <typename T>
00229 inline void SanitizerPoisonObject(const T* object) {
00230 SanitizerPoisonMemoryRegion(object, sizeof(T));
00231 }
00232
00233 template <typename T>
00234 inline void SanitizerUnpoisonObject(const T* object) {
00235 SanitizerUnpoisonMemoryRegion(object, sizeof(T));
00236 }
00237
00238 namespace memory_internal {
00239
00240
00241
00242
00243
00244
00245
00246 template <class Pair, class = std::true_type>
00247 struct OffsetOf {
00248 static constexpr size_t kFirst = -1;
00249 static constexpr size_t kSecond = -1;
00250 };
00251
00252 template <class Pair>
00253 struct OffsetOf<Pair, typename std::is_standard_layout<Pair>::type> {
00254 static constexpr size_t kFirst = offsetof(Pair, first);
00255 static constexpr size_t kSecond = offsetof(Pair, second);
00256 };
00257
00258 template <class K, class V>
00259 struct IsLayoutCompatible {
00260 private:
00261 struct Pair {
00262 K first;
00263 V second;
00264 };
00265
00266
00267 template <class P>
00268 static constexpr bool LayoutCompatible() {
00269 return std::is_standard_layout<P>() && sizeof(P) == sizeof(Pair) &&
00270 alignof(P) == alignof(Pair) &&
00271 memory_internal::OffsetOf<P>::kFirst ==
00272 memory_internal::OffsetOf<Pair>::kFirst &&
00273 memory_internal::OffsetOf<P>::kSecond ==
00274 memory_internal::OffsetOf<Pair>::kSecond;
00275 }
00276
00277 public:
00278
00279
00280 static constexpr bool value = std::is_standard_layout<K>() &&
00281 std::is_standard_layout<Pair>() &&
00282 memory_internal::OffsetOf<Pair>::kFirst == 0 &&
00283 LayoutCompatible<std::pair<K, V>>() &&
00284 LayoutCompatible<std::pair<const K, V>>();
00285 };
00286
00287 }
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 template <class K, class V>
00314 union map_slot_type {
00315 map_slot_type() {}
00316 ~map_slot_type() = delete;
00317 using value_type = std::pair<const K, V>;
00318 using mutable_value_type = std::pair<K, V>;
00319
00320 value_type value;
00321 mutable_value_type mutable_value;
00322 K key;
00323 };
00324
00325 template <class K, class V>
00326 struct map_slot_policy {
00327 using slot_type = map_slot_type<K, V>;
00328 using value_type = std::pair<const K, V>;
00329 using mutable_value_type = std::pair<K, V>;
00330
00331 private:
00332 static void emplace(slot_type* slot) {
00333
00334
00335 new (slot) slot_type;
00336 }
00337
00338
00339
00340 using kMutableKeys = memory_internal::IsLayoutCompatible<K, V>;
00341
00342 public:
00343 static value_type& element(slot_type* slot) { return slot->value; }
00344 static const value_type& element(const slot_type* slot) {
00345 return slot->value;
00346 }
00347
00348 static const K& key(const slot_type* slot) {
00349 return kMutableKeys::value ? slot->key : slot->value.first;
00350 }
00351
00352 template <class Allocator, class... Args>
00353 static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {
00354 emplace(slot);
00355 if (kMutableKeys::value) {
00356 absl::allocator_traits<Allocator>::construct(*alloc, &slot->mutable_value,
00357 std::forward<Args>(args)...);
00358 } else {
00359 absl::allocator_traits<Allocator>::construct(*alloc, &slot->value,
00360 std::forward<Args>(args)...);
00361 }
00362 }
00363
00364
00365 template <class Allocator>
00366 static void construct(Allocator* alloc, slot_type* slot, slot_type* other) {
00367 emplace(slot);
00368 if (kMutableKeys::value) {
00369 absl::allocator_traits<Allocator>::construct(
00370 *alloc, &slot->mutable_value, std::move(other->mutable_value));
00371 } else {
00372 absl::allocator_traits<Allocator>::construct(*alloc, &slot->value,
00373 std::move(other->value));
00374 }
00375 }
00376
00377 template <class Allocator>
00378 static void destroy(Allocator* alloc, slot_type* slot) {
00379 if (kMutableKeys::value) {
00380 absl::allocator_traits<Allocator>::destroy(*alloc, &slot->mutable_value);
00381 } else {
00382 absl::allocator_traits<Allocator>::destroy(*alloc, &slot->value);
00383 }
00384 }
00385
00386 template <class Allocator>
00387 static void transfer(Allocator* alloc, slot_type* new_slot,
00388 slot_type* old_slot) {
00389 emplace(new_slot);
00390 if (kMutableKeys::value) {
00391 absl::allocator_traits<Allocator>::construct(
00392 *alloc, &new_slot->mutable_value, std::move(old_slot->mutable_value));
00393 } else {
00394 absl::allocator_traits<Allocator>::construct(*alloc, &new_slot->value,
00395 std::move(old_slot->value));
00396 }
00397 destroy(alloc, old_slot);
00398 }
00399
00400 template <class Allocator>
00401 static void swap(Allocator* alloc, slot_type* a, slot_type* b) {
00402 if (kMutableKeys::value) {
00403 using std::swap;
00404 swap(a->mutable_value, b->mutable_value);
00405 } else {
00406 value_type tmp = std::move(a->value);
00407 absl::allocator_traits<Allocator>::destroy(*alloc, &a->value);
00408 absl::allocator_traits<Allocator>::construct(*alloc, &a->value,
00409 std::move(b->value));
00410 absl::allocator_traits<Allocator>::destroy(*alloc, &b->value);
00411 absl::allocator_traits<Allocator>::construct(*alloc, &b->value,
00412 std::move(tmp));
00413 }
00414 }
00415
00416 template <class Allocator>
00417 static void move(Allocator* alloc, slot_type* src, slot_type* dest) {
00418 if (kMutableKeys::value) {
00419 dest->mutable_value = std::move(src->mutable_value);
00420 } else {
00421 absl::allocator_traits<Allocator>::destroy(*alloc, &dest->value);
00422 absl::allocator_traits<Allocator>::construct(*alloc, &dest->value,
00423 std::move(src->value));
00424 }
00425 }
00426
00427 template <class Allocator>
00428 static void move(Allocator* alloc, slot_type* first, slot_type* last,
00429 slot_type* result) {
00430 for (slot_type *src = first, *dest = result; src != last; ++src, ++dest)
00431 move(alloc, src, dest);
00432 }
00433 };
00434
00435 }
00436 }
00437
00438 #endif // ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_