- add sources.
[platform/framework/web/crosswalk.git] / src / sync / internal_api / public / util / weak_handle.h
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
63 namespace base {
64 class MessageLoopProxy;
65 }  // namespace base
66
67 namespace tracked_objects {
68 class Location;
69 }  // namespace tracked_objects
70
71 namespace syncer {
72
73 template <typename T> class WeakHandle;
74
75 namespace 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
81 template <typename T>
82 struct ParamTraits {
83   typedef const T& ForwardType;
84 };
85
86 template <typename T>
87 struct ParamTraits<T&> {
88   typedef T& ForwardType;
89 };
90
91 template <typename T, size_t n>
92 struct ParamTraits<T[n]> {
93   typedef const T* ForwardType;
94 };
95
96 template <typename T>
97 struct 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.
103 class 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>.
127 template <typename T>
128 class 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.
274 template <typename T>
275 class 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.
372 template <typename T>
373 WeakHandle<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_