xref: /aosp_15_r20/external/perfetto/include/perfetto/ext/base/weak_ptr.h (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef INCLUDE_PERFETTO_EXT_BASE_WEAK_PTR_H_
18 #define INCLUDE_PERFETTO_EXT_BASE_WEAK_PTR_H_
19 
20 #include "perfetto/ext/base/thread_checker.h"
21 
22 #include <memory>
23 
24 namespace perfetto {
25 namespace base {
26 
27 // A simple WeakPtr for single-threaded cases.
28 // Generally keep the WeakPtrFactory as last fields in classes: it makes the
29 // WeakPtr(s) invalidate as first thing in the class dtor.
30 // Usage:
31 // class MyClass {
32 //  MyClass() : weak_factory_(this) {}
33 //  WeakPtr<MyClass> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
34 //
35 // private:
36 //  WeakPtrFactory<MyClass> weak_factory_;
37 // }
38 //
39 // int main() {
40 //  std::unique_ptr<MyClass> foo(new MyClass);
41 //  auto wptr = foo.GetWeakPtr();
42 //  ASSERT_TRUE(wptr);
43 //  ASSERT_EQ(foo.get(), wptr->get());
44 //  foo.reset();
45 //  ASSERT_FALSE(wptr);
46 //  ASSERT_EQ(nullptr, wptr->get());
47 // }
48 
49 template <typename T>
50 class WeakPtrFactory;  // Forward declaration, defined below.
51 
52 template <typename T>
53 class WeakPtr {
54  public:
WeakPtr()55   WeakPtr() {}
56   WeakPtr(const WeakPtr&) = default;
57   WeakPtr& operator=(const WeakPtr&) = default;
58   WeakPtr(WeakPtr&&) = default;
59   WeakPtr& operator=(WeakPtr&&) = default;
60 
get()61   T* get() const {
62     PERFETTO_DCHECK_THREAD(thread_checker);
63     return handle_ ? *handle_.get() : nullptr;
64   }
65   T* operator->() const { return get(); }
66   T& operator*() const { return *get(); }
67 
68   explicit operator bool() const { return !!get(); }
69 
70  private:
71   friend class WeakPtrFactory<T>;
WeakPtr(const std::shared_ptr<T * > & handle)72   explicit WeakPtr(const std::shared_ptr<T*>& handle) : handle_(handle) {}
73 
74   std::shared_ptr<T*> handle_;
75   PERFETTO_THREAD_CHECKER(thread_checker)
76 };
77 
78 template <typename T>
79 class WeakPtrFactory {
80  public:
WeakPtrFactory(T * owner)81   explicit WeakPtrFactory(T* owner) : weak_ptr_(std::make_shared<T*>(owner)) {
82     PERFETTO_DCHECK_THREAD(thread_checker);
83   }
84 
~WeakPtrFactory()85   ~WeakPtrFactory() {
86     PERFETTO_DCHECK_THREAD(thread_checker);
87     *(weak_ptr_.handle_.get()) = nullptr;
88   }
89 
90   // Can be safely called on any thread, since it simply copies |weak_ptr_|.
91   // Note that any accesses to the returned pointer need to be made on the
92   // thread that created/reset the factory.
GetWeakPtr()93   WeakPtr<T> GetWeakPtr() const { return weak_ptr_; }
94 
95   // Reset the factory to a new owner & thread. May only be called before any
96   // weak pointers were passed out. Future weak pointers will be valid on the
97   // calling thread.
Reset(T * owner)98   void Reset(T* owner) {
99     // Reset thread checker to current thread.
100     PERFETTO_DETACH_FROM_THREAD(thread_checker);
101     PERFETTO_DCHECK_THREAD(thread_checker);
102 
103     // We should not have passed out any weak pointers yet at this point.
104     PERFETTO_DCHECK(weak_ptr_.handle_.use_count() == 1);
105 
106     weak_ptr_ = WeakPtr<T>(std::make_shared<T*>(owner));
107   }
108 
109  private:
110   WeakPtrFactory(const WeakPtrFactory&) = delete;
111   WeakPtrFactory& operator=(const WeakPtrFactory&) = delete;
112 
113   WeakPtr<T> weak_ptr_;
114   PERFETTO_THREAD_CHECKER(thread_checker)
115 };
116 
117 }  // namespace base
118 }  // namespace perfetto
119 
120 #endif  // INCLUDE_PERFETTO_EXT_BASE_WEAK_PTR_H_
121