Update UnusedResources lint suppressions.
[chromium-blink-merge.git] / ppapi / utility / completion_callback_factory.h
blobf755c5c2e129eec55ce44a4873fc705f04bcc0d9
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 containing 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 containing 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 containing 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 containing 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_() {
620 Traits::Initialize(&output_);
622 DispatcherWithOutput0(Method method)
623 : method_(method),
624 output_() {
625 Traits::Initialize(&output_);
627 void operator()(T* object, int32_t result) {
628 // We must call Traits::StorageToPluginArg() even if we don't need to call
629 // the callback anymore, otherwise we may leak resource or var references.
630 if (object)
631 (object->*method_)(result, Traits::StorageToPluginArg(output_));
632 else
633 Traits::StorageToPluginArg(output_);
635 typename Traits::StorageType* output() {
636 return &output_;
638 private:
639 Method method_;
641 typename Traits::StorageType output_;
644 template <typename Method, typename A>
645 class Dispatcher1 {
646 public:
647 Dispatcher1()
648 : method_(NULL),
649 a_() {
651 Dispatcher1(Method method, const A& a)
652 : method_(method),
653 a_(a) {
655 void operator()(T* object, int32_t result) {
656 if (object)
657 (object->*method_)(result, a_);
659 private:
660 Method method_;
661 A a_;
664 template <typename Output, typename Method, typename A>
665 class DispatcherWithOutput1 {
666 public:
667 typedef Output OutputType;
668 typedef internal::CallbackOutputTraits<Output> Traits;
670 DispatcherWithOutput1()
671 : method_(NULL),
672 a_(),
673 output_() {
674 Traits::Initialize(&output_);
676 DispatcherWithOutput1(Method method, const A& a)
677 : method_(method),
678 a_(a),
679 output_() {
680 Traits::Initialize(&output_);
682 void operator()(T* object, int32_t result) {
683 // We must call Traits::StorageToPluginArg() even if we don't need to call
684 // the callback anymore, otherwise we may leak resource or var references.
685 if (object)
686 (object->*method_)(result, Traits::StorageToPluginArg(output_), a_);
687 else
688 Traits::StorageToPluginArg(output_);
690 typename Traits::StorageType* output() {
691 return &output_;
693 private:
694 Method method_;
695 A a_;
697 typename Traits::StorageType output_;
700 template <typename Method, typename A, typename B>
701 class Dispatcher2 {
702 public:
703 Dispatcher2()
704 : method_(NULL),
705 a_(),
706 b_() {
708 Dispatcher2(Method method, const A& a, const B& b)
709 : method_(method),
710 a_(a),
711 b_(b) {
713 void operator()(T* object, int32_t result) {
714 if (object)
715 (object->*method_)(result, a_, b_);
717 private:
718 Method method_;
719 A a_;
720 B b_;
723 template <typename Output, typename Method, typename A, typename B>
724 class DispatcherWithOutput2 {
725 public:
726 typedef Output OutputType;
727 typedef internal::CallbackOutputTraits<Output> Traits;
729 DispatcherWithOutput2()
730 : method_(NULL),
731 a_(),
732 b_(),
733 output_() {
734 Traits::Initialize(&output_);
736 DispatcherWithOutput2(Method method, const A& a, const B& b)
737 : method_(method),
738 a_(a),
739 b_(b),
740 output_() {
741 Traits::Initialize(&output_);
743 void operator()(T* object, int32_t result) {
744 // We must call Traits::StorageToPluginArg() even if we don't need to call
745 // the callback anymore, otherwise we may leak resource or var references.
746 if (object)
747 (object->*method_)(result, Traits::StorageToPluginArg(output_), a_, b_);
748 else
749 Traits::StorageToPluginArg(output_);
751 typename Traits::StorageType* output() {
752 return &output_;
754 private:
755 Method method_;
756 A a_;
757 B b_;
759 typename Traits::StorageType output_;
762 template <typename Method, typename A, typename B, typename C>
763 class Dispatcher3 {
764 public:
765 Dispatcher3()
766 : method_(NULL),
767 a_(),
768 b_(),
769 c_() {
771 Dispatcher3(Method method, const A& a, const B& b, const C& c)
772 : method_(method),
773 a_(a),
774 b_(b),
775 c_(c) {
777 void operator()(T* object, int32_t result) {
778 if (object)
779 (object->*method_)(result, a_, b_, c_);
781 private:
782 Method method_;
783 A a_;
784 B b_;
785 C c_;
788 template <typename Output, typename Method, typename A, typename B,
789 typename C>
790 class DispatcherWithOutput3 {
791 public:
792 typedef Output OutputType;
793 typedef internal::CallbackOutputTraits<Output> Traits;
795 DispatcherWithOutput3()
796 : method_(NULL),
797 a_(),
798 b_(),
799 c_(),
800 output_() {
801 Traits::Initialize(&output_);
803 DispatcherWithOutput3(Method method, const A& a, const B& b, const C& c)
804 : method_(method),
805 a_(a),
806 b_(b),
807 c_(c),
808 output_() {
809 Traits::Initialize(&output_);
811 void operator()(T* object, int32_t result) {
812 // We must call Traits::StorageToPluginArg() even if we don't need to call
813 // the callback anymore, otherwise we may leak resource or var references.
814 if (object) {
815 (object->*method_)(result, Traits::StorageToPluginArg(output_),
816 a_, b_, c_);
817 } else {
818 Traits::StorageToPluginArg(output_);
821 typename Traits::StorageType* output() {
822 return &output_;
824 private:
825 Method method_;
826 A a_;
827 B b_;
828 C c_;
830 typename Traits::StorageType output_;
833 // Creates the back pointer object and takes a reference to it. This assumes
834 // either that the lock is held or that it is not needed.
835 void InitBackPointer() {
836 back_pointer_ = new BackPointer(this);
837 back_pointer_->AddRef();
840 // Releases our reference to the back pointer object and clears the pointer.
841 // This assumes either that the lock is held or that it is not needed.
842 void ResetBackPointer() {
843 back_pointer_->DropFactory();
844 back_pointer_->Release();
845 back_pointer_ = NULL;
848 // Takes ownership of the dispatcher pointer, which should be heap allocated.
849 template <typename Dispatcher>
850 CompletionCallback NewCallbackHelper(Dispatcher* dispatcher) {
851 typename ThreadTraits::AutoLock lock(lock_);
853 PP_DCHECK(object_); // Expects a non-null object!
854 return CompletionCallback(
855 &CallbackData<Dispatcher>::Thunk,
856 new CallbackData<Dispatcher>(back_pointer_, dispatcher));
859 // Takes ownership of the dispatcher pointer, which should be heap allocated.
860 template <typename Dispatcher> CompletionCallbackWithOutput<
861 typename internal::TypeUnwrapper<
862 typename Dispatcher::OutputType>::StorageType>
863 NewCallbackWithOutputHelper(Dispatcher* dispatcher) {
864 typename ThreadTraits::AutoLock lock(lock_);
866 PP_DCHECK(object_); // Expects a non-null object!
867 CallbackData<Dispatcher>* data =
868 new CallbackData<Dispatcher>(back_pointer_, dispatcher);
870 return CompletionCallbackWithOutput<typename Dispatcher::OutputType>(
871 &CallbackData<Dispatcher>::Thunk,
872 data,
873 data->dispatcher()->output());
876 // Disallowed:
877 CompletionCallbackFactory(const CompletionCallbackFactory&);
878 CompletionCallbackFactory& operator=(const CompletionCallbackFactory&);
880 // Never changed once initialized so does not need protection by the lock.
881 T* object_;
883 // Protects the back pointer.
884 typename ThreadTraits::Lock lock_;
886 // Protected by the lock. This will get reset when you do CancelAll, for
887 // example.
888 BackPointer* back_pointer_;
891 } // namespace pp
893 #endif // PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_