Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-08-28 08:27:01

0001 // Licensed to the Apache Software Foundation (ASF) under one
0002 // or more contributor license agreements.  See the NOTICE file
0003 // distributed with this work for additional information
0004 // regarding copyright ownership.  The ASF licenses this file
0005 // to you under the Apache License, Version 2.0 (the
0006 // "License"); you may not use this file except in compliance
0007 // with the License.  You may obtain a copy of the License at
0008 //
0009 //   http://www.apache.org/licenses/LICENSE-2.0
0010 //
0011 // Unless required by applicable law or agreed to in writing,
0012 // software distributed under the License is distributed on an
0013 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0014 // KIND, either express or implied.  See the License for the
0015 // specific language governing permissions and limitations
0016 // under the License.
0017 
0018 #pragma once
0019 
0020 #include <cstring>
0021 #include <type_traits>
0022 #include <utility>
0023 
0024 #include "arrow/util/launder.h"
0025 #include "arrow/util/macros.h"
0026 
0027 namespace arrow {
0028 namespace internal {
0029 
0030 template <typename T>
0031 class AlignedStorage {
0032  public:
0033   static constexpr bool can_memcpy = std::is_trivial<T>::value;
0034 
0035   constexpr T* get() noexcept {
0036     return arrow::internal::launder(reinterpret_cast<T*>(&data_));
0037   }
0038 
0039   constexpr const T* get() const noexcept {
0040     // Use fully qualified name to avoid ambiguities with MSVC (ARROW-14800)
0041     return arrow::internal::launder(reinterpret_cast<const T*>(&data_));
0042   }
0043 
0044   void destroy() noexcept {
0045     if (!std::is_trivially_destructible<T>::value) {
0046       get()->~T();
0047     }
0048   }
0049 
0050   template <typename... A>
0051   void construct(A&&... args) noexcept {
0052     new (&data_) T(std::forward<A>(args)...);
0053   }
0054 
0055   template <typename V>
0056   void assign(V&& v) noexcept {
0057     *get() = std::forward<V>(v);
0058   }
0059 
0060   void move_construct(AlignedStorage* other) noexcept {
0061     new (&data_) T(std::move(*other->get()));
0062   }
0063 
0064   void move_assign(AlignedStorage* other) noexcept { *get() = std::move(*other->get()); }
0065 
0066   template <bool CanMemcpy = can_memcpy>
0067   static typename std::enable_if<CanMemcpy>::type move_construct_several(
0068       AlignedStorage* ARROW_RESTRICT src, AlignedStorage* ARROW_RESTRICT dest, size_t n,
0069       size_t memcpy_length) noexcept {
0070     memcpy(dest->get(), src->get(), memcpy_length * sizeof(T));
0071   }
0072 
0073   template <bool CanMemcpy = can_memcpy>
0074   static typename std::enable_if<CanMemcpy>::type
0075   move_construct_several_and_destroy_source(AlignedStorage* ARROW_RESTRICT src,
0076                                             AlignedStorage* ARROW_RESTRICT dest, size_t n,
0077                                             size_t memcpy_length) noexcept {
0078     memcpy(dest->get(), src->get(), memcpy_length * sizeof(T));
0079   }
0080 
0081   template <bool CanMemcpy = can_memcpy>
0082   static typename std::enable_if<!CanMemcpy>::type move_construct_several(
0083       AlignedStorage* ARROW_RESTRICT src, AlignedStorage* ARROW_RESTRICT dest, size_t n,
0084       size_t memcpy_length) noexcept {
0085     for (size_t i = 0; i < n; ++i) {
0086       new (dest[i].get()) T(std::move(*src[i].get()));
0087     }
0088   }
0089 
0090   template <bool CanMemcpy = can_memcpy>
0091   static typename std::enable_if<!CanMemcpy>::type
0092   move_construct_several_and_destroy_source(AlignedStorage* ARROW_RESTRICT src,
0093                                             AlignedStorage* ARROW_RESTRICT dest, size_t n,
0094                                             size_t memcpy_length) noexcept {
0095     for (size_t i = 0; i < n; ++i) {
0096       new (dest[i].get()) T(std::move(*src[i].get()));
0097       src[i].destroy();
0098     }
0099   }
0100 
0101   static void move_construct_several(AlignedStorage* ARROW_RESTRICT src,
0102                                      AlignedStorage* ARROW_RESTRICT dest,
0103                                      size_t n) noexcept {
0104     move_construct_several(src, dest, n, n);
0105   }
0106 
0107   static void move_construct_several_and_destroy_source(
0108       AlignedStorage* ARROW_RESTRICT src, AlignedStorage* ARROW_RESTRICT dest,
0109       size_t n) noexcept {
0110     move_construct_several_and_destroy_source(src, dest, n, n);
0111   }
0112 
0113   static void destroy_several(AlignedStorage* p, size_t n) noexcept {
0114     if (!std::is_trivially_destructible<T>::value) {
0115       for (size_t i = 0; i < n; ++i) {
0116         p[i].destroy();
0117       }
0118     }
0119   }
0120 
0121  private:
0122   alignas(T) std::byte data_[sizeof(T)];
0123 };
0124 
0125 }  // namespace internal
0126 }  // namespace arrow