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 "sync/base/sync_export.h"
64 class MessageLoopProxy
;
67 namespace tracked_objects
{
69 } // namespace tracked_objects
73 template <typename T
> class WeakHandle
;
76 // These classes are part of the WeakHandle implementation. DO NOT
77 // USE THESE CLASSES DIRECTLY YOURSELF.
79 // Adapted from base/callback_internal.h.
83 typedef const T
& ForwardType
;
87 struct ParamTraits
<T
&> {
88 typedef T
& ForwardType
;
91 template <typename T
, size_t n
>
92 struct ParamTraits
<T
[n
]> {
93 typedef const T
* ForwardType
;
97 struct ParamTraits
<T
[]> {
98 typedef const T
* ForwardType
;
101 // Base class for WeakHandleCore<T> to avoid template bloat. Handles
102 // the interaction with the owner thread and its message loop.
103 class SYNC_EXPORT WeakHandleCoreBase
{
105 // Assumes the current thread is the owner thread.
106 WeakHandleCoreBase();
108 // May be called on any thread.
109 bool IsOnOwnerThread() const;
112 // May be destroyed on any thread.
113 ~WeakHandleCoreBase();
115 // May be called on any thread.
116 void PostToOwnerThread(const tracked_objects::Location
& from_here
,
117 const base::Closure
& fn
) const;
120 // May be used on any thread.
121 const scoped_refptr
<base::MessageLoopProxy
> owner_loop_proxy_
;
123 DISALLOW_COPY_AND_ASSIGN(WeakHandleCoreBase
);
126 // WeakHandleCore<T> contains all the logic for WeakHandle<T>.
127 template <typename T
>
129 : public WeakHandleCoreBase
,
130 public base::RefCountedThreadSafe
<WeakHandleCore
<T
> > {
132 // Must be called on |ptr|'s owner thread, which is assumed to be
133 // the current thread.
134 explicit WeakHandleCore(const base::WeakPtr
<T
>& ptr
) : ptr_(ptr
) {}
136 // Must be called on |ptr_|'s owner thread.
137 base::WeakPtr
<T
> Get() const {
138 CHECK(IsOnOwnerThread());
142 // Call(...) may be called on any thread, but all its arguments
143 // should be safe to be bound and copied across threads.
145 template <typename U
>
146 void Call(const tracked_objects::Location
& from_here
,
147 void (U::*fn
)(void)) const {
150 Bind(&WeakHandleCore::template DoCall0
<U
>, this, fn
));
153 template <typename U
, typename A1
>
154 void Call(const tracked_objects::Location
& from_here
,
156 typename ParamTraits
<A1
>::ForwardType a1
) const {
159 Bind(&WeakHandleCore::template DoCall1
<U
, A1
>,
163 template <typename U
, typename A1
, typename A2
>
164 void Call(const tracked_objects::Location
& from_here
,
165 void (U::*fn
)(A1
, A2
),
166 typename ParamTraits
<A1
>::ForwardType a1
,
167 typename ParamTraits
<A2
>::ForwardType a2
) const {
170 Bind(&WeakHandleCore::template DoCall2
<U
, A1
, A2
>,
174 template <typename U
, typename A1
, typename A2
, typename A3
>
175 void Call(const tracked_objects::Location
& from_here
,
176 void (U::*fn
)(A1
, A2
, A3
),
177 typename ParamTraits
<A1
>::ForwardType a1
,
178 typename ParamTraits
<A2
>::ForwardType a2
,
179 typename ParamTraits
<A3
>::ForwardType a3
) const {
182 Bind(&WeakHandleCore::template DoCall3
<U
, A1
, A2
, A3
>,
183 this, fn
, a1
, a2
, a3
));
186 template <typename U
, typename A1
, typename A2
, typename A3
, typename A4
>
187 void Call(const tracked_objects::Location
& from_here
,
188 void (U::*fn
)(A1
, A2
, A3
, A4
),
189 typename ParamTraits
<A1
>::ForwardType a1
,
190 typename ParamTraits
<A2
>::ForwardType a2
,
191 typename ParamTraits
<A3
>::ForwardType a3
,
192 typename ParamTraits
<A4
>::ForwardType a4
) const {
195 Bind(&WeakHandleCore::template DoCall4
<U
, A1
, A2
, A3
, A4
>,
196 this, fn
, a1
, a2
, a3
, a4
));
200 friend class base::RefCountedThreadSafe
<WeakHandleCore
<T
> >;
202 // May be destroyed on any thread.
205 // GCC 4.2.1 on OS X gets confused if all the DoCall functions are
206 // named the same, so we distinguish them.
208 template <typename U
>
209 void DoCall0(void (U::*fn
)(void)) const {
210 CHECK(IsOnOwnerThread());
214 (Get().get()->*fn
)();
217 template <typename U
, typename A1
>
218 void DoCall1(void (U::*fn
)(A1
),
219 typename ParamTraits
<A1
>::ForwardType a1
) const {
220 CHECK(IsOnOwnerThread());
224 (Get().get()->*fn
)(a1
);
227 template <typename U
, typename A1
, typename A2
>
228 void DoCall2(void (U::*fn
)(A1
, A2
),
229 typename ParamTraits
<A1
>::ForwardType a1
,
230 typename ParamTraits
<A2
>::ForwardType a2
) const {
231 CHECK(IsOnOwnerThread());
235 (Get().get()->*fn
)(a1
, a2
);
238 template <typename U
, typename A1
, typename A2
, typename A3
>
239 void DoCall3(void (U::*fn
)(A1
, A2
, A3
),
240 typename ParamTraits
<A1
>::ForwardType a1
,
241 typename ParamTraits
<A2
>::ForwardType a2
,
242 typename ParamTraits
<A3
>::ForwardType a3
) const {
243 CHECK(IsOnOwnerThread());
247 (Get().get()->*fn
)(a1
, a2
, a3
);
250 template <typename U
, typename A1
, typename A2
, typename A3
, typename A4
>
251 void DoCall4(void (U::*fn
)(A1
, A2
, A3
, A4
),
252 typename ParamTraits
<A1
>::ForwardType a1
,
253 typename ParamTraits
<A2
>::ForwardType a2
,
254 typename ParamTraits
<A3
>::ForwardType a3
,
255 typename ParamTraits
<A4
>::ForwardType a4
) const {
256 CHECK(IsOnOwnerThread());
260 (Get().get()->*fn
)(a1
, a2
, a3
, a4
);
263 // Must be dereferenced only on the owner thread. May be destroyed
265 base::WeakPtr
<T
> ptr_
;
267 DISALLOW_COPY_AND_ASSIGN(WeakHandleCore
);
270 } // namespace internal
272 // May be destroyed on any thread.
273 // Copying and assignment are welcome.
274 template <typename T
>
277 // Creates an uninitialized WeakHandle.
280 // Creates an initialized WeakHandle from |ptr|.
281 explicit WeakHandle(const base::WeakPtr
<T
>& ptr
)
282 : core_(new internal::WeakHandleCore
<T
>(ptr
)) {}
284 // Allow conversion from WeakHandle<U> to WeakHandle<T> if U is
285 // convertible to T, but we *must* be on |other|'s owner thread.
286 // Note that this doesn't override the regular copy constructor, so
287 // that one can be called on any thread.
288 template <typename U
>
289 WeakHandle(const WeakHandle
<U
>& other
) // NOLINT
291 other
.IsInitialized() ?
292 new internal::WeakHandleCore
<T
>(other
.Get()) :
295 // Returns true iff this WeakHandle is initialized. Note that being
296 // initialized isn't a guarantee that the underlying object is still
298 bool IsInitialized() const {
299 return core_
.get() != NULL
;
302 // Resets to an uninitialized WeakHandle.
307 // Must be called only on the underlying object's owner thread.
308 base::WeakPtr
<T
> Get() const {
309 CHECK(IsInitialized());
310 CHECK(core_
->IsOnOwnerThread());
314 // Call(...) may be called on any thread, but all its arguments
315 // should be safe to be bound and copied across threads.
317 template <typename U
>
318 void Call(const tracked_objects::Location
& from_here
,
319 void (U::*fn
)(void)) const {
320 CHECK(IsInitialized());
321 core_
->Call(from_here
, fn
);
324 template <typename U
, typename A1
>
325 void Call(const tracked_objects::Location
& from_here
,
327 typename
internal::ParamTraits
<A1
>::ForwardType a1
) const {
328 CHECK(IsInitialized());
329 core_
->Call(from_here
, fn
, a1
);
332 template <typename U
, typename A1
, typename A2
>
333 void Call(const tracked_objects::Location
& from_here
,
334 void (U::*fn
)(A1
, A2
),
335 typename
internal::ParamTraits
<A1
>::ForwardType a1
,
336 typename
internal::ParamTraits
<A2
>::ForwardType a2
) const {
337 CHECK(IsInitialized());
338 core_
->Call(from_here
, fn
, a1
, a2
);
341 template <typename U
, typename A1
, typename A2
, typename A3
>
342 void Call(const tracked_objects::Location
& from_here
,
343 void (U::*fn
)(A1
, A2
, A3
),
344 typename
internal::ParamTraits
<A1
>::ForwardType a1
,
345 typename
internal::ParamTraits
<A2
>::ForwardType a2
,
346 typename
internal::ParamTraits
<A3
>::ForwardType a3
) const {
347 CHECK(IsInitialized());
348 core_
->Call(from_here
, fn
, a1
, a2
, a3
);
351 template <typename U
, typename A1
, typename A2
, typename A3
, typename A4
>
352 void Call(const tracked_objects::Location
& from_here
,
353 void (U::*fn
)(A1
, A2
, A3
, A4
),
354 typename
internal::ParamTraits
<A1
>::ForwardType a1
,
355 typename
internal::ParamTraits
<A2
>::ForwardType a2
,
356 typename
internal::ParamTraits
<A3
>::ForwardType a3
,
357 typename
internal::ParamTraits
<A4
>::ForwardType a4
) const {
358 CHECK(IsInitialized());
359 core_
->Call(from_here
, fn
, a1
, a2
, a3
, a4
);
363 FRIEND_TEST_ALL_PREFIXES(WeakHandleTest
,
364 TypeConversionConstructor
);
365 FRIEND_TEST_ALL_PREFIXES(WeakHandleTest
,
366 TypeConversionConstructorAssignment
);
368 scoped_refptr
<internal::WeakHandleCore
<T
> > core_
;
371 // Makes a WeakHandle from a WeakPtr.
372 template <typename T
>
373 WeakHandle
<T
> MakeWeakHandle(const base::WeakPtr
<T
>& ptr
) {
374 return WeakHandle
<T
>(ptr
);
377 } // namespace syncer
379 #endif // SYNC_UTIL_WEAK_HANDLE_H_