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
18namespace invalidation {
19
20typedef ::base::Closure Closure;
21
22template <class T>
23bool 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
30namespace 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.
34template <typename T>
35struct 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
46inline Closure* NewPermanentCallback(void (*fn)()) {
47  return new ::base::Closure(::base::Bind(fn));
48}
49
50template <class T1, class T2>
51Closure* NewPermanentCallback(
52    T1* object, void (T2::*method)()) {
53  return new ::base::Closure(::base::Bind(method, base::Unretained(object)));
54}
55
56template <class T1, class T2, typename 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
63template <class T1, class T2, typename Arg1>
64Closure* 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
72template <typename Arg1, typename Arg2>
73Closure* 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
80template <class T1, class T2, typename Arg1, typename Arg2>
81Closure* 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
90template <class T1, class T2, typename Arg1, typename Arg2>
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
99template <class T1, class T2, typename Arg1, typename Arg2, typename Arg3>
100Closure* 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
110template <class T1, class T2, typename Arg1, typename Arg2, typename Arg3,
111          typename Arg4>
112Closure* 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|.
125template <typename ArgType>
126Closure* 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