OLD | NEW |
| (Empty) |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // Weak handles provides a way to refer to weak pointers from another | |
6 // thread. This is useful because it is not safe to reference a weak | |
7 // pointer from a thread other than the thread on which it was | |
8 // created. | |
9 // | |
10 // Weak handles can be passed across threads, so for example, you can | |
11 // use them to do the "real" work on one thread and get notified on | |
12 // another thread: | |
13 // | |
14 // class FooIOWorker { | |
15 // public: | |
16 // FooIOWorker(const WeakHandle<Foo>& foo) : foo_(foo) {} | |
17 // | |
18 // void OnIOStart() { | |
19 // foo_.Call(FROM_HERE, &Foo::OnIOStart); | |
20 // } | |
21 // | |
22 // void OnIOEvent(IOEvent e) { | |
23 // foo_.Call(FROM_HERE, &Foo::OnIOEvent, e); | |
24 // } | |
25 // | |
26 // void OnIOError(IOError err) { | |
27 // foo_.Call(FROM_HERE, &Foo::OnIOError, err); | |
28 // } | |
29 // | |
30 // private: | |
31 // const WeakHandle<Foo> foo_; | |
32 // }; | |
33 // | |
34 // class Foo : public SupportsWeakPtr<Foo>, public NonThreadSafe { | |
35 // public: | |
36 // Foo() { | |
37 // SpawnFooIOWorkerOnIOThread(base::MakeWeakHandle(AsWeakPtr())); | |
38 // } | |
39 // | |
40 // /* Will always be called on the correct thread, and only if this | |
41 // object hasn't been destroyed. */ | |
42 // void OnIOStart() { DCHECK(CalledOnValidThread(); ... } | |
43 // void OnIOEvent(IOEvent e) { DCHECK(CalledOnValidThread(); ... } | |
44 // void OnIOError(IOError err) { DCHECK(CalledOnValidThread(); ... } | |
45 // }; | |
46 | |
47 #ifndef SYNC_INTERNAL_API_PUBLIC_UTIL_WEAK_HANDLE_H_ | |
48 #define SYNC_INTERNAL_API_PUBLIC_UTIL_WEAK_HANDLE_H_ | |
49 | |
50 #include <cstddef> | |
51 #include <utility> | |
52 | |
53 #include "base/bind.h" | |
54 #include "base/compiler_specific.h" | |
55 #include "base/gtest_prod_util.h" | |
56 #include "base/location.h" | |
57 #include "base/logging.h" | |
58 #include "base/macros.h" | |
59 #include "base/memory/ref_counted.h" | |
60 #include "base/memory/weak_ptr.h" | |
61 #include "base/single_thread_task_runner.h" | |
62 #include "sync/base/sync_export.h" | |
63 | |
64 namespace tracked_objects { | |
65 class Location; | |
66 } // namespace tracked_objects | |
67 | |
68 namespace syncer { | |
69 | |
70 template <typename T> class WeakHandle; | |
71 | |
72 namespace internal { | |
73 // These classes are part of the WeakHandle implementation. DO NOT | |
74 // USE THESE CLASSES DIRECTLY YOURSELF. | |
75 | |
76 // Base class for WeakHandleCore<T> to avoid template bloat. Handles | |
77 // the interaction with the owner thread and its message loop. | |
78 class SYNC_EXPORT WeakHandleCoreBase { | |
79 public: | |
80 // Assumes the current thread is the owner thread. | |
81 WeakHandleCoreBase(); | |
82 | |
83 // May be called on any thread. | |
84 bool IsOnOwnerThread() const; | |
85 | |
86 protected: | |
87 // May be destroyed on any thread. | |
88 ~WeakHandleCoreBase(); | |
89 | |
90 // May be called on any thread. | |
91 void PostToOwnerThread(const tracked_objects::Location& from_here, | |
92 const base::Closure& fn) const; | |
93 | |
94 private: | |
95 // May be used on any thread. | |
96 const scoped_refptr<base::SingleThreadTaskRunner> owner_loop_task_runner_; | |
97 | |
98 DISALLOW_COPY_AND_ASSIGN(WeakHandleCoreBase); | |
99 }; | |
100 | |
101 // WeakHandleCore<T> contains all the logic for WeakHandle<T>. | |
102 template <typename T> | |
103 class WeakHandleCore | |
104 : public WeakHandleCoreBase, | |
105 public base::RefCountedThreadSafe<WeakHandleCore<T> > { | |
106 public: | |
107 // Must be called on |ptr|'s owner thread, which is assumed to be | |
108 // the current thread. | |
109 explicit WeakHandleCore(const base::WeakPtr<T>& ptr) : ptr_(ptr) {} | |
110 | |
111 // Must be called on |ptr_|'s owner thread. | |
112 base::WeakPtr<T> Get() const { | |
113 CHECK(IsOnOwnerThread()); | |
114 return ptr_; | |
115 } | |
116 | |
117 // Call(...) may be called on any thread, but all its arguments | |
118 // should be safe to be bound and copied across threads. | |
119 template <typename Method, typename... Args> | |
120 void Call(const tracked_objects::Location& from_here, | |
121 Method method, Args&&... args) const { | |
122 PostToOwnerThread( | |
123 from_here, base::Bind(method, ptr_, std::forward<Args>(args)...)); | |
124 } | |
125 | |
126 private: | |
127 friend class base::RefCountedThreadSafe<WeakHandleCore<T> >; | |
128 | |
129 // May be destroyed on any thread. | |
130 ~WeakHandleCore() {} | |
131 | |
132 // Must be dereferenced only on the owner thread. May be destroyed | |
133 // from any thread. | |
134 base::WeakPtr<T> ptr_; | |
135 | |
136 DISALLOW_COPY_AND_ASSIGN(WeakHandleCore); | |
137 }; | |
138 | |
139 } // namespace internal | |
140 | |
141 // May be destroyed on any thread. | |
142 // Copying and assignment are welcome. | |
143 template <typename T> | |
144 class WeakHandle { | |
145 public: | |
146 // Creates an uninitialized WeakHandle. | |
147 WeakHandle() {} | |
148 | |
149 // Creates an initialized WeakHandle from |ptr|. | |
150 explicit WeakHandle(const base::WeakPtr<T>& ptr) | |
151 : core_(new internal::WeakHandleCore<T>(ptr)) {} | |
152 | |
153 // Allow conversion from WeakHandle<U> to WeakHandle<T> if U is | |
154 // convertible to T, but we *must* be on |other|'s owner thread. | |
155 // Note that this doesn't override the regular copy constructor, so | |
156 // that one can be called on any thread. | |
157 template <typename U> | |
158 WeakHandle(const WeakHandle<U>& other) // NOLINT | |
159 : core_( | |
160 other.IsInitialized() ? | |
161 new internal::WeakHandleCore<T>(other.Get()) : | |
162 NULL) {} | |
163 | |
164 // Returns true iff this WeakHandle is initialized. Note that being | |
165 // initialized isn't a guarantee that the underlying object is still | |
166 // alive. | |
167 bool IsInitialized() const { | |
168 return core_.get() != NULL; | |
169 } | |
170 | |
171 // Resets to an uninitialized WeakHandle. | |
172 void Reset() { | |
173 core_ = NULL; | |
174 } | |
175 | |
176 // Must be called only on the underlying object's owner thread. | |
177 base::WeakPtr<T> Get() const { | |
178 CHECK(IsInitialized()); | |
179 CHECK(core_->IsOnOwnerThread()); | |
180 return core_->Get(); | |
181 } | |
182 | |
183 // Call(...) may be called on any thread, but all its arguments | |
184 // should be safe to be bound and copied across threads. | |
185 template <typename Method, typename... Args> | |
186 void Call(const tracked_objects::Location& from_here, | |
187 Method method, Args&&... args) const { | |
188 CHECK(IsInitialized()); | |
189 core_->Call(from_here, method, std::forward<Args>(args)...); | |
190 } | |
191 | |
192 private: | |
193 FRIEND_TEST_ALL_PREFIXES(WeakHandleTest, | |
194 TypeConversionConstructor); | |
195 FRIEND_TEST_ALL_PREFIXES(WeakHandleTest, | |
196 TypeConversionConstructorAssignment); | |
197 | |
198 scoped_refptr<internal::WeakHandleCore<T> > core_; | |
199 }; | |
200 | |
201 // Makes a WeakHandle from a WeakPtr. | |
202 template <typename T> | |
203 WeakHandle<T> MakeWeakHandle(const base::WeakPtr<T>& ptr) { | |
204 return WeakHandle<T>(ptr); | |
205 } | |
206 | |
207 } // namespace syncer | |
208 | |
209 #endif // SYNC_INTERNAL_API_PUBLIC_UTIL_WEAK_HANDLE_H_ | |
OLD | NEW |