1 // Copyright 2022 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_SINGLE_SET_PTR_H 16 #define GRPC_SRC_CORE_UTIL_SINGLE_SET_PTR_H 17 18 #include <grpc/support/port_platform.h> 19 20 #include <atomic> 21 #include <memory> 22 23 #include "absl/log/check.h" 24 25 namespace grpc_core { 26 27 template <class T, class Deleter = std::default_delete<T>> 28 class SingleSetPtr { 29 public: 30 SingleSetPtr() = default; SingleSetPtr(T * p)31 explicit SingleSetPtr(T* p) : p_{p} {} SingleSetPtr(std::unique_ptr<T,Deleter> p)32 explicit SingleSetPtr(std::unique_ptr<T, Deleter> p) : p_{p.release()} {} ~SingleSetPtr()33 ~SingleSetPtr() { Delete(p_.load(std::memory_order_relaxed)); } 34 35 SingleSetPtr(const SingleSetPtr&) = delete; 36 SingleSetPtr& operator=(const SingleSetPtr&) = delete; SingleSetPtr(SingleSetPtr && other)37 SingleSetPtr(SingleSetPtr&& other) noexcept 38 : p_(other.p_.exchange(nullptr)) {} 39 SingleSetPtr& operator=(SingleSetPtr&& other) noexcept { 40 Set(other.p_.exchange(nullptr, std::memory_order_acq_rel)); 41 return *this; 42 } 43 44 // Set the pointer; 45 // if already set, return the pre-set value and delete ptr; 46 // if deleted, return nullptr and delete ptr. Set(T * ptr)47 T* Set(T* ptr) { 48 T* expected = nullptr; 49 if (!p_.compare_exchange_strong(expected, ptr, std::memory_order_acq_rel, 50 std::memory_order_acquire)) { 51 Delete(ptr); 52 return expected; 53 } 54 return ptr; 55 } 56 57 // Set the pointer from a compatible unique_ptr - with the same caveats as 58 // above. Set(std::unique_ptr<T,Deleter> ptr)59 T* Set(std::unique_ptr<T, Deleter> ptr) { return Set(ptr.release()); } 60 61 // Clear the pointer. Reset()62 void Reset() { Delete(p_.exchange(nullptr, std::memory_order_acq_rel)); } 63 is_set()64 bool is_set() const { 65 T* p = Get(); 66 return p != nullptr; 67 } 68 Get()69 T* Get() const { return p_.load(std::memory_order_acquire); } 70 71 T* operator->() const { 72 T* p = Get(); 73 DCHECK_NE(p, nullptr); 74 return p; 75 } 76 77 T& operator*() const { return *Get(); } 78 79 private: Delete(T * p)80 static void Delete(T* p) { 81 if (p == nullptr) return; 82 Deleter()(p); 83 } 84 std::atomic<T*> p_{nullptr}; 85 }; 86 87 } // namespace grpc_core 88 89 #endif // GRPC_SRC_CORE_UTIL_SINGLE_SET_PTR_H 90