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