tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

common_policy_traits.h (5522B)


      1 // Copyright 2022 The Abseil Authors.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      https://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #ifndef ABSL_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_
     16 #define ABSL_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_
     17 
     18 #include <cstddef>
     19 #include <cstring>
     20 #include <memory>
     21 #include <new>
     22 #include <type_traits>
     23 #include <utility>
     24 
     25 #include "absl/meta/type_traits.h"
     26 
     27 namespace absl {
     28 ABSL_NAMESPACE_BEGIN
     29 namespace container_internal {
     30 
     31 template <class Policy, class = void>
     32 struct policy_trait_element_is_owner : std::false_type {};
     33 
     34 template <class Policy>
     35 struct policy_trait_element_is_owner<
     36    Policy,
     37    std::enable_if_t<!std::is_void<typename Policy::element_is_owner>::value>>
     38    : Policy::element_is_owner {};
     39 
     40 // Defines how slots are initialized/destroyed/moved.
     41 template <class Policy, class = void>
     42 struct common_policy_traits {
     43  // The actual object stored in the container.
     44  using slot_type = typename Policy::slot_type;
     45  using reference = decltype(Policy::element(std::declval<slot_type*>()));
     46  using value_type = typename std::remove_reference<reference>::type;
     47 
     48  // PRECONDITION: `slot` is UNINITIALIZED
     49  // POSTCONDITION: `slot` is INITIALIZED
     50  template <class Alloc, class... Args>
     51  static void construct(Alloc* alloc, slot_type* slot, Args&&... args) {
     52    Policy::construct(alloc, slot, std::forward<Args>(args)...);
     53  }
     54 
     55  // PRECONDITION: `slot` is INITIALIZED
     56  // POSTCONDITION: `slot` is UNINITIALIZED
     57  // Returns std::true_type in case destroy is trivial.
     58  template <class Alloc>
     59  static auto destroy(Alloc* alloc, slot_type* slot) {
     60    return Policy::destroy(alloc, slot);
     61  }
     62 
     63  // Transfers the `old_slot` to `new_slot`. Any memory allocated by the
     64  // allocator inside `old_slot` to `new_slot` can be transferred.
     65  //
     66  // OPTIONAL: defaults to:
     67  //
     68  //     clone(new_slot, std::move(*old_slot));
     69  //     destroy(old_slot);
     70  //
     71  // PRECONDITION: `new_slot` is UNINITIALIZED and `old_slot` is INITIALIZED
     72  // POSTCONDITION: `new_slot` is INITIALIZED and `old_slot` is
     73  //                UNINITIALIZED
     74  template <class Alloc>
     75  static void transfer(Alloc* alloc, slot_type* new_slot, slot_type* old_slot) {
     76    transfer_impl(alloc, new_slot, old_slot, Rank2{});
     77  }
     78 
     79  // PRECONDITION: `slot` is INITIALIZED
     80  // POSTCONDITION: `slot` is INITIALIZED
     81  // Note: we use remove_const_t so that the two overloads have different args
     82  // in the case of sets with explicitly const value_types.
     83  template <class P = Policy>
     84  static auto element(absl::remove_const_t<slot_type>* slot)
     85      -> decltype(P::element(slot)) {
     86    return P::element(slot);
     87  }
     88  template <class P = Policy>
     89  static auto element(const slot_type* slot) -> decltype(P::element(slot)) {
     90    return P::element(slot);
     91  }
     92 
     93  static constexpr bool transfer_uses_memcpy() {
     94    return std::is_same<decltype(transfer_impl<std::allocator<char>>(
     95                            nullptr, nullptr, nullptr, Rank2{})),
     96                        std::true_type>::value;
     97  }
     98 
     99  // Returns true if destroy is trivial and can be omitted.
    100  template <class Alloc>
    101  static constexpr bool destroy_is_trivial() {
    102    return std::is_same<decltype(destroy<Alloc>(nullptr, nullptr)),
    103                        std::true_type>::value;
    104  }
    105 
    106 private:
    107  // Use go/ranked-overloads for dispatching.
    108  struct Rank0 {};
    109  struct Rank1 : Rank0 {};
    110  struct Rank2 : Rank1 {};
    111 
    112  // Use auto -> decltype as an enabler.
    113  // P::transfer returns std::true_type if transfer uses memcpy (e.g. in
    114  // node_slot_policy).
    115  template <class Alloc, class P = Policy>
    116  static auto transfer_impl(Alloc* alloc, slot_type* new_slot,
    117                            slot_type* old_slot,
    118                            Rank2) -> decltype(P::transfer(alloc, new_slot,
    119                                                           old_slot)) {
    120    return P::transfer(alloc, new_slot, old_slot);
    121  }
    122 
    123  // This overload returns true_type for the trait below.
    124  // The conditional_t is to make the enabler type dependent.
    125  template <class Alloc,
    126            typename = std::enable_if_t<absl::is_trivially_relocatable<
    127                std::conditional_t<false, Alloc, value_type>>::value>>
    128  static std::true_type transfer_impl(Alloc*, slot_type* new_slot,
    129                                      slot_type* old_slot, Rank1) {
    130    // TODO(b/247130232): remove casts after fixing warnings.
    131    // TODO(b/251814870): remove casts after fixing warnings.
    132    std::memcpy(
    133        static_cast<void*>(std::launder(
    134            const_cast<std::remove_const_t<value_type>*>(&element(new_slot)))),
    135        static_cast<const void*>(&element(old_slot)), sizeof(value_type));
    136    return {};
    137  }
    138 
    139  template <class Alloc>
    140  static void transfer_impl(Alloc* alloc, slot_type* new_slot,
    141                            slot_type* old_slot, Rank0) {
    142    construct(alloc, new_slot, std::move(element(old_slot)));
    143    destroy(alloc, old_slot);
    144  }
    145 };
    146 
    147 }  // namespace container_internal
    148 ABSL_NAMESPACE_END
    149 }  // namespace absl
    150 
    151 #endif  // ABSL_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_