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

Side by Side Diff: ppapi/cpp/completion_callback.h

Issue 9122012: gcl change rev (Closed) Base URL: svn://chrome-svn/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 | « gpu/demos/framework/pepper.cc ('k') | ppapi/cpp/non_thread_safe_ref_count.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef PPAPI_CPP_COMPLETION_CALLBACK_H_ 5 #ifndef PPAPI_CPP_COMPLETION_CALLBACK_H_
6 #define PPAPI_CPP_COMPLETION_CALLBACK_H_ 6 #define PPAPI_CPP_COMPLETION_CALLBACK_H_
7 7
8 #include "ppapi/c/pp_completion_callback.h" 8 #include "ppapi/c/pp_completion_callback.h"
9 #include "ppapi/c/pp_errors.h" 9 #include "ppapi/c/pp_errors.h"
10 #include "ppapi/cpp/logging.h" 10 #include "ppapi/cpp/logging.h"
11 #include "ppapi/cpp/non_thread_safe_ref_count.h" 11 #include "ppapi/cpp/module.h"
12 12
13 /// @file 13 /// @file
14 /// This file defines the API to create and run a callback. 14 /// This file defines the API to create and run a callback.
15 namespace pp { 15 namespace pp {
16 16
17 /// This API enables you to implement and receive callbacks when 17 /// This API enables you to implement and receive callbacks when
18 /// Pepper operations complete asynchronously. 18 /// Pepper operations complete asynchronously.
19 class CompletionCallback { 19 class CompletionCallback {
20 public: 20 public:
21 /// The default constructor will create a blocking 21 /// The default constructor will create a blocking
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 }; 149 };
150 150
151 /// BlockUntilComplete() is used in place of an actual completion callback 151 /// BlockUntilComplete() is used in place of an actual completion callback
152 /// to request blocking behavior. If specified, the calling thread will block 152 /// to request blocking behavior. If specified, the calling thread will block
153 /// until the function completes. Blocking completion callbacks are only 153 /// until the function completes. Blocking completion callbacks are only
154 /// allowed from background threads. 154 /// allowed from background threads.
155 /// 155 ///
156 /// @return A <code>CompletionCallback</code> corresponding to a NULL callback. 156 /// @return A <code>CompletionCallback</code> corresponding to a NULL callback.
157 CompletionCallback BlockUntilComplete(); 157 CompletionCallback BlockUntilComplete();
158 158
159 /// CompletionCallbackFactory<T> may be used to create CompletionCallback
160 /// objects that are bound to member functions.
161 ///
162 /// If a factory is destroyed, then any pending callbacks will be cancelled
163 /// preventing any bound member functions from being called. The CancelAll()
164 /// method allows pending callbacks to be cancelled without destroying the
165 /// factory.
166 ///
167 /// <strong>Note: </strong><code>CompletionCallbackFactory<T></code> isn't
168 /// thread safe, but you can make it more thread-friendly by passing a
169 /// thread-safe refcounting class as the second template element. However, it
170 /// only guarantees safety for creating a callback from another thread, the
171 /// callback itself needs to execute on the same thread as the thread that
172 /// creates/destroys the factory. With this restriction, it is safe to create
173 /// the <code>CompletionCallbackFactory</code> on the main thread, create
174 /// callbacks from any thread and pass them to CallOnMainThread().
175 ///
176 /// <strong>Example: </strong>
177 ///
178 /// @code
179 ///
180 /// class MyHandler {
181 /// public:
182 /// // If an compiler warns on following using |this| in the initializer
183 /// // list, use PP_ALLOW_THIS_IN_INITIALIZER_LIST macro.
184 /// MyHandler() : factory_(this), offset_(0) {
185 /// }
186 ///
187 /// void ProcessFile(const FileRef& file) {
188 /// CompletionCallback cc = factory_.NewRequiredCallback(
189 /// &MyHandler::DidOpen);
190 /// int32_t rv = fio_.Open(file, PP_FileOpenFlag_Read, cc);
191 /// CHECK(rv == PP_OK_COMPLETIONPENDING);
192 /// }
193 ///
194 /// private:
195 /// CompletionCallback NewCallback() {
196 /// return factory_.NewCallback(&MyHandler::DidCompleteIO);
197 /// }
198 ///
199 /// void DidOpen(int32_t result) {
200 /// if (result == PP_OK) {
201 /// // The file is open, and we can begin reading.
202 /// offset_ = 0;
203 /// ReadMore();
204 /// } else {
205 /// // Failed to open the file with error given by 'result'.
206 /// }
207 /// }
208 ///
209 /// void DidRead(int32_t result) {
210 /// if (result > 0) {
211 /// // buf_ now contains 'result' number of bytes from the file.
212 /// ProcessBytes(buf_, result);
213 /// offset_ += result;
214 /// ReadMore();
215 /// } else {
216 /// // Done reading (possibly with an error given by 'result').
217 /// }
218 /// }
219 ///
220 /// void ReadMore() {
221 /// CompletionCallback cc =
222 /// factory_.NewOptionalCallback(&MyHandler::DidRead);
223 /// int32_t rv = fio_.Read(offset_, buf_, sizeof(buf_),
224 /// cc.pp_completion_callback());
225 /// if (rv != PP_OK_COMPLETIONPENDING)
226 /// cc.Run(rv);
227 /// }
228 ///
229 /// void ProcessBytes(const char* bytes, int32_t length) {
230 /// // Do work ...
231 /// }
232 ///
233 /// pp::CompletionCallbackFactory<MyHandler> factory_;
234 /// pp::FileIO fio_;
235 /// char buf_[4096];
236 /// int64_t offset_;
237 /// };
238 ///
239 /// @endcode
240 ///
241 template <typename T, typename RefCount = NonThreadSafeRefCount>
242 class CompletionCallbackFactory {
243 public:
244
245 /// This constructor creates a <code>CompletionCallbackFactory</code>
246 /// bound to an object. If the constructor is called without an argument,
247 /// the default value of <code>NULL</code> is used. The user then must call
248 /// Initialize() to initialize the object.
249 ///
250 /// param[in] object Optional parameter. An object whose member functions
251 /// are to be bound to CompletionCallbacks created by this
252 /// <code>CompletionCallbackFactory</code>. The default value of this
253 /// parameter is <code>NULL</code>.
254 explicit CompletionCallbackFactory(T* object = NULL)
255 : object_(object) {
256 InitBackPointer();
257 }
258
259 /// Destructor.
260 ~CompletionCallbackFactory() {
261 ResetBackPointer();
262 }
263
264 /// CancelAll() cancels all <code>CompletionCallbacks</code> allocated from
265 /// this factory.
266 void CancelAll() {
267 ResetBackPointer();
268 InitBackPointer();
269 }
270 /// Initialize() binds the <code>CallbackFactory</code> to a particular
271 /// object. Use this when the object is not available at
272 /// <code>CallbackFactory</code> creation, and the <code>NULL</code> default
273 /// is passed to the constructor. The object may only be initialized once,
274 /// either by the constructor, or by a call to Initialize().
275 ///
276 /// @param[in] object The object whose member functions are to be bound to
277 /// the <code>CompletionCallback</code> created by this
278 /// <code>CompletionCallbackFactory</code>.
279 void Initialize(T* object) {
280 PP_DCHECK(object);
281 PP_DCHECK(!object_); // May only initialize once!
282 object_ = object;
283 }
284
285 /// GetObject() returns the object that was passed at initialization to
286 /// Intialize().
287 ///
288 /// @return the object passed to the constructor or Intialize().
289 T* GetObject() {
290 return object_;
291 }
292
293 /// NewCallback allocates a new, single-use <code>CompletionCallback</code>.
294 /// The <code>CompletionCallback</code> must be run in order for the memory
295 /// allocated by the methods to be freed.
296 /// NewCallback() is equivalent to NewRequiredCallback() below.
297 ///
298 /// @param[in] method The method to be invoked upon completion of the
299 /// operation.
300 ///
301 /// @return A <code>CompletionCallback</code>.
302 template <typename Method>
303 CompletionCallback NewCallback(Method method) {
304 PP_DCHECK(object_);
305 return NewCallbackHelper(Dispatcher0<Method>(method));
306 }
307
308 /// NewRequiredCallback() allocates a new, single-use
309 /// <code>CompletionCallback</code> that will always run. The
310 /// <code>CompletionCallback</code> must be run in order for the memory
311 /// allocated by the methods to be freed.
312 ///
313 /// @param[in] method The method to be invoked upon completion of the
314 /// operation.
315 ///
316 /// @return A <code>CompletionCallback</code>.
317 template <typename Method>
318 CompletionCallback NewRequiredCallback(Method method) {
319 CompletionCallback cc = NewCallback(method);
320 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
321 return cc;
322 }
323
324 /// NewOptionalCallback() allocates a new, single-use
325 /// <code>CompletionCallback</code> that might not run if the method
326 /// taking it can complete synchronously. Thus, if after passing the
327 /// CompletionCallback to a Pepper method, the method does not return
328 /// PP_OK_COMPLETIONPENDING, then you should manually call the
329 /// CompletionCallback's Run method, or memory will be leaked.
330 ///
331 /// @param[in] method The method to be invoked upon completion of the
332 /// operation.
333 ///
334 /// @return A <code>CompletionCallback</code>.
335 template <typename Method>
336 CompletionCallback NewOptionalCallback(Method method) {
337 CompletionCallback cc = NewCallback(method);
338 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
339 return cc;
340 }
341
342 /// NewCallback() allocates a new, single-use <code>CompletionCallback</code>.
343 /// The <code>CompletionCallback</code> must be run in order for the memory
344 /// allocated by the methods to be freed.
345 /// NewCallback() is equivalent to NewRequiredCallback() below.
346 ///
347 /// @param[in] method The method to be invoked upon completion of the
348 /// operation. Method should be of type:
349 /// <code>void (T::*)(int32_t result, const A& a)</code>
350 ///
351 /// @param[in] a Passed to <code>method</code> when the completion callback
352 /// runs.
353 ///
354 /// @return A <code>CompletionCallback</code>.
355 template <typename Method, typename A>
356 CompletionCallback NewCallback(Method method, const A& a) {
357 PP_DCHECK(object_);
358 return NewCallbackHelper(Dispatcher1<Method, A>(method, a));
359 }
360
361 /// NewRequiredCallback() allocates a new, single-use
362 /// <code>CompletionCallback</code> that will always run. The
363 /// <code>CompletionCallback</code> must be run in order for the memory
364 /// allocated by the methods to be freed.
365 ///
366 /// @param[in] method The method to be invoked upon completion of the
367 /// operation. Method should be of type:
368 /// <code>void (T::*)(int32_t result, const A& a)</code>
369 ///
370 /// @param[in] a Passed to <code>method</code> when the completion callback
371 /// runs.
372 ///
373 /// @return A <code>CompletionCallback</code>.
374 template <typename Method, typename A>
375 CompletionCallback NewRequiredCallback(Method method, const A& a) {
376 CompletionCallback cc = NewCallback(method, a);
377 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
378 return cc;
379 }
380
381 /// NewOptionalCallback() allocates a new, single-use
382 /// <code>CompletionCallback</code> that might not run if the method
383 /// taking it can complete synchronously. Thus, if after passing the
384 /// CompletionCallback to a Pepper method, the method does not return
385 /// PP_OK_COMPLETIONPENDING, then you should manually call the
386 /// CompletionCallback's Run method, or memory will be leaked.
387 ///
388 /// @param[in] method The method to be invoked upon completion of the
389 /// operation. Method should be of type:
390 /// <code>void (T::*)(int32_t result, const A& a)</code>
391 ///
392 /// @param[in] a Passed to <code>method</code> when the completion callback
393 /// runs.
394 ///
395 /// @return A <code>CompletionCallback</code>.
396 template <typename Method, typename A>
397 CompletionCallback NewOptionalCallback(Method method, const A& a) {
398 CompletionCallback cc = NewCallback(method, a);
399 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
400 return cc;
401 }
402
403 /// NewCallback() allocates a new, single-use
404 /// <code>CompletionCallback</code>.
405 /// The <code>CompletionCallback</code> must be run in order for the memory
406 /// allocated by the methods to be freed.
407 /// NewCallback() is equivalent to NewRequiredCallback() below.
408 ///
409 /// @param method The method taking the callback. Method should be of type:
410 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
411 ///
412 /// @param[in] a Passed to <code>method</code> when the completion callback
413 /// runs.
414 ///
415 /// @param[in] b Passed to <code>method</code> when the completion callback
416 /// runs.
417 ///
418 /// @return A <code>CompletionCallback</code>.
419 template <typename Method, typename A, typename B>
420 CompletionCallback NewCallback(Method method, const A& a, const B& b) {
421 PP_DCHECK(object_);
422 return NewCallbackHelper(Dispatcher2<Method, A, B>(method, a, b));
423 }
424
425 /// NewRequiredCallback() allocates a new, single-use
426 /// <code>CompletionCallback</code> that will always run. The
427 /// <code>CompletionCallback</code> must be run in order for the memory
428 /// allocated by the methods to be freed.
429 ///
430 /// @param method The method taking the callback. Method should be of type:
431 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
432 ///
433 /// @param[in] a Passed to <code>method</code> when the completion callback
434 /// runs.
435 ///
436 /// @param[in] b Passed to <code>method</code> when the completion callback
437 /// runs.
438 ///
439 /// @return A <code>CompletionCallback</code>.
440 template <typename Method, typename A, typename B>
441 CompletionCallback NewRequiredCallback(Method method, const A& a,
442 const B& b) {
443 CompletionCallback cc = NewCallback(method, a, b);
444 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
445 return cc;
446 }
447
448 /// NewOptionalCallback() allocates a new, single-use
449 /// <code>CompletionCallback</code> that might not run if the method
450 /// taking it can complete synchronously. Thus, if after passing the
451 /// CompletionCallback to a Pepper method, the method does not return
452 /// PP_OK_COMPLETIONPENDING, then you should manually call the
453 /// CompletionCallback's Run method, or memory will be leaked.
454 ///
455 /// @param[in] method The method taking the callback. Method should be of
456 /// type:
457 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
458 ///
459 /// @param[in] a Passed to <code>method</code> when the completion callback
460 /// runs.
461 ///
462 /// @param[in] b Passed to <code>method</code> when the completion callback
463 /// runs.
464 ///
465 /// @return A <code>CompletionCallback</code>.
466 template <typename Method, typename A, typename B>
467 CompletionCallback NewOptionalCallback(Method method, const A& a,
468 const B& b) {
469 CompletionCallback cc = NewCallback(method, a, b);
470 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
471 return cc;
472 }
473
474 /// NewCallback() allocates a new, single-use
475 /// <code>CompletionCallback</code>.
476 /// The <code>CompletionCallback</code> must be run in order for the memory
477 /// allocated by the methods to be freed.
478 /// NewCallback() is equivalent to NewRequiredCallback() below.
479 ///
480 /// @param method The method taking the callback. Method should be of type:
481 /// <code>
482 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
483 /// </code>
484 ///
485 /// @param[in] a Passed to <code>method</code> when the completion callback
486 /// runs.
487 ///
488 /// @param[in] b Passed to <code>method</code> when the completion callback
489 /// runs.
490 ///
491 /// @param[in] c Passed to <code>method</code> when the completion callback
492 /// runs.
493 ///
494 /// @return A <code>CompletionCallback</code>.
495 template <typename Method, typename A, typename B, typename C>
496 CompletionCallback NewCallback(Method method, const A& a, const B& b,
497 const C& c) {
498 PP_DCHECK(object_);
499 return NewCallbackHelper(Dispatcher3<Method, A, B, C>(method, a, b, c));
500 }
501
502 /// NewRequiredCallback() allocates a new, single-use
503 /// <code>CompletionCallback</code> that will always run. The
504 /// <code>CompletionCallback</code> must be run in order for the memory
505 /// allocated by the methods to be freed.
506 ///
507 /// @param method The method taking the callback. Method should be of type:
508 /// <code>
509 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
510 /// </code>
511 ///
512 /// @param[in] a Passed to <code>method</code> when the completion callback
513 /// runs.
514 ///
515 /// @param[in] b Passed to <code>method</code> when the completion callback
516 /// runs.
517 ///
518 /// @param[in] c Passed to <code>method</code> when the completion callback
519 /// runs.
520 ///
521 /// @return A <code>CompletionCallback</code>.
522 template <typename Method, typename A, typename B, typename C>
523 CompletionCallback NewRequiredCallback(Method method, const A& a,
524 const B& b, const C& c) {
525 CompletionCallback cc = NewCallback(method, a, b, c);
526 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
527 return cc;
528 }
529
530 /// NewOptionalCallback() allocates a new, single-use
531 /// <code>CompletionCallback</code> that might not run if the method
532 /// taking it can complete synchronously. Thus, if after passing the
533 /// CompletionCallback to a Pepper method, the method does not return
534 /// PP_OK_COMPLETIONPENDING, then you should manually call the
535 /// CompletionCallback's Run method, or memory will be leaked.
536 ///
537 /// @param[in] method The method taking the callback. Method should be of
538 /// type:
539 /// <code>
540 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
541 /// </code>
542 ///
543 /// @param[in] a Passed to <code>method</code> when the completion callback
544 /// runs.
545 ///
546 /// @param[in] b Passed to <code>method</code> when the completion callback
547 /// runs.
548 ///
549 /// @param[in] c Passed to <code>method</code> when the completion callback
550 /// runs.
551 ///
552 /// @return A <code>CompletionCallback</code>.
553 template <typename Method, typename A, typename B, typename C>
554 CompletionCallback NewOptionalCallback(Method method, const A& a,
555 const B& b, const C& c) {
556 CompletionCallback cc = NewCallback(method, a, b, c);
557 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
558 return cc;
559 }
560
561 private:
562 class BackPointer {
563 public:
564 typedef CompletionCallbackFactory<T, RefCount> FactoryType;
565
566 BackPointer(FactoryType* factory)
567 : factory_(factory) {
568 }
569
570 void AddRef() {
571 ref_.AddRef();
572 }
573
574 void Release() {
575 if (ref_.Release() == 0)
576 delete this;
577 }
578
579 void DropFactory() {
580 factory_ = NULL;
581 }
582
583 T* GetObject() {
584 return factory_ ? factory_->GetObject() : NULL;
585 }
586
587 private:
588 RefCount ref_;
589 FactoryType* factory_;
590 };
591
592 template <typename Dispatcher>
593 class CallbackData {
594 public:
595 CallbackData(BackPointer* back_pointer, const Dispatcher& dispatcher)
596 : back_pointer_(back_pointer),
597 dispatcher_(dispatcher) {
598 back_pointer_->AddRef();
599 }
600
601 ~CallbackData() {
602 back_pointer_->Release();
603 }
604
605 static void Thunk(void* user_data, int32_t result) {
606 Self* self = static_cast<Self*>(user_data);
607 T* object = self->back_pointer_->GetObject();
608 if (object)
609 self->dispatcher_(object, result);
610 delete self;
611 }
612
613 private:
614 typedef CallbackData<Dispatcher> Self;
615 BackPointer* back_pointer_;
616 Dispatcher dispatcher_;
617 };
618
619 template <typename Method>
620 class Dispatcher0 {
621 public:
622 Dispatcher0(Method method) : method_(method) {
623 }
624 void operator()(T* object, int32_t result) {
625 (object->*method_)(result);
626 }
627 private:
628 Method method_;
629 };
630
631 template <typename Method, typename A>
632 class Dispatcher1 {
633 public:
634 Dispatcher1(Method method, const A& a)
635 : method_(method),
636 a_(a) {
637 }
638 void operator()(T* object, int32_t result) {
639 (object->*method_)(result, a_);
640 }
641 private:
642 Method method_;
643 A a_;
644 };
645
646 template <typename Method, typename A, typename B>
647 class Dispatcher2 {
648 public:
649 Dispatcher2(Method method, const A& a, const B& b)
650 : method_(method),
651 a_(a),
652 b_(b) {
653 }
654 void operator()(T* object, int32_t result) {
655 (object->*method_)(result, a_, b_);
656 }
657 private:
658 Method method_;
659 A a_;
660 B b_;
661 };
662
663 template <typename Method, typename A, typename B, typename C>
664 class Dispatcher3 {
665 public:
666 Dispatcher3(Method method, const A& a, const B& b, const C& c)
667 : method_(method),
668 a_(a),
669 b_(b),
670 c_(c) {
671 }
672 void operator()(T* object, int32_t result) {
673 (object->*method_)(result, a_, b_, c_);
674 }
675 private:
676 Method method_;
677 A a_;
678 B b_;
679 C c_;
680 };
681
682 void InitBackPointer() {
683 back_pointer_ = new BackPointer(this);
684 back_pointer_->AddRef();
685 }
686
687 void ResetBackPointer() {
688 back_pointer_->DropFactory();
689 back_pointer_->Release();
690 }
691
692 template <typename Dispatcher>
693 CompletionCallback NewCallbackHelper(const Dispatcher& dispatcher) {
694 PP_DCHECK(object_); // Expects a non-null object!
695 return CompletionCallback(
696 &CallbackData<Dispatcher>::Thunk,
697 new CallbackData<Dispatcher>(back_pointer_, dispatcher));
698 }
699
700 // Disallowed:
701 CompletionCallbackFactory(const CompletionCallbackFactory&);
702 CompletionCallbackFactory& operator=(const CompletionCallbackFactory&);
703
704 T* object_;
705 BackPointer* back_pointer_;
706 };
707
708 } // namespace pp 159 } // namespace pp
709 160
710 #endif // PPAPI_CPP_COMPLETION_CALLBACK_H_ 161 #endif // PPAPI_CPP_COMPLETION_CALLBACK_H_
OLDNEW
« no previous file with comments | « gpu/demos/framework/pepper.cc ('k') | ppapi/cpp/non_thread_safe_ref_count.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698