xref: /aosp_15_r20/external/pytorch/c10/util/SmallBuffer.h (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
1*da0073e9SAndroid Build Coastguard Worker #pragma once
2*da0073e9SAndroid Build Coastguard Worker #include <array>
3*da0073e9SAndroid Build Coastguard Worker #include <cstddef>
4*da0073e9SAndroid Build Coastguard Worker #include <cstdint>
5*da0073e9SAndroid Build Coastguard Worker #include <type_traits>
6*da0073e9SAndroid Build Coastguard Worker 
7*da0073e9SAndroid Build Coastguard Worker /** Helper class for allocating temporary fixed size arrays with SBO.
8*da0073e9SAndroid Build Coastguard Worker  *
9*da0073e9SAndroid Build Coastguard Worker  * This is intentionally much simpler than SmallVector, to improve performance
10*da0073e9SAndroid Build Coastguard Worker  * at the expense of many features:
11*da0073e9SAndroid Build Coastguard Worker  * - No zero-initialization for numeric types
12*da0073e9SAndroid Build Coastguard Worker  * - No resizing after construction
13*da0073e9SAndroid Build Coastguard Worker  * - No copy/move
14*da0073e9SAndroid Build Coastguard Worker  * - No non-trivial types
15*da0073e9SAndroid Build Coastguard Worker  */
16*da0073e9SAndroid Build Coastguard Worker 
17*da0073e9SAndroid Build Coastguard Worker namespace c10 {
18*da0073e9SAndroid Build Coastguard Worker 
19*da0073e9SAndroid Build Coastguard Worker template <typename T, size_t N>
20*da0073e9SAndroid Build Coastguard Worker class SmallBuffer {
21*da0073e9SAndroid Build Coastguard Worker   static_assert(std::is_trivial_v<T>, "SmallBuffer is intended for POD types");
22*da0073e9SAndroid Build Coastguard Worker 
23*da0073e9SAndroid Build Coastguard Worker   std::array<T, N> storage_;
24*da0073e9SAndroid Build Coastguard Worker   size_t size_{};
25*da0073e9SAndroid Build Coastguard Worker   T* data_{};
26*da0073e9SAndroid Build Coastguard Worker 
27*da0073e9SAndroid Build Coastguard Worker  public:
SmallBuffer(size_t size)28*da0073e9SAndroid Build Coastguard Worker   SmallBuffer(size_t size) : size_(size) {
29*da0073e9SAndroid Build Coastguard Worker     if (size > N) {
30*da0073e9SAndroid Build Coastguard Worker       data_ = new T[size];
31*da0073e9SAndroid Build Coastguard Worker     } else {
32*da0073e9SAndroid Build Coastguard Worker       data_ = &storage_[0];
33*da0073e9SAndroid Build Coastguard Worker     }
34*da0073e9SAndroid Build Coastguard Worker   }
35*da0073e9SAndroid Build Coastguard Worker 
36*da0073e9SAndroid Build Coastguard Worker   SmallBuffer(const SmallBuffer&) = delete;
37*da0073e9SAndroid Build Coastguard Worker   SmallBuffer& operator=(const SmallBuffer&) = delete;
38*da0073e9SAndroid Build Coastguard Worker 
39*da0073e9SAndroid Build Coastguard Worker   // move constructor is needed in function return
SmallBuffer(SmallBuffer && rhs)40*da0073e9SAndroid Build Coastguard Worker   SmallBuffer(SmallBuffer&& rhs) noexcept : size_{rhs.size_} {
41*da0073e9SAndroid Build Coastguard Worker     rhs.size_ = 0;
42*da0073e9SAndroid Build Coastguard Worker     if (size_ > N) {
43*da0073e9SAndroid Build Coastguard Worker       data_ = rhs.data_;
44*da0073e9SAndroid Build Coastguard Worker       rhs.data_ = nullptr;
45*da0073e9SAndroid Build Coastguard Worker     } else {
46*da0073e9SAndroid Build Coastguard Worker       storage_ = std::move(rhs.storage_);
47*da0073e9SAndroid Build Coastguard Worker       data_ = &storage_[0];
48*da0073e9SAndroid Build Coastguard Worker     }
49*da0073e9SAndroid Build Coastguard Worker   }
50*da0073e9SAndroid Build Coastguard Worker 
51*da0073e9SAndroid Build Coastguard Worker   SmallBuffer& operator=(SmallBuffer&&) = delete;
52*da0073e9SAndroid Build Coastguard Worker 
~SmallBuffer()53*da0073e9SAndroid Build Coastguard Worker   ~SmallBuffer() {
54*da0073e9SAndroid Build Coastguard Worker     if (size_ > N) {
55*da0073e9SAndroid Build Coastguard Worker       delete[] data_;
56*da0073e9SAndroid Build Coastguard Worker     }
57*da0073e9SAndroid Build Coastguard Worker   }
58*da0073e9SAndroid Build Coastguard Worker   T& operator[](size_t idx) {
59*da0073e9SAndroid Build Coastguard Worker     return data()[idx];
60*da0073e9SAndroid Build Coastguard Worker   }
61*da0073e9SAndroid Build Coastguard Worker   const T& operator[](size_t idx) const {
62*da0073e9SAndroid Build Coastguard Worker     return data()[idx];
63*da0073e9SAndroid Build Coastguard Worker   }
data()64*da0073e9SAndroid Build Coastguard Worker   T* data() {
65*da0073e9SAndroid Build Coastguard Worker     return data_;
66*da0073e9SAndroid Build Coastguard Worker   }
data()67*da0073e9SAndroid Build Coastguard Worker   const T* data() const {
68*da0073e9SAndroid Build Coastguard Worker     return data_;
69*da0073e9SAndroid Build Coastguard Worker   }
size()70*da0073e9SAndroid Build Coastguard Worker   size_t size() const {
71*da0073e9SAndroid Build Coastguard Worker     return size_;
72*da0073e9SAndroid Build Coastguard Worker   }
begin()73*da0073e9SAndroid Build Coastguard Worker   T* begin() {
74*da0073e9SAndroid Build Coastguard Worker     return data_;
75*da0073e9SAndroid Build Coastguard Worker   }
begin()76*da0073e9SAndroid Build Coastguard Worker   const T* begin() const {
77*da0073e9SAndroid Build Coastguard Worker     return data_;
78*da0073e9SAndroid Build Coastguard Worker   }
end()79*da0073e9SAndroid Build Coastguard Worker   T* end() {
80*da0073e9SAndroid Build Coastguard Worker     return data_ + size_;
81*da0073e9SAndroid Build Coastguard Worker   }
end()82*da0073e9SAndroid Build Coastguard Worker   const T* end() const {
83*da0073e9SAndroid Build Coastguard Worker     return data_ + size_;
84*da0073e9SAndroid Build Coastguard Worker   }
85*da0073e9SAndroid Build Coastguard Worker };
86*da0073e9SAndroid Build Coastguard Worker 
87*da0073e9SAndroid Build Coastguard Worker } // namespace c10
88