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.
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
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
14 // class FooIOWorker {
16 // FooIOWorker(const WeakHandle<Foo>& foo) : foo_(foo) {}
19 // foo_.Call(FROM_HERE, &Foo::OnIOStart);
22 // void OnIOEvent(IOEvent e) {
23 // foo_.Call(FROM_HERE, &Foo::OnIOEvent, e);
26 // void OnIOError(IOError err) {
27 // foo_.Call(FROM_HERE, &Foo::OnIOError, err);
31 // const WeakHandle<Foo> foo_;
34 // class Foo : public SupportsWeakPtr<Foo>, public NonThreadSafe {
37 // SpawnFooIOWorkerOnIOThread(base::MakeWeakHandle(AsWeakPtr()));
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(); ... }
47 #ifndef SYNC_UTIL_WEAK_HANDLE_H_
48 #define SYNC_UTIL_WEAK_HANDLE_H_
52 #include "base/basictypes.h"
53 #include "base/bind.h"
54 #include "base/callback_forward.h"
55 #include "base/compiler_specific.h"
56 #include "base/gtest_prod_util.h"
57 #include "base/location.h"
58 #include "base/logging.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"
64 namespace tracked_objects
{
66 } // namespace tracked_objects
70 template <typename T
> class WeakHandle
;
73 // These classes are part of the WeakHandle implementation. DO NOT
74 // USE THESE CLASSES DIRECTLY YOURSELF.
76 // Adapted from base/callback_internal.h.
80 typedef const T
& ForwardType
;
84 struct ParamTraits
<T
&> {
85 typedef T
& ForwardType
;
88 template <typename T
, size_t n
>
89 struct ParamTraits
<T
[n
]> {
90 typedef const T
* ForwardType
;
94 struct ParamTraits
<T
[]> {
95 typedef const T
* ForwardType
;
98 // Base class for WeakHandleCore<T> to avoid template bloat. Handles
99 // the interaction with the owner thread and its message loop.
100 class SYNC_EXPORT WeakHandleCoreBase
{
102 // Assumes the current thread is the owner thread.
103 WeakHandleCoreBase();
105 // May be called on any thread.
106 bool IsOnOwnerThread() const;
109 // May be destroyed on any thread.
110 ~WeakHandleCoreBase();
112 // May be called on any thread.
113 void PostToOwnerThread(const tracked_objects::Location
& from_here
,
114 const base::Closure
& fn
) const;
117 // May be used on any thread.
118 const scoped_refptr
<base::SingleThreadTaskRunner
> owner_loop_task_runner_
;
120 DISALLOW_COPY_AND_ASSIGN(WeakHandleCoreBase
);
123 // WeakHandleCore<T> contains all the logic for WeakHandle<T>.
124 template <typename T
>
126 : public WeakHandleCoreBase
,
127 public base::RefCountedThreadSafe
<WeakHandleCore
<T
> > {
129 // Must be called on |ptr|'s owner thread, which is assumed to be
130 // the current thread.
131 explicit WeakHandleCore(const base::WeakPtr
<T
>& ptr
) : ptr_(ptr
) {}
133 // Must be called on |ptr_|'s owner thread.
134 base::WeakPtr
<T
> Get() const {
135 CHECK(IsOnOwnerThread());
139 // Call(...) may be called on any thread, but all its arguments
140 // should be safe to be bound and copied across threads.
142 template <typename U
>
143 void Call(const tracked_objects::Location
& from_here
,
144 void (U::*fn
)(void)) const {
147 Bind(&WeakHandleCore::template DoCall0
<U
>, this, fn
));
150 template <typename U
, typename A1
>
151 void Call(const tracked_objects::Location
& from_here
,
153 typename ParamTraits
<A1
>::ForwardType a1
) const {
156 Bind(&WeakHandleCore::template DoCall1
<U
, A1
>,
160 template <typename U
, typename A1
, typename A2
>
161 void Call(const tracked_objects::Location
& from_here
,
162 void (U::*fn
)(A1
, A2
),
163 typename ParamTraits
<A1
>::ForwardType a1
,
164 typename ParamTraits
<A2
>::ForwardType a2
) const {
167 Bind(&WeakHandleCore::template DoCall2
<U
, A1
, A2
>,
171 template <typename U
, typename A1
, typename A2
, typename A3
>
172 void Call(const tracked_objects::Location
& from_here
,
173 void (U::*fn
)(A1
, A2
, A3
),
174 typename ParamTraits
<A1
>::ForwardType a1
,
175 typename ParamTraits
<A2
>::ForwardType a2
,
176 typename ParamTraits
<A3
>::ForwardType a3
) const {
179 Bind(&WeakHandleCore::template DoCall3
<U
, A1
, A2
, A3
>,
180 this, fn
, a1
, a2
, a3
));
183 template <typename U
, typename A1
, typename A2
, typename A3
, typename A4
>
184 void Call(const tracked_objects::Location
& from_here
,
185 void (U::*fn
)(A1
, A2
, A3
, A4
),
186 typename ParamTraits
<A1
>::ForwardType a1
,
187 typename ParamTraits
<A2
>::ForwardType a2
,
188 typename ParamTraits
<A3
>::ForwardType a3
,
189 typename ParamTraits
<A4
>::ForwardType a4
) const {
192 Bind(&WeakHandleCore::template DoCall4
<U
, A1
, A2
, A3
, A4
>,
193 this, fn
, a1
, a2
, a3
, a4
));
197 friend class base::RefCountedThreadSafe
<WeakHandleCore
<T
> >;
199 // May be destroyed on any thread.
202 // GCC 4.2.1 on OS X gets confused if all the DoCall functions are
203 // named the same, so we distinguish them.
205 template <typename U
>
206 void DoCall0(void (U::*fn
)(void)) const {
207 CHECK(IsOnOwnerThread());
211 (Get().get()->*fn
)();
214 template <typename U
, typename A1
>
215 void DoCall1(void (U::*fn
)(A1
),
216 typename ParamTraits
<A1
>::ForwardType a1
) const {
217 CHECK(IsOnOwnerThread());
221 (Get().get()->*fn
)(a1
);
224 template <typename U
, typename A1
, typename A2
>
225 void DoCall2(void (U::*fn
)(A1
, A2
),
226 typename ParamTraits
<A1
>::ForwardType a1
,
227 typename ParamTraits
<A2
>::ForwardType a2
) const {
228 CHECK(IsOnOwnerThread());
232 (Get().get()->*fn
)(a1
, a2
);
235 template <typename U
, typename A1
, typename A2
, typename A3
>
236 void DoCall3(void (U::*fn
)(A1
, A2
, A3
),
237 typename ParamTraits
<A1
>::ForwardType a1
,
238 typename ParamTraits
<A2
>::ForwardType a2
,
239 typename ParamTraits
<A3
>::ForwardType a3
) const {
240 CHECK(IsOnOwnerThread());
244 (Get().get()->*fn
)(a1
, a2
, a3
);
247 template <typename U
, typename A1
, typename A2
, typename A3
, typename A4
>
248 void DoCall4(void (U::*fn
)(A1
, A2
, A3
, A4
),
249 typename ParamTraits
<A1
>::ForwardType a1
,
250 typename ParamTraits
<A2
>::ForwardType a2
,
251 typename ParamTraits
<A3
>::ForwardType a3
,
252 typename ParamTraits
<A4
>::ForwardType a4
) const {
253 CHECK(IsOnOwnerThread());
257 (Get().get()->*fn
)(a1
, a2
, a3
, a4
);
260 // Must be dereferenced only on the owner thread. May be destroyed
262 base::WeakPtr
<T
> ptr_
;
264 DISALLOW_COPY_AND_ASSIGN(WeakHandleCore
);
267 } // namespace internal
269 // May be destroyed on any thread.
270 // Copying and assignment are welcome.
271 template <typename T
>
274 // Creates an uninitialized WeakHandle.
277 // Creates an initialized WeakHandle from |ptr|.
278 explicit WeakHandle(const base::WeakPtr
<T
>& ptr
)
279 : core_(new internal::WeakHandleCore
<T
>(ptr
)) {}
281 // Allow conversion from WeakHandle<U> to WeakHandle<T> if U is
282 // convertible to T, but we *must* be on |other|'s owner thread.
283 // Note that this doesn't override the regular copy constructor, so
284 // that one can be called on any thread.
285 template <typename U
>
286 WeakHandle(const WeakHandle
<U
>& other
) // NOLINT
288 other
.IsInitialized() ?
289 new internal::WeakHandleCore
<T
>(other
.Get()) :
292 // Returns true iff this WeakHandle is initialized. Note that being
293 // initialized isn't a guarantee that the underlying object is still
295 bool IsInitialized() const {
296 return core_
.get() != NULL
;
299 // Resets to an uninitialized WeakHandle.
304 // Must be called only on the underlying object's owner thread.
305 base::WeakPtr
<T
> Get() const {
306 CHECK(IsInitialized());
307 CHECK(core_
->IsOnOwnerThread());
311 // Call(...) may be called on any thread, but all its arguments
312 // should be safe to be bound and copied across threads.
314 template <typename U
>
315 void Call(const tracked_objects::Location
& from_here
,
316 void (U::*fn
)(void)) const {
317 CHECK(IsInitialized());
318 core_
->Call(from_here
, fn
);
321 template <typename U
, typename A1
>
322 void Call(const tracked_objects::Location
& from_here
,
324 typename
internal::ParamTraits
<A1
>::ForwardType a1
) const {
325 CHECK(IsInitialized());
326 core_
->Call(from_here
, fn
, a1
);
329 template <typename U
, typename A1
, typename A2
>
330 void Call(const tracked_objects::Location
& from_here
,
331 void (U::*fn
)(A1
, A2
),
332 typename
internal::ParamTraits
<A1
>::ForwardType a1
,
333 typename
internal::ParamTraits
<A2
>::ForwardType a2
) const {
334 CHECK(IsInitialized());
335 core_
->Call(from_here
, fn
, a1
, a2
);
338 template <typename U
, typename A1
, typename A2
, typename A3
>
339 void Call(const tracked_objects::Location
& from_here
,
340 void (U::*fn
)(A1
, A2
, A3
),
341 typename
internal::ParamTraits
<A1
>::ForwardType a1
,
342 typename
internal::ParamTraits
<A2
>::ForwardType a2
,
343 typename
internal::ParamTraits
<A3
>::ForwardType a3
) const {
344 CHECK(IsInitialized());
345 core_
->Call(from_here
, fn
, a1
, a2
, a3
);
348 template <typename U
, typename A1
, typename A2
, typename A3
, typename A4
>
349 void Call(const tracked_objects::Location
& from_here
,
350 void (U::*fn
)(A1
, A2
, A3
, A4
),
351 typename
internal::ParamTraits
<A1
>::ForwardType a1
,
352 typename
internal::ParamTraits
<A2
>::ForwardType a2
,
353 typename
internal::ParamTraits
<A3
>::ForwardType a3
,
354 typename
internal::ParamTraits
<A4
>::ForwardType a4
) const {
355 CHECK(IsInitialized());
356 core_
->Call(from_here
, fn
, a1
, a2
, a3
, a4
);
360 FRIEND_TEST_ALL_PREFIXES(WeakHandleTest
,
361 TypeConversionConstructor
);
362 FRIEND_TEST_ALL_PREFIXES(WeakHandleTest
,
363 TypeConversionConstructorAssignment
);
365 scoped_refptr
<internal::WeakHandleCore
<T
> > core_
;
368 // Makes a WeakHandle from a WeakPtr.
369 template <typename T
>
370 WeakHandle
<T
> MakeWeakHandle(const base::WeakPtr
<T
>& ptr
) {
371 return WeakHandle
<T
>(ptr
);
374 } // namespace syncer
376 #endif // SYNC_UTIL_WEAK_HANDLE_H_