• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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