• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 gRPC 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 //     http://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 GRPC_SRC_CORE_UTIL_UNIQUE_PTR_WITH_BITSET_H
16 #define GRPC_SRC_CORE_UTIL_UNIQUE_PTR_WITH_BITSET_H
17 
18 #include <memory>
19 #include <utility>
20 
21 #include "absl/log/check.h"
22 #include "absl/numeric/bits.h"
23 
24 namespace grpc_core {
25 
26 // Like std::unique_ptr, but also includes a small bitset stored in the lower
27 // bits of the underlying T*.
28 template <typename T, size_t kBits>
29 class UniquePtrWithBitset {
30  public:
UniquePtrWithBitset()31   UniquePtrWithBitset() : p_(0) {}
32   // NOLINTNEXTLINE(google-explicit-constructor)
UniquePtrWithBitset(std::nullptr_t)33   UniquePtrWithBitset(std::nullptr_t) : p_(0) {}
UniquePtrWithBitset(T * p)34   explicit UniquePtrWithBitset(T* p) : p_(reinterpret_cast<uintptr_t>(p)) {}
35   // NOLINTNEXTLINE(google-explicit-constructor)
UniquePtrWithBitset(std::unique_ptr<T> && p)36   UniquePtrWithBitset(std::unique_ptr<T>&& p)
37       : UniquePtrWithBitset(p.release()) {}
~UniquePtrWithBitset()38   ~UniquePtrWithBitset() {
39     DCHECK_LE(kBits, static_cast<size_t>(absl::countr_zero(alignof(T))));
40     delete get();
41   }
42   UniquePtrWithBitset(const UniquePtrWithBitset&) = delete;
43   UniquePtrWithBitset& operator=(const UniquePtrWithBitset&) = delete;
UniquePtrWithBitset(UniquePtrWithBitset && other)44   UniquePtrWithBitset(UniquePtrWithBitset&& other) noexcept
45       : p_(std::exchange(other.p_, 0)) {}
46   UniquePtrWithBitset& operator=(UniquePtrWithBitset&& other) noexcept {
47     p_ = std::exchange(other.p_, 0);
48     return *this;
49   }
50 
get()51   T* get() const { return reinterpret_cast<T*>(p_ & ~kBitMask); }
52   T* operator->() const { return get(); }
53   T& operator*() const { return *get(); }
54   explicit operator bool() const { return get() != nullptr; }
55   void reset(T* p = nullptr) {
56     uintptr_t bits = p_ & kBitMask;
57     delete get();
58     p_ = reinterpret_cast<uintptr_t>(p) | bits;
59   }
60 
SetBit(size_t bit)61   void SetBit(size_t bit) {
62     DCHECK_LT(bit, kBits);
63     p_ |= 1 << bit;
64   }
ClearBit(size_t bit)65   void ClearBit(size_t bit) {
66     DCHECK_LT(bit, kBits);
67     p_ &= ~(1 << bit);
68   }
TestBit(size_t bit)69   bool TestBit(size_t bit) const {
70     DCHECK_LT(bit, kBits);
71     return p_ & (1 << bit);
72   }
73 
74   friend bool operator==(const UniquePtrWithBitset& a,
75                          const UniquePtrWithBitset& b) {
76     return a.p_ == b.p_;
77   }
78 
79  private:
80   static constexpr uintptr_t kBitMask = (1 << kBits) - 1;
81   uintptr_t p_;
82 };
83 
84 }  // namespace grpc_core
85 
86 #endif  // GRPC_SRC_CORE_UTIL_UNIQUE_PTR_WITH_BITSET_H
87