1 // Copyright (c) 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 #ifndef GOOGLE_CACHEINVALIDATION_DEPS_CALLBACK_H_
6 #define GOOGLE_CACHEINVALIDATION_DEPS_CALLBACK_H_
7
8 #include "base/bind.h"
9 #include "base/bind_helpers.h"
10 #include "base/callback.h"
11
12 #define INVALIDATION_CALLBACK1_TYPE(Arg1) ::base::Callback<void(Arg1)>
13
14 // Below are a collection of types and functions that adapt base::Callback's
15 // pass-by-value semantics to the pointer-based callback system that
16 // cacheinvalidation needs.
17
18 namespace invalidation {
19
20 typedef ::base::Closure Closure;
21
22 template <class T>
IsCallbackRepeatable(const T * callback)23 bool IsCallbackRepeatable(const T* callback) {
24 // The default cacheinvalidation Callbacks may be self-deleting. We don't
25 // support this behave, so we already return true to indicate that the
26 // cacheinvalidation implementation should delete our Callbacks.
27 return true;
28 }
29
30 namespace internal {
31
32 // Identity<T>::type is a typedef of T. Useful for preventing the
33 // compiler from inferring the type of an argument in templates.
34 template <typename T>
35 struct Identity {
36 typedef T type;
37 };
38
39 } // namespace internal
40
41 // The cacheinvalidation callback system expects to take the callback by
42 // pointer and handle the ownership semantics itself. Adapting the
43 // Chromium Callback system requires returning a dynamically allocated
44 // copy of the result of Bind().
45
NewPermanentCallback(void (* fn)())46 inline Closure* NewPermanentCallback(void (*fn)()) {
47 return new ::base::Closure(::base::Bind(fn));
48 }
49
50 template <class T1, class T2>
NewPermanentCallback(T1 * object,void (T2::* method)())51 Closure* NewPermanentCallback(
52 T1* object, void (T2::*method)()) {
53 return new ::base::Closure(::base::Bind(method, base::Unretained(object)));
54 }
55
56 template <class T1, class T2, typename Arg1>
NewPermanentCallback(T1 * object,void (T2::* method)(Arg1))57 ::base::Callback<void(Arg1)>* NewPermanentCallback(
58 T1* object, void (T2::*method)(Arg1)) {
59 return new ::base::Callback<void(Arg1)>(
60 ::base::Bind(method, base::Unretained(object)));
61 }
62
63 template <class T1, class T2, typename Arg1>
NewPermanentCallback(T1 * object,void (T2::* method)(Arg1),typename internal::Identity<Arg1>::type arg1)64 Closure* NewPermanentCallback(
65 T1* object,
66 void (T2::*method)(Arg1),
67 typename internal::Identity<Arg1>::type arg1) {
68 return new ::base::Closure(::base::Bind(method, base::Unretained(object),
69 arg1));
70 }
71
72 template <typename Arg1, typename Arg2>
NewPermanentCallback(void (* fn)(Arg1,Arg2),typename internal::Identity<Arg1>::type arg1,typename internal::Identity<Arg2>::type arg2)73 Closure* NewPermanentCallback(
74 void (*fn)(Arg1, Arg2),
75 typename internal::Identity<Arg1>::type arg1,
76 typename internal::Identity<Arg2>::type arg2) {
77 return new ::base::Closure(::base::Bind(fn, arg1, arg2));
78 }
79
80 template <class T1, class T2, typename Arg1, typename Arg2>
NewPermanentCallback(T1 * object,void (T2::* method)(Arg1,Arg2),typename internal::Identity<Arg1>::type arg1,typename internal::Identity<Arg2>::type arg2)81 Closure* NewPermanentCallback(
82 T1* object,
83 void (T2::*method)(Arg1, Arg2),
84 typename internal::Identity<Arg1>::type arg1,
85 typename internal::Identity<Arg2>::type arg2) {
86 return new ::base::Closure(::base::Bind(method, base::Unretained(object),
87 arg1, arg2));
88 }
89
90 template <class T1, class T2, typename Arg1, typename Arg2>
NewPermanentCallback(T1 * object,void (T2::* method)(Arg1,Arg2),typename internal::Identity<Arg1>::type arg1)91 ::base::Callback<void(Arg2)>* NewPermanentCallback(
92 T1* object,
93 void (T2::*method)(Arg1, Arg2),
94 typename internal::Identity<Arg1>::type arg1) {
95 return new ::base::Callback<void(Arg2)>(
96 ::base::Bind(method, base::Unretained(object), arg1));
97 }
98
99 template <class T1, class T2, typename Arg1, typename Arg2, typename Arg3>
NewPermanentCallback(T1 * object,void (T2::* method)(Arg1,Arg2,Arg3),typename internal::Identity<Arg1>::type arg1,typename internal::Identity<Arg2>::type arg2,typename internal::Identity<Arg3>::type arg3)100 Closure* NewPermanentCallback(
101 T1* object,
102 void (T2::*method)(Arg1, Arg2, Arg3),
103 typename internal::Identity<Arg1>::type arg1,
104 typename internal::Identity<Arg2>::type arg2,
105 typename internal::Identity<Arg3>::type arg3) {
106 return new ::base::Closure(::base::Bind(method, base::Unretained(object),
107 arg1, arg2, arg3));
108 }
109
110 template <class T1, class T2, typename Arg1, typename Arg2, typename Arg3,
111 typename Arg4>
NewPermanentCallback(T1 * object,void (T2::* method)(Arg1,Arg2,Arg3,Arg4),typename internal::Identity<Arg1>::type arg1,typename internal::Identity<Arg2>::type arg2,typename internal::Identity<Arg3>::type arg3,typename internal::Identity<Arg4>::type arg4)112 Closure* NewPermanentCallback(
113 T1* object,
114 void (T2::*method)(Arg1, Arg2, Arg3, Arg4),
115 typename internal::Identity<Arg1>::type arg1,
116 typename internal::Identity<Arg2>::type arg2,
117 typename internal::Identity<Arg3>::type arg3,
118 typename internal::Identity<Arg4>::type arg4) {
119 return new ::base::Closure(::base::Bind(method, base::Unretained(object),
120 arg1, arg2, arg3, arg4));
121 }
122
123 // Creates a Closure that runs |callback| on |arg|. The returned Closure owns
124 // |callback|.
125 template <typename ArgType>
NewPermanentCallback(INVALIDATION_CALLBACK1_TYPE (ArgType)* callback,typename internal::Identity<ArgType>::type arg)126 Closure* NewPermanentCallback(
127 INVALIDATION_CALLBACK1_TYPE(ArgType)* callback,
128 typename internal::Identity<ArgType>::type arg) {
129 return new ::base::Closure(::base::Bind(
130 &::base::Callback<void(ArgType)>::Run, base::Owned(callback), arg));
131 }
132
133 } // namespace invalidation
134
135 #endif // GOOGLE_CACHEINVALIDATION_DEPS_CALLBACK_H_
136