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) 82 : weak_ptr_(std::shared_ptr<T*>(new T* {owner})) { 83 PERFETTO_DCHECK_THREAD(thread_checker); 84 } 85 ~WeakPtrFactory()86 ~WeakPtrFactory() { 87 PERFETTO_DCHECK_THREAD(thread_checker); 88 *(weak_ptr_.handle_.get()) = nullptr; 89 } 90 91 // Can be safely called on any thread, since it simply copies |weak_ptr_|. 92 // Note that any accesses to the returned pointer need to be made on the 93 // thread that created/reset the factory. GetWeakPtr()94 WeakPtr<T> GetWeakPtr() const { return weak_ptr_; } 95 96 // Reset the factory to a new owner & thread. May only be called before any 97 // weak pointers were passed out. Future weak pointers will be valid on the 98 // calling thread. Reset(T * owner)99 void Reset(T* owner) { 100 // Reset thread checker to current thread. 101 PERFETTO_DETACH_FROM_THREAD(thread_checker); 102 PERFETTO_DCHECK_THREAD(thread_checker); 103 104 // We should not have passed out any weak pointers yet at this point. 105 PERFETTO_DCHECK(weak_ptr_.handle_.use_count() == 1); 106 107 weak_ptr_ = WeakPtr<T>(std::shared_ptr<T*>(new T* {owner})); 108 } 109 110 private: 111 WeakPtrFactory(const WeakPtrFactory&) = delete; 112 WeakPtrFactory& operator=(const WeakPtrFactory&) = delete; 113 114 WeakPtr<T> weak_ptr_; 115 PERFETTO_THREAD_CHECKER(thread_checker) 116 }; 117 118 } // namespace base 119 } // namespace perfetto 120 121 #endif // INCLUDE_PERFETTO_EXT_BASE_WEAK_PTR_H_ 122