blob: 070a7f96066285f5d87cfe0aa376bc1c28596426 [file] [log] [blame]
Primiano Tucci4f9b6d72017-12-05 20:59:16 +00001/*
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
24namespace perfetto {
25namespace base {
26
27// A simple WeakPtr for single-threaded cases.
Primiano Tucci68323b02017-12-18 10:54:13 +010028// Generally keep the WeakPtrFactory as last fields in classes: it makes the
29// WeakPtr(s) invalidate as first thing in the class dtor.
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000030// 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
49template <typename T>
50class WeakPtrFactory; // Forward declaration, defined below.
51
52template <typename T>
53class WeakPtr {
54 public:
55 WeakPtr() {}
56 WeakPtr(const WeakPtr&) = default;
57 WeakPtr& operator=(const WeakPtr&) = default;
58 WeakPtr(WeakPtr&&) = default;
59 WeakPtr& operator=(WeakPtr&&) = default;
60
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>;
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
78template <typename T>
79class WeakPtrFactory {
80 public:
81 explicit WeakPtrFactory(T* owner) : handle_(new T* {owner}) {
82 PERFETTO_DCHECK_THREAD(thread_checker);
83 }
84 ~WeakPtrFactory() {
85 PERFETTO_DCHECK_THREAD(thread_checker);
86 *(handle_.get()) = nullptr;
87 }
88
89 WeakPtr<T> GetWeakPtr() const {
90 PERFETTO_DCHECK_THREAD(thread_checker);
91 return WeakPtr<T>(handle_);
92 }
93
94 private:
95 WeakPtrFactory(const WeakPtrFactory&) = delete;
96 WeakPtrFactory& operator=(const WeakPtrFactory&) = delete;
97
98 std::shared_ptr<T*> handle_;
99 PERFETTO_THREAD_CHECKER(thread_checker)
100};
101
102} // namespace base
103} // namespace perfetto
104
105#endif // INCLUDE_PERFETTO_BASE_WEAK_PTR_H_