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_BASE_WEAK_PTR_H_ 18 #define INCLUDE_PERFETTO_BASE_WEAK_PTR_H_ 19 20 #include "perfetto/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 the factory. GetWeakPtr()94 WeakPtr<T> GetWeakPtr() const { return weak_ptr_; } 95 96 private: 97 WeakPtrFactory(const WeakPtrFactory&) = delete; 98 WeakPtrFactory& operator=(const WeakPtrFactory&) = delete; 99 100 WeakPtr<T> weak_ptr_; 101 PERFETTO_THREAD_CHECKER(thread_checker) 102 }; 103 104 } // namespace base 105 } // namespace perfetto 106 107 #endif // INCLUDE_PERFETTO_BASE_WEAK_PTR_H_ 108