Additional fixes to new notification docs
[chromium-blink-merge.git] / ppapi / utility / completion_callback_factory.h
blob885767b0928c40579e9e55afc8b6bd13dc20ae62
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.
5 #ifndef PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_
6 #define PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_
8 #include "ppapi/cpp/completion_callback.h"
9 #include "ppapi/utility/completion_callback_factory_thread_traits.h"
11 /// @file
12 /// This file defines the API to create CompletionCallback objects that are
13 /// bound to member functions.
14 namespace pp {
16 // TypeUnwrapper --------------------------------------------------------------
18 namespace internal {
20 // The TypeUnwrapper converts references and const references to the
21 // underlying type used for storage and passing as an argument. It is for
22 // internal use only.
23 template <typename T> struct TypeUnwrapper {
24 typedef T StorageType;
26 template <typename T> struct TypeUnwrapper<T&> {
27 typedef T StorageType;
29 template <typename T> struct TypeUnwrapper<const T&> {
30 typedef T StorageType;
33 } // namespace internal
35 // ----------------------------------------------------------------------------
37 /// CompletionCallbackFactory<T> may be used to create CompletionCallback
38 /// objects that are bound to member functions.
39 ///
40 /// If a factory is destroyed, then any pending callbacks will be cancelled
41 /// preventing any bound member functions from being called. The CancelAll()
42 /// method allows pending callbacks to be cancelled without destroying the
43 /// factory.
44 ///
45 /// <strong>Note: </strong><code>CompletionCallbackFactory<T></code> isn't
46 /// thread safe, but it is somewhat thread-friendly when used with a
47 /// thread-safe traits class as the second template element. However, it
48 /// only guarantees safety for creating a callback from another thread, the
49 /// callback itself needs to execute on the same thread as the thread that
50 /// creates/destroys the factory. With this restriction, it is safe to create
51 /// the <code>CompletionCallbackFactory</code> on the main thread, create
52 /// callbacks from any thread and pass them to CallOnMainThread().
53 ///
54 /// <strong>Example: </strong>
55 ///
56 /// @code
57 /// class MyClass {
58 /// public:
59 /// // If an compiler warns on following using |this| in the initializer
60 /// // list, use PP_ALLOW_THIS_IN_INITIALIZER_LIST macro.
61 /// MyClass() : factory_(this) {
62 /// }
63 ///
64 /// void OpenFile(const pp::FileRef& file) {
65 /// pp::CompletionCallback cc = factory_.NewCallback(&MyClass::DidOpen);
66 /// int32_t rv = file_io_.Open(file, PP_FileOpenFlag_Read, cc);
67 /// CHECK(rv == PP_OK_COMPLETIONPENDING);
68 /// }
69 ///
70 /// private:
71 /// void DidOpen(int32_t result) {
72 /// if (result == PP_OK) {
73 /// // The file is open, and we can begin reading.
74 /// // ...
75 /// } else {
76 /// // Failed to open the file with error given by 'result'.
77 /// }
78 /// }
79 ///
80 /// pp::CompletionCallbackFactory<MyClass> factory_;
81 /// };
82 /// @endcode
83 ///
84 /// <strong>Passing additional parameters to your callback</strong>
85 ///
86 /// As a convenience, the <code>CompletionCallbackFactory</code> can optionally
87 /// create a closure with up to three bound parameters that it will pass to
88 /// your callback function. This can be useful for passing information about
89 /// the request to your callback function, which is especially useful if your
90 /// class has multiple asynchronous callbacks pending.
91 ///
92 /// For the above example, of opening a file, let's say you want to keep some
93 /// description associated with your request, you might implement your OpenFile
94 /// and DidOpen callback as follows:
95 ///
96 /// @code
97 /// void OpenFile(const pp::FileRef& file) {
98 /// std::string message = "Opening file!";
99 /// pp::CompletionCallback cc = factory_.NewCallback(&MyClass::DidOpen,
100 /// message);
101 /// int32_t rv = file_io_.Open(file, PP_FileOpenFlag_Read, cc);
102 /// CHECK(rv == PP_OK_COMPLETIONPENDING);
103 /// }
104 /// void DidOpen(int32_t result, const std::string& message) {
105 /// // "message" will be "Opening file!".
106 /// ...
107 /// }
108 /// @endcode
110 /// <strong>Optional versus required callbacks</strong>
112 /// When you create an "optional" callback, the browser may return the results
113 /// synchronously if they are available. This can allow for higher performance
114 /// in some cases if data is available quickly (for example, for network loads
115 /// where there may be a lot of data coming quickly). In this case, the
116 /// callback will never be run.
118 /// When creating a new callback with the factory, there will be data allocated
119 /// on the heap that tracks the callback information and any bound arguments.
120 /// This data is freed when the callback executes. In the case of optional
121 /// callbacks, since the browser will never issue the callback, the internal
122 /// tracking data will be leaked.
124 /// Therefore, if you use optional callbacks, it's important to manually
125 /// issue the callback to free up this data. The typical pattern is:
127 /// @code
128 /// pp::CompletionCallback callback = callback_factory.NewOptionalCallback(
129 /// &MyClass::OnDataReady);
130 /// int32_t result = interface->GetData(callback);
131 /// if (result != PP_OK_COMPLETIONPENDING)
132 /// callback.Run(result);
133 /// @endcode
135 /// Because of this additional complexity, it's generally recommended that
136 /// you not use optional callbacks except when performance is more important
137 /// (such as loading large resources from the network). In most other cases,
138 /// the performance difference will not be worth the additional complexity,
139 /// and most functions may never actually have the ability to complete
140 /// synchronously.
142 /// <strong>Completion callbacks with output</strong>
144 /// For some API calls, the browser returns data to the caller via an output
145 /// parameter. These can be difficult to manage since the output parameter
146 /// must remain valid for as long as the callback is pending. Note also that
147 /// CancelAll (or destroying the callback factory) does <i>not</i> cancel the
148 /// callback from the browser's perspective, only the execution of the callback
149 /// in the plugin code, and the output parameter will still be written to!
150 /// This means that you can't use class members as output parameters without
151 /// risking crashes.
153 /// To make this case easier, the CompletionCallbackFactory can allocate and
154 /// manage the output data for you and pass it to your callback function. This
155 /// makes such calls more natural and less error-prone.
157 /// To create such a callback, use NewCallbackWithOutput and specify a callback
158 /// function that takes the output parameter as its second argument. Let's say
159 /// you're calling a function GetFile which asynchronously returns a
160 /// pp::FileRef. GetFile's signature will be <code>int32_t GetFile(const
161 /// CompletionCallbackWithOutput<pp::FileRef>& callback);</code> and your
162 /// calling code would look like this:
164 /// @code
165 /// void RequestFile() {
166 /// file_interface->GetFile(callback_factory_.NewCallbackWithOutput(
167 /// &MyClass::GotFile));
168 /// }
169 /// void GotFile(int32_t result, const pp::FileRef& file) {
170 /// if (result == PP_OK) {
171 /// ...use file...
172 /// } else {
173 /// ...handle error...
174 /// }
175 /// }
176 /// @endcode
178 /// As with regular completion callbacks, you can optionally add up to three
179 /// bound arguments. These are passed following the output argument.
181 /// Your callback may take the output argument as a copy (common for small
182 /// types like integers, a const reference (common for structures and
183 /// resources to avoid an extra copy), or as a non-const reference. One
184 /// optimization you can do if your callback function may take large arrays
185 /// is to accept your output argument as a non-const reference and to swap()
186 /// the argument with a vector of your own to store it. This means you don't
187 /// have to copy the buffer to consume it.
188 template <typename T, typename ThreadTraits = ThreadSafeThreadTraits>
189 class CompletionCallbackFactory {
190 public:
192 /// This constructor creates a <code>CompletionCallbackFactory</code>
193 /// bound to an object. If the constructor is called without an argument,
194 /// the default value of <code>NULL</code> is used. The user then must call
195 /// Initialize() to initialize the object.
197 /// param[in] object Optional parameter. An object whose member functions
198 /// are to be bound to CompletionCallbacks created by this
199 /// <code>CompletionCallbackFactory</code>. The default value of this
200 /// parameter is <code>NULL</code>.
201 explicit CompletionCallbackFactory(T* object = NULL)
202 : object_(object) {
203 // Assume that we don't need to lock since construction should be complete
204 // before the pointer is used on another thread.
205 InitBackPointer();
208 /// Destructor.
209 ~CompletionCallbackFactory() {
210 // Assume that we don't need to lock since this object should not be used
211 // from multiple threads during destruction.
212 ResetBackPointer();
215 /// CancelAll() cancels all <code>CompletionCallbacks</code> allocated from
216 /// this factory.
217 void CancelAll() {
218 typename ThreadTraits::AutoLock lock(lock_);
220 ResetBackPointer();
221 InitBackPointer();
224 /// Initialize() binds the <code>CallbackFactory</code> to a particular
225 /// object. Use this when the object is not available at
226 /// <code>CallbackFactory</code> creation, and the <code>NULL</code> default
227 /// is passed to the constructor. The object may only be initialized once,
228 /// either by the constructor, or by a call to Initialize().
230 /// This class may not be used on any thread until initialization is complete.
232 /// @param[in] object The object whose member functions are to be bound to
233 /// the <code>CompletionCallback</code> created by this
234 /// <code>CompletionCallbackFactory</code>.
235 void Initialize(T* object) {
236 PP_DCHECK(object);
237 PP_DCHECK(!object_); // May only initialize once!
238 object_ = object;
241 /// GetObject() returns the object that was passed at initialization to
242 /// Intialize().
244 /// @return the object passed to the constructor or Intialize().
245 T* GetObject() {
246 return object_;
249 /// NewCallback allocates a new, single-use <code>CompletionCallback</code>.
250 /// The <code>CompletionCallback</code> must be run in order for the memory
251 /// allocated by the methods to be freed.
253 /// @param[in] method The method to be invoked upon completion of the
254 /// operation.
256 /// @return A <code>CompletionCallback</code>.
257 template <typename Method>
258 CompletionCallback NewCallback(Method method) {
259 return NewCallbackHelper(new Dispatcher0<Method>(method));
262 /// NewOptionalCallback() allocates a new, single-use
263 /// <code>CompletionCallback</code> that might not run if the method
264 /// taking it can complete synchronously. Thus, if after passing the
265 /// CompletionCallback to a Pepper method, the method does not return
266 /// PP_OK_COMPLETIONPENDING, then you should manually call the
267 /// CompletionCallback's Run method, or memory will be leaked.
269 /// @param[in] method The method to be invoked upon completion of the
270 /// operation.
272 /// @return A <code>CompletionCallback</code>.
273 template <typename Method>
274 CompletionCallback NewOptionalCallback(Method method) {
275 CompletionCallback cc = NewCallback(method);
276 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
277 return cc;
280 /// NewCallbackWithOutput() allocates a new, single-use
281 /// <code>CompletionCallback</code> where the browser will pass an additional
282 /// parameter comtaining the result of the request. The
283 /// <code>CompletionCallback</code> must be run in order for the memory
284 /// allocated by the methods to be freed.
286 /// @param[in] method The method to be invoked upon completion of the
287 /// operation.
289 /// @return A <code>CompletionCallback</code>.
290 template <typename Output>
291 CompletionCallbackWithOutput<
292 typename internal::TypeUnwrapper<Output>::StorageType>
293 NewCallbackWithOutput(void (T::*method)(int32_t, Output)) {
294 return NewCallbackWithOutputHelper(new DispatcherWithOutput0<
295 typename internal::TypeUnwrapper<Output>::StorageType,
296 void (T::*)(int32_t, Output)>(method));
299 /// NewCallback() allocates a new, single-use <code>CompletionCallback</code>.
300 /// The <code>CompletionCallback</code> must be run in order for the memory
301 /// allocated by the methods to be freed.
303 /// @param[in] method The method to be invoked upon completion of the
304 /// operation. Method should be of type:
305 /// <code>void (T::*)(int32_t result, const A& a)</code>
307 /// @param[in] a Passed to <code>method</code> when the completion callback
308 /// runs.
310 /// @return A <code>CompletionCallback</code>.
311 template <typename Method, typename A>
312 CompletionCallback NewCallback(Method method, const A& a) {
313 return NewCallbackHelper(new Dispatcher1<Method, A>(method, a));
316 /// NewOptionalCallback() allocates a new, single-use
317 /// <code>CompletionCallback</code> that might not run if the method
318 /// taking it can complete synchronously. Thus, if after passing the
319 /// CompletionCallback to a Pepper method, the method does not return
320 /// PP_OK_COMPLETIONPENDING, then you should manually call the
321 /// CompletionCallback's Run method, or memory will be leaked.
323 /// @param[in] method The method to be invoked upon completion of the
324 /// operation. Method should be of type:
325 /// <code>void (T::*)(int32_t result, const A& a)</code>
327 /// @param[in] a Passed to <code>method</code> when the completion callback
328 /// runs.
330 /// @return A <code>CompletionCallback</code>.
331 template <typename Method, typename A>
332 CompletionCallback NewOptionalCallback(Method method, const A& a) {
333 CompletionCallback cc = NewCallback(method, a);
334 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
335 return cc;
338 /// NewCallbackWithOutput() allocates a new, single-use
339 /// <code>CompletionCallback</code> where the browser will pass an additional
340 /// parameter comtaining the result of the request. The
341 /// <code>CompletionCallback</code> must be run in order for the memory
342 /// allocated by the methods to be freed.
344 /// @param[in] method The method to be invoked upon completion of the
345 /// operation.
347 /// @param[in] a Passed to <code>method</code> when the completion callback
348 /// runs.
350 /// @return A <code>CompletionCallback</code>.
351 template <typename Output, typename A>
352 CompletionCallbackWithOutput<
353 typename internal::TypeUnwrapper<Output>::StorageType>
354 NewCallbackWithOutput(void (T::*method)(int32_t, Output, A),
355 const A& a) {
356 return NewCallbackWithOutputHelper(new DispatcherWithOutput1<
357 typename internal::TypeUnwrapper<Output>::StorageType,
358 void (T::*)(int32_t, Output, A),
359 typename internal::TypeUnwrapper<A>::StorageType>(method, a));
362 /// NewCallback() allocates a new, single-use
363 /// <code>CompletionCallback</code>.
364 /// The <code>CompletionCallback</code> must be run in order for the memory
365 /// allocated by the methods to be freed.
367 /// @param method The method taking the callback. Method should be of type:
368 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
370 /// @param[in] a Passed to <code>method</code> when the completion callback
371 /// runs.
373 /// @param[in] b Passed to <code>method</code> when the completion callback
374 /// runs.
376 /// @return A <code>CompletionCallback</code>.
377 template <typename Method, typename A, typename B>
378 CompletionCallback NewCallback(Method method, const A& a, const B& b) {
379 return NewCallbackHelper(new Dispatcher2<Method, A, B>(method, a, b));
382 /// NewOptionalCallback() allocates a new, single-use
383 /// <code>CompletionCallback</code> that might not run if the method
384 /// taking it can complete synchronously. Thus, if after passing the
385 /// CompletionCallback to a Pepper method, the method does not return
386 /// PP_OK_COMPLETIONPENDING, then you should manually call the
387 /// CompletionCallback's Run method, or memory will be leaked.
389 /// @param[in] method The method taking the callback. Method should be of
390 /// type:
391 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
393 /// @param[in] a Passed to <code>method</code> when the completion callback
394 /// runs.
396 /// @param[in] b Passed to <code>method</code> when the completion callback
397 /// runs.
399 /// @return A <code>CompletionCallback</code>.
400 template <typename Method, typename A, typename B>
401 CompletionCallback NewOptionalCallback(Method method, const A& a,
402 const B& b) {
403 CompletionCallback cc = NewCallback(method, a, b);
404 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
405 return cc;
408 /// NewCallbackWithOutput() allocates a new, single-use
409 /// <code>CompletionCallback</code> where the browser will pass an additional
410 /// parameter comtaining the result of the request. The
411 /// <code>CompletionCallback</code> must be run in order for the memory
412 /// allocated by the methods to be freed.
414 /// @param[in] method The method to be invoked upon completion of the
415 /// operation.
417 /// @param[in] a Passed to <code>method</code> when the completion callback
418 /// runs.
420 /// @param[in] b Passed to <code>method</code> when the completion callback
421 /// runs.
423 /// @return A <code>CompletionCallback</code>.
424 template <typename Output, typename A, typename B>
425 CompletionCallbackWithOutput<
426 typename internal::TypeUnwrapper<Output>::StorageType>
427 NewCallbackWithOutput(void (T::*method)(int32_t, Output, A, B),
428 const A& a,
429 const B& b) {
430 return NewCallbackWithOutputHelper(new DispatcherWithOutput2<
431 typename internal::TypeUnwrapper<Output>::StorageType,
432 void (T::*)(int32_t, Output, A, B),
433 typename internal::TypeUnwrapper<A>::StorageType,
434 typename internal::TypeUnwrapper<B>::StorageType>(method, a, b));
437 /// NewCallback() allocates a new, single-use
438 /// <code>CompletionCallback</code>.
439 /// The <code>CompletionCallback</code> must be run in order for the memory
440 /// allocated by the methods to be freed.
442 /// @param method The method taking the callback. Method should be of type:
443 /// <code>
444 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
445 /// </code>
447 /// @param[in] a Passed to <code>method</code> when the completion callback
448 /// runs.
450 /// @param[in] b Passed to <code>method</code> when the completion callback
451 /// runs.
453 /// @param[in] c Passed to <code>method</code> when the completion callback
454 /// runs.
456 /// @return A <code>CompletionCallback</code>.
457 template <typename Method, typename A, typename B, typename C>
458 CompletionCallback NewCallback(Method method, const A& a, const B& b,
459 const C& c) {
460 return NewCallbackHelper(new Dispatcher3<Method, A, B, C>(method, a, b, c));
463 /// NewOptionalCallback() allocates a new, single-use
464 /// <code>CompletionCallback</code> that might not run if the method
465 /// taking it can complete synchronously. Thus, if after passing the
466 /// CompletionCallback to a Pepper method, the method does not return
467 /// PP_OK_COMPLETIONPENDING, then you should manually call the
468 /// CompletionCallback's Run method, or memory will be leaked.
470 /// @param[in] method The method taking the callback. Method should be of
471 /// type:
472 /// <code>
473 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
474 /// </code>
476 /// @param[in] a Passed to <code>method</code> when the completion callback
477 /// runs.
479 /// @param[in] b Passed to <code>method</code> when the completion callback
480 /// runs.
482 /// @param[in] c Passed to <code>method</code> when the completion callback
483 /// runs.
485 /// @return A <code>CompletionCallback</code>.
486 template <typename Method, typename A, typename B, typename C>
487 CompletionCallback NewOptionalCallback(Method method, const A& a,
488 const B& b, const C& c) {
489 CompletionCallback cc = NewCallback(method, a, b, c);
490 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
491 return cc;
494 /// NewCallbackWithOutput() allocates a new, single-use
495 /// <code>CompletionCallback</code> where the browser will pass an additional
496 /// parameter comtaining the result of the request. The
497 /// <code>CompletionCallback</code> must be run in order for the memory
498 /// allocated by the methods to be freed.
500 /// @param method The method to be run.
502 /// @param[in] a Passed to <code>method</code> when the completion callback
503 /// runs.
505 /// @param[in] b Passed to <code>method</code> when the completion callback
506 /// runs.
508 /// @param[in] c Passed to <code>method</code> when the completion callback
509 /// runs.
511 /// @return A <code>CompletionCallback</code>.
512 template <typename Output, typename A, typename B, typename C>
513 CompletionCallbackWithOutput<
514 typename internal::TypeUnwrapper<Output>::StorageType>
515 NewCallbackWithOutput(void (T::*method)(int32_t, Output, A, B, C),
516 const A& a,
517 const B& b,
518 const C& c) {
519 return NewCallbackWithOutputHelper(new DispatcherWithOutput3<
520 typename internal::TypeUnwrapper<Output>::StorageType,
521 void (T::*)(int32_t, Output, A, B, C),
522 typename internal::TypeUnwrapper<A>::StorageType,
523 typename internal::TypeUnwrapper<B>::StorageType,
524 typename internal::TypeUnwrapper<C>::StorageType>(method, a, b, c));
527 private:
528 class BackPointer {
529 public:
530 typedef CompletionCallbackFactory<T, ThreadTraits> FactoryType;
532 explicit BackPointer(FactoryType* factory)
533 : factory_(factory) {
536 void AddRef() {
537 ref_.AddRef();
540 void Release() {
541 if (ref_.Release() == 0)
542 delete this;
545 void DropFactory() {
546 factory_ = NULL;
549 T* GetObject() {
550 return factory_ ? factory_->GetObject() : NULL;
553 private:
554 typename ThreadTraits::RefCount ref_;
555 FactoryType* factory_;
558 template <typename Dispatcher>
559 class CallbackData {
560 public:
561 // Takes ownership of the given dispatcher pointer.
562 CallbackData(BackPointer* back_pointer, Dispatcher* dispatcher)
563 : back_pointer_(back_pointer),
564 dispatcher_(dispatcher) {
565 back_pointer_->AddRef();
568 ~CallbackData() {
569 back_pointer_->Release();
570 delete dispatcher_;
573 Dispatcher* dispatcher() { return dispatcher_; }
575 static void Thunk(void* user_data, int32_t result) {
576 Self* self = static_cast<Self*>(user_data);
577 T* object = self->back_pointer_->GetObject();
579 // Please note that |object| may be NULL at this point. But we still need
580 // to call into Dispatcher::operator() in that case, so that it can do
581 // necessary cleanup.
582 (*self->dispatcher_)(object, result);
584 delete self;
587 private:
588 typedef CallbackData<Dispatcher> Self;
589 BackPointer* back_pointer_; // We own a ref to this refcounted object.
590 Dispatcher* dispatcher_; // We own this pointer.
592 // Disallow copying & assignment.
593 CallbackData(const CallbackData<Dispatcher>&);
594 CallbackData<Dispatcher>& operator=(const CallbackData<Dispatcher>&);
597 template <typename Method>
598 class Dispatcher0 {
599 public:
600 Dispatcher0() : method_(NULL) {}
601 explicit Dispatcher0(Method method) : method_(method) {
603 void operator()(T* object, int32_t result) {
604 if (object)
605 (object->*method_)(result);
607 private:
608 Method method_;
611 template <typename Output, typename Method>
612 class DispatcherWithOutput0 {
613 public:
614 typedef Output OutputType;
615 typedef internal::CallbackOutputTraits<Output> Traits;
617 DispatcherWithOutput0()
618 : method_(NULL),
619 output_() {
621 DispatcherWithOutput0(Method method)
622 : method_(method),
623 output_() {
625 void operator()(T* object, int32_t result) {
626 // We must call Traits::StorageToPluginArg() even if we don't need to call
627 // the callback anymore, otherwise we may leak resource or var references.
628 if (object)
629 (object->*method_)(result, Traits::StorageToPluginArg(output_));
630 else
631 Traits::StorageToPluginArg(output_);
633 typename Traits::StorageType* output() {
634 return &output_;
636 private:
637 Method method_;
639 typename Traits::StorageType output_;
642 template <typename Method, typename A>
643 class Dispatcher1 {
644 public:
645 Dispatcher1()
646 : method_(NULL),
647 a_() {
649 Dispatcher1(Method method, const A& a)
650 : method_(method),
651 a_(a) {
653 void operator()(T* object, int32_t result) {
654 if (object)
655 (object->*method_)(result, a_);
657 private:
658 Method method_;
659 A a_;
662 template <typename Output, typename Method, typename A>
663 class DispatcherWithOutput1 {
664 public:
665 typedef Output OutputType;
666 typedef internal::CallbackOutputTraits<Output> Traits;
668 DispatcherWithOutput1()
669 : method_(NULL),
670 a_(),
671 output_() {
673 DispatcherWithOutput1(Method method, const A& a)
674 : method_(method),
675 a_(a),
676 output_() {
678 void operator()(T* object, int32_t result) {
679 // We must call Traits::StorageToPluginArg() even if we don't need to call
680 // the callback anymore, otherwise we may leak resource or var references.
681 if (object)
682 (object->*method_)(result, Traits::StorageToPluginArg(output_), a_);
683 else
684 Traits::StorageToPluginArg(output_);
686 typename Traits::StorageType* output() {
687 return &output_;
689 private:
690 Method method_;
691 A a_;
693 typename Traits::StorageType output_;
696 template <typename Method, typename A, typename B>
697 class Dispatcher2 {
698 public:
699 Dispatcher2()
700 : method_(NULL),
701 a_(),
702 b_() {
704 Dispatcher2(Method method, const A& a, const B& b)
705 : method_(method),
706 a_(a),
707 b_(b) {
709 void operator()(T* object, int32_t result) {
710 if (object)
711 (object->*method_)(result, a_, b_);
713 private:
714 Method method_;
715 A a_;
716 B b_;
719 template <typename Output, typename Method, typename A, typename B>
720 class DispatcherWithOutput2 {
721 public:
722 typedef Output OutputType;
723 typedef internal::CallbackOutputTraits<Output> Traits;
725 DispatcherWithOutput2()
726 : method_(NULL),
727 a_(),
728 b_(),
729 output_() {
731 DispatcherWithOutput2(Method method, const A& a, const B& b)
732 : method_(method),
733 a_(a),
734 b_(b),
735 output_() {
737 void operator()(T* object, int32_t result) {
738 // We must call Traits::StorageToPluginArg() even if we don't need to call
739 // the callback anymore, otherwise we may leak resource or var references.
740 if (object)
741 (object->*method_)(result, Traits::StorageToPluginArg(output_), a_, b_);
742 else
743 Traits::StorageToPluginArg(output_);
745 typename Traits::StorageType* output() {
746 return &output_;
748 private:
749 Method method_;
750 A a_;
751 B b_;
753 typename Traits::StorageType output_;
756 template <typename Method, typename A, typename B, typename C>
757 class Dispatcher3 {
758 public:
759 Dispatcher3()
760 : method_(NULL),
761 a_(),
762 b_(),
763 c_() {
765 Dispatcher3(Method method, const A& a, const B& b, const C& c)
766 : method_(method),
767 a_(a),
768 b_(b),
769 c_(c) {
771 void operator()(T* object, int32_t result) {
772 if (object)
773 (object->*method_)(result, a_, b_, c_);
775 private:
776 Method method_;
777 A a_;
778 B b_;
779 C c_;
782 template <typename Output, typename Method, typename A, typename B,
783 typename C>
784 class DispatcherWithOutput3 {
785 public:
786 typedef Output OutputType;
787 typedef internal::CallbackOutputTraits<Output> Traits;
789 DispatcherWithOutput3()
790 : method_(NULL),
791 a_(),
792 b_(),
793 c_(),
794 output_() {
796 DispatcherWithOutput3(Method method, const A& a, const B& b, const C& c)
797 : method_(method),
798 a_(a),
799 b_(b),
800 c_(c),
801 output_() {
803 void operator()(T* object, int32_t result) {
804 // We must call Traits::StorageToPluginArg() even if we don't need to call
805 // the callback anymore, otherwise we may leak resource or var references.
806 if (object) {
807 (object->*method_)(result, Traits::StorageToPluginArg(output_),
808 a_, b_, c_);
809 } else {
810 Traits::StorageToPluginArg(output_);
813 typename Traits::StorageType* output() {
814 return &output_;
816 private:
817 Method method_;
818 A a_;
819 B b_;
820 C c_;
822 typename Traits::StorageType output_;
825 // Creates the back pointer object and takes a reference to it. This assumes
826 // either that the lock is held or that it is not needed.
827 void InitBackPointer() {
828 back_pointer_ = new BackPointer(this);
829 back_pointer_->AddRef();
832 // Releases our reference to the back pointer object and clears the pointer.
833 // This assumes either that the lock is held or that it is not needed.
834 void ResetBackPointer() {
835 back_pointer_->DropFactory();
836 back_pointer_->Release();
837 back_pointer_ = NULL;
840 // Takes ownership of the dispatcher pointer, which should be heap allocated.
841 template <typename Dispatcher>
842 CompletionCallback NewCallbackHelper(Dispatcher* dispatcher) {
843 typename ThreadTraits::AutoLock lock(lock_);
845 PP_DCHECK(object_); // Expects a non-null object!
846 return CompletionCallback(
847 &CallbackData<Dispatcher>::Thunk,
848 new CallbackData<Dispatcher>(back_pointer_, dispatcher));
851 // Takes ownership of the dispatcher pointer, which should be heap allocated.
852 template <typename Dispatcher> CompletionCallbackWithOutput<
853 typename internal::TypeUnwrapper<
854 typename Dispatcher::OutputType>::StorageType>
855 NewCallbackWithOutputHelper(Dispatcher* dispatcher) {
856 typename ThreadTraits::AutoLock lock(lock_);
858 PP_DCHECK(object_); // Expects a non-null object!
859 CallbackData<Dispatcher>* data =
860 new CallbackData<Dispatcher>(back_pointer_, dispatcher);
862 return CompletionCallbackWithOutput<typename Dispatcher::OutputType>(
863 &CallbackData<Dispatcher>::Thunk,
864 data,
865 data->dispatcher()->output());
868 // Disallowed:
869 CompletionCallbackFactory(const CompletionCallbackFactory&);
870 CompletionCallbackFactory& operator=(const CompletionCallbackFactory&);
872 // Never changed once initialized so does not need protection by the lock.
873 T* object_;
875 // Protects the back pointer.
876 typename ThreadTraits::Lock lock_;
878 // Protected by the lock. This will get reset when you do CancelAll, for
879 // example.
880 BackPointer* back_pointer_;
883 } // namespace pp
885 #endif // PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_