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"
12 /// This file defines the API to create CompletionCallback objects that are
13 /// bound to member functions.
16 // TypeUnwrapper --------------------------------------------------------------
20 // The TypeUnwrapper converts references and const references to the
21 // underlying type used for storage and passing as an argument. It is for
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.
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
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().
54 /// <strong>Example: </strong>
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) {
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);
71 /// void DidOpen(int32_t result) {
72 /// if (result == PP_OK) {
73 /// // The file is open, and we can begin reading.
76 /// // Failed to open the file with error given by 'result'.
80 /// pp::CompletionCallbackFactory<MyClass> factory_;
84 /// <strong>Passing additional parameters to your callback</strong>
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.
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:
97 /// void OpenFile(const pp::FileRef& file) {
98 /// std::string message = "Opening file!";
99 /// pp::CompletionCallback cc = factory_.NewCallback(&MyClass::DidOpen,
101 /// int32_t rv = file_io_.Open(file, PP_FileOpenFlag_Read, cc);
102 /// CHECK(rv == PP_OK_COMPLETIONPENDING);
104 /// void DidOpen(int32_t result, const std::string& message) {
105 /// // "message" will be "Opening file!".
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:
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);
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
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
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:
165 /// void RequestFile() {
166 /// file_interface->GetFile(callback_factory_.NewCallbackWithOutput(
167 /// &MyClass::GotFile));
169 /// void GotFile(int32_t result, const pp::FileRef& file) {
170 /// if (result == PP_OK) {
173 /// ...handle error...
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
{
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
)
203 // Assume that we don't need to lock since construction should be complete
204 // before the pointer is used on another thread.
209 ~CompletionCallbackFactory() {
210 // Assume that we don't need to lock since this object should not be used
211 // from multiple threads during destruction.
215 /// CancelAll() cancels all <code>CompletionCallbacks</code> allocated from
218 typename
ThreadTraits::AutoLock
lock(lock_
);
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
) {
237 PP_DCHECK(!object_
); // May only initialize once!
241 /// GetObject() returns the object that was passed at initialization to
244 /// @return the object passed to the constructor or Intialize().
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
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
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
);
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
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
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
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
);
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
347 /// @param[in] a Passed to <code>method</code> when the completion callback
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
),
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
373 /// @param[in] b Passed to <code>method</code> when the completion callback
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
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
396 /// @param[in] b Passed to <code>method</code> when the completion callback
399 /// @return A <code>CompletionCallback</code>.
400 template <typename Method
, typename A
, typename B
>
401 CompletionCallback
NewOptionalCallback(Method method
, const A
& a
,
403 CompletionCallback cc
= NewCallback(method
, a
, b
);
404 cc
.set_flags(cc
.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL
);
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
417 /// @param[in] a Passed to <code>method</code> when the completion callback
420 /// @param[in] b Passed to <code>method</code> when the completion callback
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
),
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:
444 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
447 /// @param[in] a Passed to <code>method</code> when the completion callback
450 /// @param[in] b Passed to <code>method</code> when the completion callback
453 /// @param[in] c Passed to <code>method</code> when the completion callback
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
,
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
473 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
476 /// @param[in] a Passed to <code>method</code> when the completion callback
479 /// @param[in] b Passed to <code>method</code> when the completion callback
482 /// @param[in] c Passed to <code>method</code> when the completion callback
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
);
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
505 /// @param[in] b Passed to <code>method</code> when the completion callback
508 /// @param[in] c Passed to <code>method</code> when the completion callback
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
),
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
));
530 typedef CompletionCallbackFactory
<T
, ThreadTraits
> FactoryType
;
532 explicit BackPointer(FactoryType
* factory
)
533 : factory_(factory
) {
541 if (ref_
.Release() == 0)
550 return factory_
? factory_
->GetObject() : NULL
;
554 typename
ThreadTraits::RefCount ref_
;
555 FactoryType
* factory_
;
558 template <typename Dispatcher
>
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();
569 back_pointer_
->Release();
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
);
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
>
600 Dispatcher0() : method_(NULL
) {}
601 explicit Dispatcher0(Method method
) : method_(method
) {
603 void operator()(T
* object
, int32_t result
) {
605 (object
->*method_
)(result
);
611 template <typename Output
, typename Method
>
612 class DispatcherWithOutput0
{
614 typedef Output OutputType
;
615 typedef internal::CallbackOutputTraits
<Output
> Traits
;
617 DispatcherWithOutput0()
620 Traits::Initialize(&output_
);
622 DispatcherWithOutput0(Method method
)
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.
631 (object
->*method_
)(result
, Traits::StorageToPluginArg(output_
));
633 Traits::StorageToPluginArg(output_
);
635 typename
Traits::StorageType
* output() {
641 typename
Traits::StorageType output_
;
644 template <typename Method
, typename A
>
651 Dispatcher1(Method method
, const A
& a
)
655 void operator()(T
* object
, int32_t result
) {
657 (object
->*method_
)(result
, a_
);
664 template <typename Output
, typename Method
, typename A
>
665 class DispatcherWithOutput1
{
667 typedef Output OutputType
;
668 typedef internal::CallbackOutputTraits
<Output
> Traits
;
670 DispatcherWithOutput1()
674 Traits::Initialize(&output_
);
676 DispatcherWithOutput1(Method method
, const A
& a
)
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.
686 (object
->*method_
)(result
, Traits::StorageToPluginArg(output_
), a_
);
688 Traits::StorageToPluginArg(output_
);
690 typename
Traits::StorageType
* output() {
697 typename
Traits::StorageType output_
;
700 template <typename Method
, typename A
, typename B
>
708 Dispatcher2(Method method
, const A
& a
, const B
& b
)
713 void operator()(T
* object
, int32_t result
) {
715 (object
->*method_
)(result
, a_
, b_
);
723 template <typename Output
, typename Method
, typename A
, typename B
>
724 class DispatcherWithOutput2
{
726 typedef Output OutputType
;
727 typedef internal::CallbackOutputTraits
<Output
> Traits
;
729 DispatcherWithOutput2()
734 Traits::Initialize(&output_
);
736 DispatcherWithOutput2(Method method
, const A
& a
, const B
& b
)
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.
747 (object
->*method_
)(result
, Traits::StorageToPluginArg(output_
), a_
, b_
);
749 Traits::StorageToPluginArg(output_
);
751 typename
Traits::StorageType
* output() {
759 typename
Traits::StorageType output_
;
762 template <typename Method
, typename A
, typename B
, typename C
>
771 Dispatcher3(Method method
, const A
& a
, const B
& b
, const C
& c
)
777 void operator()(T
* object
, int32_t result
) {
779 (object
->*method_
)(result
, a_
, b_
, c_
);
788 template <typename Output
, typename Method
, typename A
, typename B
,
790 class DispatcherWithOutput3
{
792 typedef Output OutputType
;
793 typedef internal::CallbackOutputTraits
<Output
> Traits
;
795 DispatcherWithOutput3()
801 Traits::Initialize(&output_
);
803 DispatcherWithOutput3(Method method
, const A
& a
, const B
& b
, const C
& c
)
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.
815 (object
->*method_
)(result
, Traits::StorageToPluginArg(output_
),
818 Traits::StorageToPluginArg(output_
);
821 typename
Traits::StorageType
* output() {
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
,
873 data
->dispatcher()->output());
877 CompletionCallbackFactory(const CompletionCallbackFactory
&);
878 CompletionCallbackFactory
& operator=(const CompletionCallbackFactory
&);
880 // Never changed once initialized so does not need protection by the lock.
883 // Protects the back pointer.
884 typename
ThreadTraits::Lock lock_
;
886 // Protected by the lock. This will get reset when you do CancelAll, for
888 BackPointer
* back_pointer_
;
893 #endif // PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_