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

Side by Side Diff: ppapi/utility/completion_callback_factory.h

Issue 9086003: Revert 116281 - Move paint aggregator and the completion callback factory. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 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
« no previous file with comments | « ppapi/utility/README.txt ('k') | ppapi/utility/graphics/paint_aggregator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_
6 #define PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_
7
8 #include "ppapi/cpp/completion_callback.h"
9 #include "ppapi/utility/non_thread_safe_ref_count.h"
10
11 namespace pp {
12
13 /// CompletionCallbackFactory<T> may be used to create CompletionCallback
14 /// objects that are bound to member functions.
15 ///
16 /// If a factory is destroyed, then any pending callbacks will be cancelled
17 /// preventing any bound member functions from being called. The CancelAll()
18 /// method allows pending callbacks to be cancelled without destroying the
19 /// factory.
20 ///
21 /// <strong>Note: </strong><code>CompletionCallbackFactory<T></code> isn't
22 /// thread safe, but you can make it more thread-friendly by passing a
23 /// thread-safe refcounting class as the second template element. However, it
24 /// only guarantees safety for creating a callback from another thread, the
25 /// callback itself needs to execute on the same thread as the thread that
26 /// creates/destroys the factory. With this restriction, it is safe to create
27 /// the <code>CompletionCallbackFactory</code> on the main thread, create
28 /// callbacks from any thread and pass them to CallOnMainThread().
29 ///
30 /// <strong>Example: </strong>
31 ///
32 /// @code
33 ///
34 /// class MyHandler {
35 /// public:
36 /// // If an compiler warns on following using |this| in the initializer
37 /// // list, use PP_ALLOW_THIS_IN_INITIALIZER_LIST macro.
38 /// MyHandler() : factory_(this), offset_(0) {
39 /// }
40 ///
41 /// void ProcessFile(const FileRef& file) {
42 /// CompletionCallback cc = factory_.NewRequiredCallback(
43 /// &MyHandler::DidOpen);
44 /// int32_t rv = fio_.Open(file, PP_FileOpenFlag_Read, cc);
45 /// CHECK(rv == PP_OK_COMPLETIONPENDING);
46 /// }
47 ///
48 /// private:
49 /// CompletionCallback NewCallback() {
50 /// return factory_.NewCallback(&MyHandler::DidCompleteIO);
51 /// }
52 ///
53 /// void DidOpen(int32_t result) {
54 /// if (result == PP_OK) {
55 /// // The file is open, and we can begin reading.
56 /// offset_ = 0;
57 /// ReadMore();
58 /// } else {
59 /// // Failed to open the file with error given by 'result'.
60 /// }
61 /// }
62 ///
63 /// void DidRead(int32_t result) {
64 /// if (result > 0) {
65 /// // buf_ now contains 'result' number of bytes from the file.
66 /// ProcessBytes(buf_, result);
67 /// offset_ += result;
68 /// ReadMore();
69 /// } else {
70 /// // Done reading (possibly with an error given by 'result').
71 /// }
72 /// }
73 ///
74 /// void ReadMore() {
75 /// CompletionCallback cc =
76 /// factory_.NewOptionalCallback(&MyHandler::DidRead);
77 /// int32_t rv = fio_.Read(offset_, buf_, sizeof(buf_),
78 /// cc.pp_completion_callback());
79 /// if (rv != PP_OK_COMPLETIONPENDING)
80 /// cc.Run(rv);
81 /// }
82 ///
83 /// void ProcessBytes(const char* bytes, int32_t length) {
84 /// // Do work ...
85 /// }
86 ///
87 /// pp::CompletionCallbackFactory<MyHandler> factory_;
88 /// pp::FileIO fio_;
89 /// char buf_[4096];
90 /// int64_t offset_;
91 /// };
92 ///
93 /// @endcode
94 ///
95 template <typename T, typename RefCount = NonThreadSafeRefCount>
96 class CompletionCallbackFactory {
97 public:
98
99 /// This constructor creates a <code>CompletionCallbackFactory</code>
100 /// bound to an object. If the constructor is called without an argument,
101 /// the default value of <code>NULL</code> is used. The user then must call
102 /// Initialize() to initialize the object.
103 ///
104 /// param[in] object Optional parameter. An object whose member functions
105 /// are to be bound to CompletionCallbacks created by this
106 /// <code>CompletionCallbackFactory</code>. The default value of this
107 /// parameter is <code>NULL</code>.
108 explicit CompletionCallbackFactory(T* object = NULL)
109 : object_(object) {
110 InitBackPointer();
111 }
112
113 /// Destructor.
114 ~CompletionCallbackFactory() {
115 ResetBackPointer();
116 }
117
118 /// CancelAll() cancels all <code>CompletionCallbacks</code> allocated from
119 /// this factory.
120 void CancelAll() {
121 ResetBackPointer();
122 InitBackPointer();
123 }
124 /// Initialize() binds the <code>CallbackFactory</code> to a particular
125 /// object. Use this when the object is not available at
126 /// <code>CallbackFactory</code> creation, and the <code>NULL</code> default
127 /// is passed to the constructor. The object may only be initialized once,
128 /// either by the constructor, or by a call to Initialize().
129 ///
130 /// @param[in] object The object whose member functions are to be bound to
131 /// the <code>CompletionCallback</code> created by this
132 /// <code>CompletionCallbackFactory</code>.
133 void Initialize(T* object) {
134 PP_DCHECK(object);
135 PP_DCHECK(!object_); // May only initialize once!
136 object_ = object;
137 }
138
139 /// GetObject() returns the object that was passed at initialization to
140 /// Intialize().
141 ///
142 /// @return the object passed to the constructor or Intialize().
143 T* GetObject() {
144 return object_;
145 }
146
147 /// NewCallback allocates a new, single-use <code>CompletionCallback</code>.
148 /// The <code>CompletionCallback</code> must be run in order for the memory
149 /// allocated by the methods to be freed.
150 /// NewCallback() is equivalent to NewRequiredCallback() below.
151 ///
152 /// @param[in] method The method to be invoked upon completion of the
153 /// operation.
154 ///
155 /// @return A <code>CompletionCallback</code>.
156 template <typename Method>
157 CompletionCallback NewCallback(Method method) {
158 PP_DCHECK(object_);
159 return NewCallbackHelper(Dispatcher0<Method>(method));
160 }
161
162 /// NewRequiredCallback() allocates a new, single-use
163 /// <code>CompletionCallback</code> that will always run. The
164 /// <code>CompletionCallback</code> must be run in order for the memory
165 /// allocated by the methods to be freed.
166 ///
167 /// @param[in] method The method to be invoked upon completion of the
168 /// operation.
169 ///
170 /// @return A <code>CompletionCallback</code>.
171 template <typename Method>
172 CompletionCallback NewRequiredCallback(Method method) {
173 CompletionCallback cc = NewCallback(method);
174 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
175 return cc;
176 }
177
178 /// NewOptionalCallback() allocates a new, single-use
179 /// <code>CompletionCallback</code> that might not run if the method
180 /// taking it can complete synchronously. Thus, if after passing the
181 /// CompletionCallback to a Pepper method, the method does not return
182 /// PP_OK_COMPLETIONPENDING, then you should manually call the
183 /// CompletionCallback's Run method, or memory will be leaked.
184 ///
185 /// @param[in] method The method to be invoked upon completion of the
186 /// operation.
187 ///
188 /// @return A <code>CompletionCallback</code>.
189 template <typename Method>
190 CompletionCallback NewOptionalCallback(Method method) {
191 CompletionCallback cc = NewCallback(method);
192 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
193 return cc;
194 }
195
196 /// NewCallback() allocates a new, single-use <code>CompletionCallback</code>.
197 /// The <code>CompletionCallback</code> must be run in order for the memory
198 /// allocated by the methods to be freed.
199 /// NewCallback() is equivalent to NewRequiredCallback() below.
200 ///
201 /// @param[in] method The method to be invoked upon completion of the
202 /// operation. Method should be of type:
203 /// <code>void (T::*)(int32_t result, const A& a)</code>
204 ///
205 /// @param[in] a Passed to <code>method</code> when the completion callback
206 /// runs.
207 ///
208 /// @return A <code>CompletionCallback</code>.
209 template <typename Method, typename A>
210 CompletionCallback NewCallback(Method method, const A& a) {
211 PP_DCHECK(object_);
212 return NewCallbackHelper(Dispatcher1<Method, A>(method, a));
213 }
214
215 /// NewRequiredCallback() allocates a new, single-use
216 /// <code>CompletionCallback</code> that will always run. The
217 /// <code>CompletionCallback</code> must be run in order for the memory
218 /// allocated by the methods to be freed.
219 ///
220 /// @param[in] method The method to be invoked upon completion of the
221 /// operation. Method should be of type:
222 /// <code>void (T::*)(int32_t result, const A& a)</code>
223 ///
224 /// @param[in] a Passed to <code>method</code> when the completion callback
225 /// runs.
226 ///
227 /// @return A <code>CompletionCallback</code>.
228 template <typename Method, typename A>
229 CompletionCallback NewRequiredCallback(Method method, const A& a) {
230 CompletionCallback cc = NewCallback(method, a);
231 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
232 return cc;
233 }
234
235 /// NewOptionalCallback() allocates a new, single-use
236 /// <code>CompletionCallback</code> that might not run if the method
237 /// taking it can complete synchronously. Thus, if after passing the
238 /// CompletionCallback to a Pepper method, the method does not return
239 /// PP_OK_COMPLETIONPENDING, then you should manually call the
240 /// CompletionCallback's Run method, or memory will be leaked.
241 ///
242 /// @param[in] method The method to be invoked upon completion of the
243 /// operation. Method should be of type:
244 /// <code>void (T::*)(int32_t result, const A& a)</code>
245 ///
246 /// @param[in] a Passed to <code>method</code> when the completion callback
247 /// runs.
248 ///
249 /// @return A <code>CompletionCallback</code>.
250 template <typename Method, typename A>
251 CompletionCallback NewOptionalCallback(Method method, const A& a) {
252 CompletionCallback cc = NewCallback(method, a);
253 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
254 return cc;
255 }
256
257 /// NewCallback() allocates a new, single-use
258 /// <code>CompletionCallback</code>.
259 /// The <code>CompletionCallback</code> must be run in order for the memory
260 /// allocated by the methods to be freed.
261 /// NewCallback() is equivalent to NewRequiredCallback() below.
262 ///
263 /// @param method The method taking the callback. Method should be of type:
264 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
265 ///
266 /// @param[in] a Passed to <code>method</code> when the completion callback
267 /// runs.
268 ///
269 /// @param[in] b Passed to <code>method</code> when the completion callback
270 /// runs.
271 ///
272 /// @return A <code>CompletionCallback</code>.
273 template <typename Method, typename A, typename B>
274 CompletionCallback NewCallback(Method method, const A& a, const B& b) {
275 PP_DCHECK(object_);
276 return NewCallbackHelper(Dispatcher2<Method, A, B>(method, a, b));
277 }
278
279 /// NewRequiredCallback() allocates a new, single-use
280 /// <code>CompletionCallback</code> that will always run. The
281 /// <code>CompletionCallback</code> must be run in order for the memory
282 /// allocated by the methods to be freed.
283 ///
284 /// @param method The method taking the callback. Method should be of type:
285 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
286 ///
287 /// @param[in] a Passed to <code>method</code> when the completion callback
288 /// runs.
289 ///
290 /// @param[in] b Passed to <code>method</code> when the completion callback
291 /// runs.
292 ///
293 /// @return A <code>CompletionCallback</code>.
294 template <typename Method, typename A, typename B>
295 CompletionCallback NewRequiredCallback(Method method, const A& a,
296 const B& b) {
297 CompletionCallback cc = NewCallback(method, a, b);
298 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
299 return cc;
300 }
301
302 /// NewOptionalCallback() allocates a new, single-use
303 /// <code>CompletionCallback</code> that might not run if the method
304 /// taking it can complete synchronously. Thus, if after passing the
305 /// CompletionCallback to a Pepper method, the method does not return
306 /// PP_OK_COMPLETIONPENDING, then you should manually call the
307 /// CompletionCallback's Run method, or memory will be leaked.
308 ///
309 /// @param[in] method The method taking the callback. Method should be of
310 /// type:
311 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
312 ///
313 /// @param[in] a Passed to <code>method</code> when the completion callback
314 /// runs.
315 ///
316 /// @param[in] b Passed to <code>method</code> when the completion callback
317 /// runs.
318 ///
319 /// @return A <code>CompletionCallback</code>.
320 template <typename Method, typename A, typename B>
321 CompletionCallback NewOptionalCallback(Method method, const A& a,
322 const B& b) {
323 CompletionCallback cc = NewCallback(method, a, b);
324 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
325 return cc;
326 }
327
328 /// NewCallback() allocates a new, single-use
329 /// <code>CompletionCallback</code>.
330 /// The <code>CompletionCallback</code> must be run in order for the memory
331 /// allocated by the methods to be freed.
332 /// NewCallback() is equivalent to NewRequiredCallback() below.
333 ///
334 /// @param method The method taking the callback. Method should be of type:
335 /// <code>
336 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
337 /// </code>
338 ///
339 /// @param[in] a Passed to <code>method</code> when the completion callback
340 /// runs.
341 ///
342 /// @param[in] b Passed to <code>method</code> when the completion callback
343 /// runs.
344 ///
345 /// @param[in] c Passed to <code>method</code> when the completion callback
346 /// runs.
347 ///
348 /// @return A <code>CompletionCallback</code>.
349 template <typename Method, typename A, typename B, typename C>
350 CompletionCallback NewCallback(Method method, const A& a, const B& b,
351 const C& c) {
352 PP_DCHECK(object_);
353 return NewCallbackHelper(Dispatcher3<Method, A, B, C>(method, a, b, c));
354 }
355
356 /// NewRequiredCallback() allocates a new, single-use
357 /// <code>CompletionCallback</code> that will always run. The
358 /// <code>CompletionCallback</code> must be run in order for the memory
359 /// allocated by the methods to be freed.
360 ///
361 /// @param method The method taking the callback. Method should be of type:
362 /// <code>
363 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
364 /// </code>
365 ///
366 /// @param[in] a Passed to <code>method</code> when the completion callback
367 /// runs.
368 ///
369 /// @param[in] b Passed to <code>method</code> when the completion callback
370 /// runs.
371 ///
372 /// @param[in] c Passed to <code>method</code> when the completion callback
373 /// runs.
374 ///
375 /// @return A <code>CompletionCallback</code>.
376 template <typename Method, typename A, typename B, typename C>
377 CompletionCallback NewRequiredCallback(Method method, const A& a,
378 const B& b, const C& c) {
379 CompletionCallback cc = NewCallback(method, a, b, c);
380 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
381 return cc;
382 }
383
384 /// NewOptionalCallback() allocates a new, single-use
385 /// <code>CompletionCallback</code> that might not run if the method
386 /// taking it can complete synchronously. Thus, if after passing the
387 /// CompletionCallback to a Pepper method, the method does not return
388 /// PP_OK_COMPLETIONPENDING, then you should manually call the
389 /// CompletionCallback's Run method, or memory will be leaked.
390 ///
391 /// @param[in] method The method taking the callback. Method should be of
392 /// type:
393 /// <code>
394 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
395 /// </code>
396 ///
397 /// @param[in] a Passed to <code>method</code> when the completion callback
398 /// runs.
399 ///
400 /// @param[in] b Passed to <code>method</code> when the completion callback
401 /// runs.
402 ///
403 /// @param[in] c Passed to <code>method</code> when the completion callback
404 /// runs.
405 ///
406 /// @return A <code>CompletionCallback</code>.
407 template <typename Method, typename A, typename B, typename C>
408 CompletionCallback NewOptionalCallback(Method method, const A& a,
409 const B& b, const C& c) {
410 CompletionCallback cc = NewCallback(method, a, b, c);
411 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
412 return cc;
413 }
414
415 private:
416 class BackPointer {
417 public:
418 typedef CompletionCallbackFactory<T, RefCount> FactoryType;
419
420 BackPointer(FactoryType* factory)
421 : factory_(factory) {
422 }
423
424 void AddRef() {
425 ref_.AddRef();
426 }
427
428 void Release() {
429 if (ref_.Release() == 0)
430 delete this;
431 }
432
433 void DropFactory() {
434 factory_ = NULL;
435 }
436
437 T* GetObject() {
438 return factory_ ? factory_->GetObject() : NULL;
439 }
440
441 private:
442 RefCount ref_;
443 FactoryType* factory_;
444 };
445
446 template <typename Dispatcher>
447 class CallbackData {
448 public:
449 CallbackData(BackPointer* back_pointer, const Dispatcher& dispatcher)
450 : back_pointer_(back_pointer),
451 dispatcher_(dispatcher) {
452 back_pointer_->AddRef();
453 }
454
455 ~CallbackData() {
456 back_pointer_->Release();
457 }
458
459 static void Thunk(void* user_data, int32_t result) {
460 Self* self = static_cast<Self*>(user_data);
461 T* object = self->back_pointer_->GetObject();
462 if (object)
463 self->dispatcher_(object, result);
464 delete self;
465 }
466
467 private:
468 typedef CallbackData<Dispatcher> Self;
469 BackPointer* back_pointer_;
470 Dispatcher dispatcher_;
471 };
472
473 template <typename Method>
474 class Dispatcher0 {
475 public:
476 Dispatcher0(Method method) : method_(method) {
477 }
478 void operator()(T* object, int32_t result) {
479 (object->*method_)(result);
480 }
481 private:
482 Method method_;
483 };
484
485 template <typename Method, typename A>
486 class Dispatcher1 {
487 public:
488 Dispatcher1(Method method, const A& a)
489 : method_(method),
490 a_(a) {
491 }
492 void operator()(T* object, int32_t result) {
493 (object->*method_)(result, a_);
494 }
495 private:
496 Method method_;
497 A a_;
498 };
499
500 template <typename Method, typename A, typename B>
501 class Dispatcher2 {
502 public:
503 Dispatcher2(Method method, const A& a, const B& b)
504 : method_(method),
505 a_(a),
506 b_(b) {
507 }
508 void operator()(T* object, int32_t result) {
509 (object->*method_)(result, a_, b_);
510 }
511 private:
512 Method method_;
513 A a_;
514 B b_;
515 };
516
517 template <typename Method, typename A, typename B, typename C>
518 class Dispatcher3 {
519 public:
520 Dispatcher3(Method method, const A& a, const B& b, const C& c)
521 : method_(method),
522 a_(a),
523 b_(b),
524 c_(c) {
525 }
526 void operator()(T* object, int32_t result) {
527 (object->*method_)(result, a_, b_, c_);
528 }
529 private:
530 Method method_;
531 A a_;
532 B b_;
533 C c_;
534 };
535
536 void InitBackPointer() {
537 back_pointer_ = new BackPointer(this);
538 back_pointer_->AddRef();
539 }
540
541 void ResetBackPointer() {
542 back_pointer_->DropFactory();
543 back_pointer_->Release();
544 }
545
546 template <typename Dispatcher>
547 CompletionCallback NewCallbackHelper(const Dispatcher& dispatcher) {
548 PP_DCHECK(object_); // Expects a non-null object!
549 return CompletionCallback(
550 &CallbackData<Dispatcher>::Thunk,
551 new CallbackData<Dispatcher>(back_pointer_, dispatcher));
552 }
553
554 // Disallowed:
555 CompletionCallbackFactory(const CompletionCallbackFactory&);
556 CompletionCallbackFactory& operator=(const CompletionCallbackFactory&);
557
558 T* object_;
559 BackPointer* back_pointer_;
560 };
561
562 } // namespace pp
563
564 #endif // PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_
OLDNEW
« no previous file with comments | « ppapi/utility/README.txt ('k') | ppapi/utility/graphics/paint_aggregator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698