Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1155)

Side by Side Diff: base/prebind.h

Issue 6094005: Create "Prebind" a wrapper to tr1::bind. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/base
Patch Set: Closure example ported to Prebinds Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2009 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 BASE_PREBIND_H
6 #define BASE_PREBIND_H
7
8 #include <tr1/functional>
9
10 #include <base/ref_counted.h>
11 #include <base/closure.h> // For UnretainedWrapper
12 #include <base/tracked.h>
13
14 namespace base {
15
16 class ThunkState : public RefCountedThreadSafe<ThunkState> {
17 public:
18 tracked_objects::Tracked tracked_;
willchan no longer on Chromium 2011/01/05 00:59:01 Similar comment as I made on the ClosureState thin
awong 2011/01/05 03:17:42 Okay, I whacked it for now.
19
20 // If we used a list here, we'd have really nice resource management.
21 ::std::tr1::function<void(void)> cleanup_;
22
23 template <typename T>
24 void RetainObject(T* obj) {
25 obj->AddRef();
26 cleanup_ = ::std::tr1::bind(&T::Release, obj);
27 }
28 };
29
30 template <typename O>
31 struct RetainTraits;
32
33 template <typename O>
34 struct RetainTraits<O*> {
35 typedef O type;
36 static O* unwrap(O* o) { return o; }
37 static void RetainObject(ThunkState* state, O* o) {
38 state->RetainObject(o);
39 }
40 };
41
42 template <typename O>
43 struct RetainTraits<UnretainedWrapper<O> > {
44 typedef O type;
45 static O* unwrap(const UnretainedWrapper<O>& o) { return o.get(); }
46 static void RetainObject(ThunkState* state, O* o) {}
47 };
48
49 template <typename Sig>
50 class Thunk;
willchan no longer on Chromium 2011/01/05 00:59:01 I'm not sure if thunk is as commonly used a term a
awong 2011/01/05 03:17:42 I don't like Thunk either. After we settle on a p
51
52 template <typename R>
53 class Thunk<R(void)> {
54 public:
55 typedef ::std::tr1::function<R(void)> ThunkType;
56 ThunkType f_;
57 scoped_refptr<ThunkState> state_;
58
59 explicit Thunk(ThunkType f) : f_(f), state_(new ThunkState()) {}
60
61 R operator()(void) {
62 return f_();
63 }
64 };
65
66 template <typename R, typename A0>
67 class Thunk<R(A0)> {
68 public:
69 typedef ::std::tr1::function<R(A0)> ThunkType;
70 ThunkType f_;
71 scoped_refptr<ThunkState> state_;
72
73 explicit Thunk(ThunkType f) : f_(f), state_(new ThunkState()) {}
74
75 R operator()(A0& a0) {
76 return f_(a0);
77 }
78 };
79
80 template <typename R, typename A0, typename A1>
81 class Thunk<R(A0, A1)> {
82 public:
83 typedef ::std::tr1::function<R(A0,A1)> ThunkType;
84 ThunkType f_;
85 ::std::tr1::function<void(void)> cleanup_;
86 scoped_refptr<ThunkState> state_;
87
88 explicit Thunk(ThunkType f) : f_(f), state_(new ThunkState()) {}
89
90 R operator()(const A0& a0, const A1& a1) {
91 return f_(a0, a1);
92 }
93 };
94
95 // Note that when declaring these template parameters, the types used in the
96 // function signature MUST not be shared with the types used in the arguments.
97 // If they are shared, then automatic conversions break. For example, this
98 // should work:
99 //
100 // void foo(double d);
101 // function<void(void)> f = Prebind(&foo, 2);
102 //
103 // However, if you declare the template for prebind as follows:
104 //
105 // template <typename R, typename P0>
106 // function<R(void)> Prebind(R(*)(P0), P0 p0);
107 //
108 // Then the line invoking Prebind will fail because 2 is an integer, and P0 is
109 // locked to be a double. If instead, you declare the template to not tie the
110 // function signature directly to the parameters, the compiler will have the
111 // flexibility to do the right conversion. Thus, the correct declaration will
112 // look like this:
113 //
114 // template <typename R, typename X0, typename P0>
115 // function<R(void)> Prebind(R(*)(X0), P0 p0);
116 //
117 // The signature uses the type X0, and the argument uses the type P0. There is
118 // no directly relationship enforced by the template declaration. Instead, we
119 // rely on the compiler to output in an error of P0 is not converatble to X0.
120 //
121
122
123 // 1 -> 0
124 template <typename R, typename X0, typename P0>
125 Thunk<R(void)>
126 Prebind(R(*f)(P0), P0 p0) {
127 return Thunk<R(void)>(::std::tr1::bind(f, p0));
128 }
129
130 // 2 -> 0
131 template <typename R, typename X0, typename X1, typename P0, typename P1>
132 Thunk<R(void)>
133 Prebind(R(*f)(X0, X1), P0 p0, P1 p1) {
134 return Thunk<R(void)>(::std::tr1::bind(f, p0, p1));
135 }
136
137 // 2 -> 1
138 template <typename R, typename X0, typename P0, typename A0>
139 Thunk<R(A0)>
140 Prebind(R(*f)(X0, A0), P0 p0) {
141 return Thunk<R(A0)>(::std::tr1::bind(f, p0, ::std::tr1::placeholders::_1));
142 }
143
144 // (curry) 1 -> 0
145 template <typename R, typename X0, typename P0>
146 Thunk<R(void)>
147 Prebind(Thunk<R(X0)> f, P0 p0) {
148 return Thunk<R(void)>(::std::tr1::bind(f, p0));
149 }
150
151 // (curry) 2 -> 0
152 template <typename R, typename X0, typename X1, typename P0, typename P1>
153 Thunk<R(void)>
154 Prebind(Thunk<R(X0, X1)> f, P0 p0, P1 p1) {
155 return Thunk<R(void)>(::std::tr1::bind(f, p0, p1));
156 }
157
158 // (curry) 2 -> 1
159 template <typename R, typename X0, typename P0, typename A0>
160 Thunk<R(A0)>
161 Prebind(Thunk<R(X0, A0)> f, P0 p0) {
162 return Thunk<R(A0)>(::std::tr1::bind(f, p0, ::std::tr1::placeholders::_1));
163 }
164
165 // Method 0 -> 0
166 template <typename R, typename O, typename T>
167 Thunk<R(void)>
168 Prebind(R(O::*f)(), T t) {
169 typename RetainTraits<T>::type* object_(RetainTraits<T>::unwrap(t));
170 Thunk<R(void)> thunk(::std::tr1::bind(f, object_));
171 RetainTraits<T>::RetainObject(thunk.state_.get(), object_);
172 return thunk;
173 }
174
175 // Method 1 -> 0
176 template <typename R, typename O, typename T, typename X0, typename P0>
177 Thunk<R(void)>
178 Prebind(R(O::*f)(X0), T t, P0 p0) {
179 typename RetainTraits<T>::type* object_(RetainTraits<T>::unwrap(t));
180 Thunk<R(void)> thunk(::std::tr1::bind(f, object_, p0));
181 RetainTraits<T>::RetainObject(thunk.state_.get(), object_);
182 return thunk;
183 }
184
185 // Method 1 -> 1
186 template <typename R, typename O, typename T, typename A0>
187 Thunk<R(A0)>
188 Prebind(R(O::*f)(A0), T t) {
189 typename RetainTraits<T>::type* object_(RetainTraits<T>::unwrap(t));
190 Thunk<R(A0)> thunk(::std::tr1::bind(f, object_));
191 RetainTraits<T>::RetainObject(thunk.state_.get(), object_);
192 return thunk;
193 }
194
195 // Method 2 -> 0
196 template <typename R, typename O, typename T, typename X0, typename X1, typename P0, typename P1>
197 Thunk<R(void)>
198 Prebind(R(O::*f)(X0, X1), T t, P0 p0, P1 p1) {
199 typename RetainTraits<T>::type* object_(RetainTraits<T>::unwrap(t));
200 Thunk<R(void)> thunk(::std::tr1::bind(f, object_, p0, p1));
201 RetainTraits<T>::RetainObject(thunk.state_.get(), object_);
202 return thunk;
203 }
204
205 // Method 2 -> 1
206 template <typename R, typename O, typename T, typename X0, typename P0, typename A0>
207 Thunk<R(A0)>
208 Prebind(R(O::*f)(X0, A0), T t, P0 p0) {
209 typename RetainTraits<T>::type* object_(RetainTraits<T>::unwrap(t));
210 Thunk<R(A0)> thunk(::std::tr1::bind(f, object_, p0, ::std::tr1::placeholders:: _1));
211 RetainTraits<T>::RetainObject(thunk.state_.get(), object_);
212 return thunk;
213 }
214
215 // Method 2 -> 2
216 template <typename R, typename O, typename T, typename A0, typename A1>
217 Thunk<R(A0, A1)>
218 Prebind(R(O::*f)(A0, A1), T t) {
219 typename RetainTraits<T>::type* object_(RetainTraits<T>::unwrap(t));
220 Thunk<R(A0,A1)> thunk(::std::tr1::bind(f, object_,
221 ::std::tr1::placeholders::_1,
222 ::std::tr1::placeholders::_2));
223 RetainTraits<T>::RetainObject(thunk.state_.get(), object_);
224 return thunk;
225 }
226
227 // Method 5 -> 2 ...yeah, I skipped a few...got bored of typing it.
228 template <typename R, typename O, typename T,
229 typename X0, typename X1, typename X2,
230 typename P0, typename P1, typename P2,
231 typename A0, typename A1>
232 Thunk<R(A0, A1)>
233 Prebind(R(O::*f)(X0, X1, X2, A0, A1), T t, P0 p0, P1 p1, P2 p2) {
234 O* object_(RetainTraits<T>::unwrap(t));
235 Thunk<R(A0,A1)> thunk(::std::tr1::bind(f, object_, p0, p1, p2,
236 ::std::tr1::placeholders::_1,
237 ::std::tr1::placeholders::_2));
238 RetainTraits<T>::RetainObject(thunk.state_.get(), object_);
239 return thunk;
240 }
241
242 // Wraps a Thunk to automatically cancel a task when the ThunkCanceller is
243 // deleted. This allows a caller to "nop" all outstanding callbacks registered
244 // with the ThunkCanceller.
245 //
246 // Note that if you're also looking at the Closure code, this is nearly
247 // identical to ClosureCanceller. In fact, it can be used interchangeably, but
248 // I put a forked version here just for completeness.
249 class ThunkCanceller {
250 public:
251 ThunkCanceller() : cancel_state_(new CancelState()) {}
252
253 ~ThunkCanceller() {
254 cancel_state_->is_canceled = true;
255 }
256
257 template <typename T>
258 Thunk<void(void)> Wrap(T c) {
259 using ::std::tr1::bind;
260 return base::Thunk<void(void)>(Prebind(&ThunkCanceller::Run<T>, cancel_state _, c));
261 }
262
263 bool empty() const {
264 // The ThunkCanceller has the only reference, no tasks are outstanding.
265 return cancel_state_->HasOneRef();
266 }
267
268 void RevokeAll() {
269 // Cancel all outstanding, then create a new cancel state so this object may
270 // be reused.
271 cancel_state_->is_canceled = true;
272 cancel_state_ = new CancelState();
273 }
274
275 private:
276 // The ScopedRunnableMethodFactory uses a WeakPtr. This is because it is
277 // actually reimplementing the storage for the task object, so a pointer is
278 // necessary and thus WeakPtr can be overloaded to serve as a flag.
279 //
280 // In this design, it seems overkill to use WeakPtr instead of a simple flag
281 // class (which WeakPtr eventually devolves into anyways).
282 class CancelState : public RefCounted<CancelState> {
283 public:
284 CancelState() : is_canceled(false) {}
285
286 bool is_canceled;
287 };
288
289 template <typename T>
290 static void Run(scoped_refptr<CancelState> cancel_state, T c) {
291 if (!cancel_state->is_canceled) {
292 c();
293 }
294 }
295
296 scoped_refptr<CancelState> cancel_state_;
297 };
298
299 } // namespace base
300
301 #endif // BASE_PREBIND_H
OLDNEW
« base/closure.h ('K') | « base/message_loop.cc ('k') | base/task.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698