Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / sync / internal_api / public / util / weak_handle.h
blob7a11a156536f2ae158248b8800b58cf7d56b95ae
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
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:
14 // class FooIOWorker {
15 // public:
16 // FooIOWorker(const WeakHandle<Foo>& foo) : foo_(foo) {}
18 // void OnIOStart() {
19 // foo_.Call(FROM_HERE, &Foo::OnIOStart);
20 // }
22 // void OnIOEvent(IOEvent e) {
23 // foo_.Call(FROM_HERE, &Foo::OnIOEvent, e);
24 // }
26 // void OnIOError(IOError err) {
27 // foo_.Call(FROM_HERE, &Foo::OnIOError, err);
28 // }
30 // private:
31 // const WeakHandle<Foo> foo_;
32 // };
34 // class Foo : public SupportsWeakPtr<Foo>, public NonThreadSafe {
35 // public:
36 // Foo() {
37 // SpawnFooIOWorkerOnIOThread(base::MakeWeakHandle(AsWeakPtr()));
38 // }
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 // };
47 #ifndef SYNC_UTIL_WEAK_HANDLE_H_
48 #define SYNC_UTIL_WEAK_HANDLE_H_
50 #include <cstddef>
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 {
65 class Location;
66 } // namespace tracked_objects
68 namespace syncer {
70 template <typename T> class WeakHandle;
72 namespace internal {
73 // These classes are part of the WeakHandle implementation. DO NOT
74 // USE THESE CLASSES DIRECTLY YOURSELF.
76 // Adapted from base/callback_internal.h.
78 template <typename T>
79 struct ParamTraits {
80 typedef const T& ForwardType;
83 template <typename T>
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;
93 template <typename T>
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 {
101 public:
102 // Assumes the current thread is the owner thread.
103 WeakHandleCoreBase();
105 // May be called on any thread.
106 bool IsOnOwnerThread() const;
108 protected:
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;
116 private:
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>
125 class WeakHandleCore
126 : public WeakHandleCoreBase,
127 public base::RefCountedThreadSafe<WeakHandleCore<T> > {
128 public:
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());
136 return ptr_;
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 {
145 PostToOwnerThread(
146 from_here,
147 Bind(&WeakHandleCore::template DoCall0<U>, this, fn));
150 template <typename U, typename A1>
151 void Call(const tracked_objects::Location& from_here,
152 void (U::*fn)(A1),
153 typename ParamTraits<A1>::ForwardType a1) const {
154 PostToOwnerThread(
155 from_here,
156 Bind(&WeakHandleCore::template DoCall1<U, A1>,
157 this, fn, 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 {
165 PostToOwnerThread(
166 from_here,
167 Bind(&WeakHandleCore::template DoCall2<U, A1, A2>,
168 this, fn, 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 {
177 PostToOwnerThread(
178 from_here,
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 {
190 PostToOwnerThread(
191 from_here,
192 Bind(&WeakHandleCore::template DoCall4<U, A1, A2, A3, A4>,
193 this, fn, a1, a2, a3, a4));
196 private:
197 friend class base::RefCountedThreadSafe<WeakHandleCore<T> >;
199 // May be destroyed on any thread.
200 ~WeakHandleCore() {}
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());
208 if (!Get()) {
209 return;
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());
218 if (!Get()) {
219 return;
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());
229 if (!Get()) {
230 return;
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());
241 if (!Get()) {
242 return;
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());
254 if (!Get()) {
255 return;
257 (Get().get()->*fn)(a1, a2, a3, a4);
260 // Must be dereferenced only on the owner thread. May be destroyed
261 // from any thread.
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>
272 class WeakHandle {
273 public:
274 // Creates an uninitialized WeakHandle.
275 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
287 : core_(
288 other.IsInitialized() ?
289 new internal::WeakHandleCore<T>(other.Get()) :
290 NULL) {}
292 // Returns true iff this WeakHandle is initialized. Note that being
293 // initialized isn't a guarantee that the underlying object is still
294 // alive.
295 bool IsInitialized() const {
296 return core_.get() != NULL;
299 // Resets to an uninitialized WeakHandle.
300 void Reset() {
301 core_ = NULL;
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());
308 return core_->Get();
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,
323 void (U::*fn)(A1),
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);
359 private:
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_