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.
189 /// NewExtCallbackWithOutput is similar to NewCallbackWithOutput. It creates
190 /// ext::ExtCompletionCallbackWithOutput instances which are used by APIs within
191 /// the pp::ext namespace.
192 template <typename T
, typename ThreadTraits
= ThreadSafeThreadTraits
>
193 class CompletionCallbackFactory
{
196 /// This constructor creates a <code>CompletionCallbackFactory</code>
197 /// bound to an object. If the constructor is called without an argument,
198 /// the default value of <code>NULL</code> is used. The user then must call
199 /// Initialize() to initialize the object.
201 /// param[in] object Optional parameter. An object whose member functions
202 /// are to be bound to CompletionCallbacks created by this
203 /// <code>CompletionCallbackFactory</code>. The default value of this
204 /// parameter is <code>NULL</code>.
205 explicit CompletionCallbackFactory(T
* object
= NULL
)
207 // Assume that we don't need to lock since construction should be complete
208 // before the pointer is used on another thread.
213 ~CompletionCallbackFactory() {
214 // Assume that we don't need to lock since this object should not be used
215 // from multiple threads during destruction.
219 /// CancelAll() cancels all <code>CompletionCallbacks</code> allocated from
222 typename
ThreadTraits::AutoLock
lock(lock_
);
228 /// Initialize() binds the <code>CallbackFactory</code> to a particular
229 /// object. Use this when the object is not available at
230 /// <code>CallbackFactory</code> creation, and the <code>NULL</code> default
231 /// is passed to the constructor. The object may only be initialized once,
232 /// either by the constructor, or by a call to Initialize().
234 /// This class may not be used on any thread until initialization is complete.
236 /// @param[in] object The object whose member functions are to be bound to
237 /// the <code>CompletionCallback</code> created by this
238 /// <code>CompletionCallbackFactory</code>.
239 void Initialize(T
* object
) {
241 PP_DCHECK(!object_
); // May only initialize once!
245 /// GetObject() returns the object that was passed at initialization to
248 /// @return the object passed to the constructor or Intialize().
253 /// NewCallback allocates a new, single-use <code>CompletionCallback</code>.
254 /// The <code>CompletionCallback</code> must be run in order for the memory
255 /// allocated by the methods to be freed.
257 /// @param[in] method The method to be invoked upon completion of the
260 /// @return A <code>CompletionCallback</code>.
261 template <typename Method
>
262 CompletionCallback
NewCallback(Method method
) {
263 return NewCallbackHelper(new Dispatcher0
<Method
>(method
));
266 /// NewOptionalCallback() allocates a new, single-use
267 /// <code>CompletionCallback</code> that might not run if the method
268 /// taking it can complete synchronously. Thus, if after passing the
269 /// CompletionCallback to a Pepper method, the method does not return
270 /// PP_OK_COMPLETIONPENDING, then you should manually call the
271 /// CompletionCallback's Run method, or memory will be leaked.
273 /// @param[in] method The method to be invoked upon completion of the
276 /// @return A <code>CompletionCallback</code>.
277 template <typename Method
>
278 CompletionCallback
NewOptionalCallback(Method method
) {
279 CompletionCallback cc
= NewCallback(method
);
280 cc
.set_flags(cc
.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL
);
284 /// NewCallbackWithOutput() allocates a new, single-use
285 /// <code>CompletionCallback</code> where the browser will pass an additional
286 /// parameter containing the result of the request. The
287 /// <code>CompletionCallback</code> must be run in order for the memory
288 /// allocated by the methods to be freed.
290 /// @param[in] method The method to be invoked upon completion of the
293 /// @return A <code>CompletionCallback</code>.
294 template <typename Output
>
295 CompletionCallbackWithOutput
<
296 typename
internal::TypeUnwrapper
<Output
>::StorageType
>
297 NewCallbackWithOutput(void (T::*method
)(int32_t, Output
)) {
298 typedef typename
internal::TypeUnwrapper
<Output
>::StorageType
300 typedef CompletionCallbackWithOutput
<OutputStorageType
> CallbackType
;
301 typedef DispatcherWithOutput0
<
302 typename
CallbackType::TraitsType
,
304 void (T::*)(int32_t, Output
)> DispatcherType
;
305 return NewCallbackWithOutputHelper
<CallbackType
>(
306 new DispatcherType(method
));
309 /// Similar to NewCallbackWithOutput(), but returns an
310 /// <code>ext::ExtCompletionCallbackWithOutput</code>.
311 template <typename Output
>
312 ext::ExtCompletionCallbackWithOutput
<
313 typename
internal::TypeUnwrapper
<Output
>::StorageType
>
314 NewExtCallbackWithOutput(void (T::*method
)(int32_t, Output
)) {
315 typedef typename
internal::TypeUnwrapper
<Output
>::StorageType
317 typedef ext::ExtCompletionCallbackWithOutput
<OutputStorageType
>
319 typedef DispatcherWithOutput0
<
320 typename
CallbackType::TraitsType
,
322 void (T::*)(int32_t, Output
)> DispatcherType
;
323 return NewCallbackWithOutputHelper
<CallbackType
>(
324 new DispatcherType(method
));
327 /// NewCallback() allocates a new, single-use <code>CompletionCallback</code>.
328 /// The <code>CompletionCallback</code> must be run in order for the memory
329 /// allocated by the methods to be freed.
331 /// @param[in] method The method to be invoked upon completion of the
332 /// operation. Method should be of type:
333 /// <code>void (T::*)(int32_t result, const A& a)</code>
335 /// @param[in] a Passed to <code>method</code> when the completion callback
338 /// @return A <code>CompletionCallback</code>.
339 template <typename Method
, typename A
>
340 CompletionCallback
NewCallback(Method method
, const A
& a
) {
341 return NewCallbackHelper(new Dispatcher1
<Method
, A
>(method
, a
));
344 /// NewOptionalCallback() allocates a new, single-use
345 /// <code>CompletionCallback</code> that might not run if the method
346 /// taking it can complete synchronously. Thus, if after passing the
347 /// CompletionCallback to a Pepper method, the method does not return
348 /// PP_OK_COMPLETIONPENDING, then you should manually call the
349 /// CompletionCallback's Run method, or memory will be leaked.
351 /// @param[in] method The method to be invoked upon completion of the
352 /// operation. Method should be of type:
353 /// <code>void (T::*)(int32_t result, const A& a)</code>
355 /// @param[in] a Passed to <code>method</code> when the completion callback
358 /// @return A <code>CompletionCallback</code>.
359 template <typename Method
, typename A
>
360 CompletionCallback
NewOptionalCallback(Method method
, const A
& a
) {
361 CompletionCallback cc
= NewCallback(method
, a
);
362 cc
.set_flags(cc
.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL
);
366 /// NewCallbackWithOutput() allocates a new, single-use
367 /// <code>CompletionCallback</code> where the browser will pass an additional
368 /// parameter containing the result of the request. The
369 /// <code>CompletionCallback</code> must be run in order for the memory
370 /// allocated by the methods to be freed.
372 /// @param[in] method The method to be invoked upon completion of the
375 /// @param[in] a Passed to <code>method</code> when the completion callback
378 /// @return A <code>CompletionCallback</code>.
379 template <typename Output
, typename A
>
380 CompletionCallbackWithOutput
<
381 typename
internal::TypeUnwrapper
<Output
>::StorageType
>
382 NewCallbackWithOutput(void (T::*method
)(int32_t, Output
, A
),
384 typedef typename
internal::TypeUnwrapper
<Output
>::StorageType
386 typedef CompletionCallbackWithOutput
<OutputStorageType
> CallbackType
;
387 typedef DispatcherWithOutput1
<
388 typename
CallbackType::TraitsType
,
390 void (T::*)(int32_t, Output
, A
),
391 typename
internal::TypeUnwrapper
<A
>::StorageType
> DispatcherType
;
392 return NewCallbackWithOutputHelper
<CallbackType
>(
393 new DispatcherType(method
, a
));
396 /// Similar to NewCallbackWithOutput(), but returns an
397 /// <code>ext::ExtCompletionCallbackWithOutput</code>.
398 template <typename Output
, typename A
>
399 ext::ExtCompletionCallbackWithOutput
<
400 typename
internal::TypeUnwrapper
<Output
>::StorageType
>
401 NewExtCallbackWithOutput(void (T::*method
)(int32_t, Output
, A
),
403 typedef typename
internal::TypeUnwrapper
<Output
>::StorageType
405 typedef ext::ExtCompletionCallbackWithOutput
<OutputStorageType
>
407 typedef DispatcherWithOutput1
<
408 typename
CallbackType::TraitsType
,
410 void (T::*)(int32_t, Output
, A
),
411 typename
internal::TypeUnwrapper
<A
>::StorageType
> DispatcherType
;
412 return NewCallbackWithOutputHelper
<CallbackType
>(
413 new DispatcherType(method
, a
));
416 /// NewCallback() allocates a new, single-use
417 /// <code>CompletionCallback</code>.
418 /// The <code>CompletionCallback</code> must be run in order for the memory
419 /// allocated by the methods to be freed.
421 /// @param method The method taking the callback. Method should be of type:
422 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
424 /// @param[in] a Passed to <code>method</code> when the completion callback
427 /// @param[in] b Passed to <code>method</code> when the completion callback
430 /// @return A <code>CompletionCallback</code>.
431 template <typename Method
, typename A
, typename B
>
432 CompletionCallback
NewCallback(Method method
, const A
& a
, const B
& b
) {
433 return NewCallbackHelper(new Dispatcher2
<Method
, A
, B
>(method
, a
, b
));
436 /// NewOptionalCallback() allocates a new, single-use
437 /// <code>CompletionCallback</code> that might not run if the method
438 /// taking it can complete synchronously. Thus, if after passing the
439 /// CompletionCallback to a Pepper method, the method does not return
440 /// PP_OK_COMPLETIONPENDING, then you should manually call the
441 /// CompletionCallback's Run method, or memory will be leaked.
443 /// @param[in] method The method taking the callback. Method should be of
445 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
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 /// @return A <code>CompletionCallback</code>.
454 template <typename Method
, typename A
, typename B
>
455 CompletionCallback
NewOptionalCallback(Method method
, const A
& a
,
457 CompletionCallback cc
= NewCallback(method
, a
, b
);
458 cc
.set_flags(cc
.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL
);
462 /// NewCallbackWithOutput() allocates a new, single-use
463 /// <code>CompletionCallback</code> where the browser will pass an additional
464 /// parameter containing the result of the request. The
465 /// <code>CompletionCallback</code> must be run in order for the memory
466 /// allocated by the methods to be freed.
468 /// @param[in] method The method to be invoked upon completion of the
471 /// @param[in] a Passed to <code>method</code> when the completion callback
474 /// @param[in] b Passed to <code>method</code> when the completion callback
477 /// @return A <code>CompletionCallback</code>.
478 template <typename Output
, typename A
, typename B
>
479 CompletionCallbackWithOutput
<
480 typename
internal::TypeUnwrapper
<Output
>::StorageType
>
481 NewCallbackWithOutput(void (T::*method
)(int32_t, Output
, A
, B
),
484 typedef typename
internal::TypeUnwrapper
<Output
>::StorageType
486 typedef CompletionCallbackWithOutput
<OutputStorageType
> CallbackType
;
487 typedef DispatcherWithOutput2
<
488 typename
CallbackType::TraitsType
,
490 void (T::*)(int32_t, Output
, A
, B
),
491 typename
internal::TypeUnwrapper
<A
>::StorageType
,
492 typename
internal::TypeUnwrapper
<B
>::StorageType
> DispatcherType
;
493 return NewCallbackWithOutputHelper
<CallbackType
>(
494 new DispatcherType(method
, a
, b
));
497 /// Similar to NewCallbackWithOutput(), but returns an
498 /// <code>ext::ExtCompletionCallbackWithOutput</code>.
499 template <typename Output
, typename A
, typename B
>
500 ext::ExtCompletionCallbackWithOutput
<
501 typename
internal::TypeUnwrapper
<Output
>::StorageType
>
502 NewExtCallbackWithOutput(void (T::*method
)(int32_t, Output
, A
, B
),
505 typedef typename
internal::TypeUnwrapper
<Output
>::StorageType
507 typedef ext::ExtCompletionCallbackWithOutput
<OutputStorageType
>
509 typedef DispatcherWithOutput2
<
510 typename
CallbackType::TraitsType
,
512 void (T::*)(int32_t, Output
, A
, B
),
513 typename
internal::TypeUnwrapper
<A
>::StorageType
,
514 typename
internal::TypeUnwrapper
<B
>::StorageType
> DispatcherType
;
515 return NewCallbackWithOutputHelper
<CallbackType
>(
516 new DispatcherType(method
, a
, b
));
519 /// NewCallback() allocates a new, single-use
520 /// <code>CompletionCallback</code>.
521 /// The <code>CompletionCallback</code> must be run in order for the memory
522 /// allocated by the methods to be freed.
524 /// @param method The method taking the callback. Method should be of type:
526 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
529 /// @param[in] a Passed to <code>method</code> when the completion callback
532 /// @param[in] b Passed to <code>method</code> when the completion callback
535 /// @param[in] c Passed to <code>method</code> when the completion callback
538 /// @return A <code>CompletionCallback</code>.
539 template <typename Method
, typename A
, typename B
, typename C
>
540 CompletionCallback
NewCallback(Method method
, const A
& a
, const B
& b
,
542 return NewCallbackHelper(new Dispatcher3
<Method
, A
, B
, C
>(method
, a
, b
, c
));
545 /// NewOptionalCallback() allocates a new, single-use
546 /// <code>CompletionCallback</code> that might not run if the method
547 /// taking it can complete synchronously. Thus, if after passing the
548 /// CompletionCallback to a Pepper method, the method does not return
549 /// PP_OK_COMPLETIONPENDING, then you should manually call the
550 /// CompletionCallback's Run method, or memory will be leaked.
552 /// @param[in] method The method taking the callback. Method should be of
555 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
558 /// @param[in] a Passed to <code>method</code> when the completion callback
561 /// @param[in] b Passed to <code>method</code> when the completion callback
564 /// @param[in] c Passed to <code>method</code> when the completion callback
567 /// @return A <code>CompletionCallback</code>.
568 template <typename Method
, typename A
, typename B
, typename C
>
569 CompletionCallback
NewOptionalCallback(Method method
, const A
& a
,
570 const B
& b
, const C
& c
) {
571 CompletionCallback cc
= NewCallback(method
, a
, b
, c
);
572 cc
.set_flags(cc
.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL
);
576 /// NewCallbackWithOutput() allocates a new, single-use
577 /// <code>CompletionCallback</code> where the browser will pass an additional
578 /// parameter containing the result of the request. The
579 /// <code>CompletionCallback</code> must be run in order for the memory
580 /// allocated by the methods to be freed.
582 /// @param method The method to be run.
584 /// @param[in] a Passed to <code>method</code> when the completion callback
587 /// @param[in] b Passed to <code>method</code> when the completion callback
590 /// @param[in] c Passed to <code>method</code> when the completion callback
593 /// @return A <code>CompletionCallback</code>.
594 template <typename Output
, typename A
, typename B
, typename C
>
595 CompletionCallbackWithOutput
<
596 typename
internal::TypeUnwrapper
<Output
>::StorageType
>
597 NewCallbackWithOutput(void (T::*method
)(int32_t, Output
, A
, B
, C
),
601 typedef typename
internal::TypeUnwrapper
<Output
>::StorageType
603 typedef CompletionCallbackWithOutput
<OutputStorageType
> CallbackType
;
604 typedef DispatcherWithOutput3
<
605 typename
CallbackType::TraitsType
,
607 void (T::*)(int32_t, Output
, A
, B
, C
),
608 typename
internal::TypeUnwrapper
<A
>::StorageType
,
609 typename
internal::TypeUnwrapper
<B
>::StorageType
,
610 typename
internal::TypeUnwrapper
<C
>::StorageType
> DispatcherType
;
611 return NewCallbackWithOutputHelper
<CallbackType
>(
612 new DispatcherType(method
, a
, b
, c
));
615 /// Similar to NewCallbackWithOutput(), but returns an
616 /// <code>ext::ExtCompletionCallbackWithOutput</code>.
617 template <typename Output
, typename A
, typename B
, typename C
>
618 ext::ExtCompletionCallbackWithOutput
<
619 typename
internal::TypeUnwrapper
<Output
>::StorageType
>
620 NewExtCallbackWithOutput(void (T::*method
)(int32_t, Output
, A
, B
, C
),
624 typedef typename
internal::TypeUnwrapper
<Output
>::StorageType
626 typedef ext::ExtCompletionCallbackWithOutput
<OutputStorageType
>
628 typedef DispatcherWithOutput3
<
629 typename
CallbackType::TraitsType
,
631 void (T::*)(int32_t, Output
, A
, B
, C
),
632 typename
internal::TypeUnwrapper
<A
>::StorageType
,
633 typename
internal::TypeUnwrapper
<B
>::StorageType
,
634 typename
internal::TypeUnwrapper
<C
>::StorageType
> DispatcherType
;
635 return NewCallbackWithOutputHelper
<CallbackType
>(
636 new DispatcherType(method
, a
, b
, c
));
642 typedef CompletionCallbackFactory
<T
, ThreadTraits
> FactoryType
;
644 explicit BackPointer(FactoryType
* factory
)
645 : factory_(factory
) {
653 if (ref_
.Release() == 0)
662 return factory_
? factory_
->GetObject() : NULL
;
666 typename
ThreadTraits::RefCount ref_
;
667 FactoryType
* factory_
;
670 template <typename Dispatcher
>
673 // Takes ownership of the given dispatcher pointer.
674 CallbackData(BackPointer
* back_pointer
, Dispatcher
* dispatcher
)
675 : back_pointer_(back_pointer
),
676 dispatcher_(dispatcher
) {
677 back_pointer_
->AddRef();
681 back_pointer_
->Release();
685 Dispatcher
* dispatcher() { return dispatcher_
; }
687 static void Thunk(void* user_data
, int32_t result
) {
688 Self
* self
= static_cast<Self
*>(user_data
);
689 T
* object
= self
->back_pointer_
->GetObject();
691 // Please note that |object| may be NULL at this point. But we still need
692 // to call into Dispatcher::operator() in that case, so that it can do
693 // necessary cleanup.
694 (*self
->dispatcher_
)(object
, result
);
700 typedef CallbackData
<Dispatcher
> Self
;
701 BackPointer
* back_pointer_
; // We own a ref to this refcounted object.
702 Dispatcher
* dispatcher_
; // We own this pointer.
704 // Disallow copying & assignment.
705 CallbackData(const CallbackData
<Dispatcher
>&);
706 CallbackData
<Dispatcher
>& operator=(const CallbackData
<Dispatcher
>&);
709 template <typename Method
>
712 Dispatcher0() : method_(NULL
) {}
713 explicit Dispatcher0(Method method
) : method_(method
) {
715 void operator()(T
* object
, int32_t result
) {
717 (object
->*method_
)(result
);
723 template <typename Traits
, typename Output
, typename Method
>
724 class DispatcherWithOutput0
{
726 typedef Output OutputType
;
728 DispatcherWithOutput0()
731 Traits::Initialize(&output_
);
733 DispatcherWithOutput0(Method method
)
736 Traits::Initialize(&output_
);
738 void operator()(T
* object
, int32_t result
) {
739 // We must call Traits::StorageToPluginArg() even if we don't need to call
740 // the callback anymore, otherwise we may leak resource or var references.
742 (object
->*method_
)(result
, Traits::StorageToPluginArg(output_
));
744 Traits::StorageToPluginArg(output_
);
746 typename
Traits::StorageType
* output() {
752 typename
Traits::StorageType output_
;
755 template <typename Method
, typename A
>
762 Dispatcher1(Method method
, const A
& a
)
766 void operator()(T
* object
, int32_t result
) {
768 (object
->*method_
)(result
, a_
);
775 template <typename Traits
, typename Output
, typename Method
, typename A
>
776 class DispatcherWithOutput1
{
778 typedef Output OutputType
;
780 DispatcherWithOutput1()
784 Traits::Initialize(&output_
);
786 DispatcherWithOutput1(Method method
, const A
& a
)
790 Traits::Initialize(&output_
);
792 void operator()(T
* object
, int32_t result
) {
793 // We must call Traits::StorageToPluginArg() even if we don't need to call
794 // the callback anymore, otherwise we may leak resource or var references.
796 (object
->*method_
)(result
, Traits::StorageToPluginArg(output_
), a_
);
798 Traits::StorageToPluginArg(output_
);
800 typename
Traits::StorageType
* output() {
807 typename
Traits::StorageType output_
;
810 template <typename Method
, typename A
, typename B
>
818 Dispatcher2(Method method
, const A
& a
, const B
& b
)
823 void operator()(T
* object
, int32_t result
) {
825 (object
->*method_
)(result
, a_
, b_
);
833 template <typename Traits
,
838 class DispatcherWithOutput2
{
840 typedef Output OutputType
;
842 DispatcherWithOutput2()
847 Traits::Initialize(&output_
);
849 DispatcherWithOutput2(Method method
, const A
& a
, const B
& b
)
854 Traits::Initialize(&output_
);
856 void operator()(T
* object
, int32_t result
) {
857 // We must call Traits::StorageToPluginArg() even if we don't need to call
858 // the callback anymore, otherwise we may leak resource or var references.
860 (object
->*method_
)(result
, Traits::StorageToPluginArg(output_
), a_
, b_
);
862 Traits::StorageToPluginArg(output_
);
864 typename
Traits::StorageType
* output() {
872 typename
Traits::StorageType output_
;
875 template <typename Method
, typename A
, typename B
, typename C
>
884 Dispatcher3(Method method
, const A
& a
, const B
& b
, const C
& c
)
890 void operator()(T
* object
, int32_t result
) {
892 (object
->*method_
)(result
, a_
, b_
, c_
);
901 template <typename Traits
,
907 class DispatcherWithOutput3
{
909 typedef Output OutputType
;
911 DispatcherWithOutput3()
917 Traits::Initialize(&output_
);
919 DispatcherWithOutput3(Method method
, const A
& a
, const B
& b
, const C
& c
)
925 Traits::Initialize(&output_
);
927 void operator()(T
* object
, int32_t result
) {
928 // We must call Traits::StorageToPluginArg() even if we don't need to call
929 // the callback anymore, otherwise we may leak resource or var references.
931 (object
->*method_
)(result
, Traits::StorageToPluginArg(output_
),
934 Traits::StorageToPluginArg(output_
);
937 typename
Traits::StorageType
* output() {
946 typename
Traits::StorageType output_
;
949 // Creates the back pointer object and takes a reference to it. This assumes
950 // either that the lock is held or that it is not needed.
951 void InitBackPointer() {
952 back_pointer_
= new BackPointer(this);
953 back_pointer_
->AddRef();
956 // Releases our reference to the back pointer object and clears the pointer.
957 // This assumes either that the lock is held or that it is not needed.
958 void ResetBackPointer() {
959 back_pointer_
->DropFactory();
960 back_pointer_
->Release();
961 back_pointer_
= NULL
;
964 // Takes ownership of the dispatcher pointer, which should be heap allocated.
965 template <typename Dispatcher
>
966 CompletionCallback
NewCallbackHelper(Dispatcher
* dispatcher
) {
967 typename
ThreadTraits::AutoLock
lock(lock_
);
969 PP_DCHECK(object_
); // Expects a non-null object!
970 return CompletionCallback(
971 &CallbackData
<Dispatcher
>::Thunk
,
972 new CallbackData
<Dispatcher
>(back_pointer_
, dispatcher
));
975 // Takes ownership of the dispatcher pointer, which should be heap allocated.
976 template <typename Callback
, typename Dispatcher
>
977 Callback
NewCallbackWithOutputHelper(Dispatcher
* dispatcher
) {
978 typename
ThreadTraits::AutoLock
lock(lock_
);
980 PP_DCHECK(object_
); // Expects a non-null object!
981 CallbackData
<Dispatcher
>* data
=
982 new CallbackData
<Dispatcher
>(back_pointer_
, dispatcher
);
984 return Callback(&CallbackData
<Dispatcher
>::Thunk
,
986 data
->dispatcher()->output());
990 CompletionCallbackFactory(const CompletionCallbackFactory
&);
991 CompletionCallbackFactory
& operator=(const CompletionCallbackFactory
&);
993 // Never changed once initialized so does not need protection by the lock.
996 // Protects the back pointer.
997 typename
ThreadTraits::Lock lock_
;
999 // Protected by the lock. This will get reset when you do CancelAll, for
1001 BackPointer
* back_pointer_
;
1006 #endif // PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_