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_UTIL_WEAK_HANDLE_H_
48#define SYNC_UTIL_WEAK_HANDLE_H_
49
50#include <cstddef>
51
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"
62
63namespace base {
64class MessageLoopProxy;
65}  // namespace base
66
67namespace tracked_objects {
68class Location;
69}  // namespace tracked_objects
70
71namespace syncer {
72
73template <typename T> class WeakHandle;
74
75namespace internal {
76// These classes are part of the WeakHandle implementation.  DO NOT
77// USE THESE CLASSES DIRECTLY YOURSELF.
78
79// Adapted from base/callback_internal.h.
80
81template <typename T>
82struct ParamTraits {
83  typedef const T& ForwardType;
84};
85
86template <typename T>
87struct ParamTraits<T&> {
88  typedef T& ForwardType;
89};
90
91template <typename T, size_t n>
92struct ParamTraits<T[n]> {
93  typedef const T* ForwardType;
94};
95
96template <typename T>
97struct ParamTraits<T[]> {
98  typedef const T* ForwardType;
99};
100
101// Base class for WeakHandleCore<T> to avoid template bloat.  Handles
102// the interaction with the owner thread and its message loop.
103class SYNC_EXPORT WeakHandleCoreBase {
104 public:
105  // Assumes the current thread is the owner thread.
106  WeakHandleCoreBase();
107
108  // May be called on any thread.
109  bool IsOnOwnerThread() const;
110
111 protected:
112  // May be destroyed on any thread.
113  ~WeakHandleCoreBase();
114
115  // May be called on any thread.
116  void PostToOwnerThread(const tracked_objects::Location& from_here,
117                         const base::Closure& fn) const;
118
119 private:
120  // May be used on any thread.
121  const scoped_refptr<base::MessageLoopProxy> owner_loop_proxy_;
122
123  DISALLOW_COPY_AND_ASSIGN(WeakHandleCoreBase);
124};
125
126// WeakHandleCore<T> contains all the logic for WeakHandle<T>.
127template <typename T>
128class WeakHandleCore
129    : public WeakHandleCoreBase,
130      public base::RefCountedThreadSafe<WeakHandleCore<T> > {
131 public:
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) {}
135
136  // Must be called on |ptr_|'s owner thread.
137  base::WeakPtr<T> Get() const {
138    CHECK(IsOnOwnerThread());
139    return ptr_;
140  }
141
142  // Call(...) may be called on any thread, but all its arguments
143  // should be safe to be bound and copied across threads.
144
145  template <typename U>
146  void Call(const tracked_objects::Location& from_here,
147            void (U::*fn)(void)) const {
148    PostToOwnerThread(
149        from_here,
150        Bind(&WeakHandleCore::template DoCall0<U>, this, fn));
151  }
152
153  template <typename U, typename A1>
154  void Call(const tracked_objects::Location& from_here,
155            void (U::*fn)(A1),
156            typename ParamTraits<A1>::ForwardType a1) const {
157    PostToOwnerThread(
158        from_here,
159        Bind(&WeakHandleCore::template DoCall1<U, A1>,
160             this, fn, a1));
161  }
162
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 {
168    PostToOwnerThread(
169        from_here,
170        Bind(&WeakHandleCore::template DoCall2<U, A1, A2>,
171             this, fn, a1, a2));
172  }
173
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 {
180    PostToOwnerThread(
181        from_here,
182        Bind(&WeakHandleCore::template DoCall3<U, A1, A2, A3>,
183             this, fn, a1, a2, a3));
184  }
185
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 {
193    PostToOwnerThread(
194        from_here,
195        Bind(&WeakHandleCore::template DoCall4<U, A1, A2, A3, A4>,
196             this, fn, a1, a2, a3, a4));
197  }
198
199 private:
200  friend class base::RefCountedThreadSafe<WeakHandleCore<T> >;
201
202  // May be destroyed on any thread.
203  ~WeakHandleCore() {}
204
205  // GCC 4.2.1 on OS X gets confused if all the DoCall functions are
206  // named the same, so we distinguish them.
207
208  template <typename U>
209  void DoCall0(void (U::*fn)(void)) const {
210    CHECK(IsOnOwnerThread());
211    if (!Get()) {
212      return;
213    }
214    (Get().get()->*fn)();
215  }
216
217  template <typename U, typename A1>
218  void DoCall1(void (U::*fn)(A1),
219               typename ParamTraits<A1>::ForwardType a1) const {
220    CHECK(IsOnOwnerThread());
221    if (!Get()) {
222      return;
223    }
224    (Get().get()->*fn)(a1);
225  }
226
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());
232    if (!Get()) {
233      return;
234    }
235    (Get().get()->*fn)(a1, a2);
236  }
237
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());
244    if (!Get()) {
245      return;
246    }
247    (Get().get()->*fn)(a1, a2, a3);
248  }
249
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());
257    if (!Get()) {
258      return;
259    }
260    (Get().get()->*fn)(a1, a2, a3, a4);
261  }
262
263  // Must be dereferenced only on the owner thread.  May be destroyed
264  // from any thread.
265  base::WeakPtr<T> ptr_;
266
267  DISALLOW_COPY_AND_ASSIGN(WeakHandleCore);
268};
269
270}  // namespace internal
271
272// May be destroyed on any thread.
273// Copying and assignment are welcome.
274template <typename T>
275class WeakHandle {
276 public:
277  // Creates an uninitialized WeakHandle.
278  WeakHandle() {}
279
280  // Creates an initialized WeakHandle from |ptr|.
281  explicit WeakHandle(const base::WeakPtr<T>& ptr)
282      : core_(new internal::WeakHandleCore<T>(ptr)) {}
283
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
290      : core_(
291          other.IsInitialized() ?
292          new internal::WeakHandleCore<T>(other.Get()) :
293          NULL) {}
294
295  // Returns true iff this WeakHandle is initialized.  Note that being
296  // initialized isn't a guarantee that the underlying object is still
297  // alive.
298  bool IsInitialized() const {
299    return core_.get() != NULL;
300  }
301
302  // Resets to an uninitialized WeakHandle.
303  void Reset() {
304    core_ = NULL;
305  }
306
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());
311    return core_->Get();
312  }
313
314  // Call(...) may be called on any thread, but all its arguments
315  // should be safe to be bound and copied across threads.
316
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);
322  }
323
324  template <typename U, typename A1>
325  void Call(const tracked_objects::Location& from_here,
326            void (U::*fn)(A1),
327            typename internal::ParamTraits<A1>::ForwardType a1) const {
328    CHECK(IsInitialized());
329    core_->Call(from_here, fn, a1);
330  }
331
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);
339  }
340
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);
349  }
350
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);
360  }
361
362 private:
363  FRIEND_TEST_ALL_PREFIXES(WeakHandleTest,
364                           TypeConversionConstructor);
365  FRIEND_TEST_ALL_PREFIXES(WeakHandleTest,
366                           TypeConversionConstructorAssignment);
367
368  scoped_refptr<internal::WeakHandleCore<T> > core_;
369};
370
371// Makes a WeakHandle from a WeakPtr.
372template <typename T>
373WeakHandle<T> MakeWeakHandle(const base::WeakPtr<T>& ptr) {
374  return WeakHandle<T>(ptr);
375}
376
377}  // namespace syncer
378
379#endif  // SYNC_UTIL_WEAK_HANDLE_H_
380