cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / ppapi / utility / completion_callback_factory.h
blob3af860a098b83ac0c8339906f415b493dc59a45f
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.
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 {
194 public:
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)
206 : object_(object) {
207 // Assume that we don't need to lock since construction should be complete
208 // before the pointer is used on another thread.
209 InitBackPointer();
212 /// Destructor.
213 ~CompletionCallbackFactory() {
214 // Assume that we don't need to lock since this object should not be used
215 // from multiple threads during destruction.
216 ResetBackPointer();
219 /// CancelAll() cancels all <code>CompletionCallbacks</code> allocated from
220 /// this factory.
221 void CancelAll() {
222 typename ThreadTraits::AutoLock lock(lock_);
224 ResetBackPointer();
225 InitBackPointer();
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) {
240 PP_DCHECK(object);
241 PP_DCHECK(!object_); // May only initialize once!
242 object_ = object;
245 /// GetObject() returns the object that was passed at initialization to
246 /// Intialize().
248 /// @return the object passed to the constructor or Intialize().
249 T* GetObject() {
250 return object_;
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
258 /// operation.
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
274 /// operation.
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);
281 return cc;
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
291 /// operation.
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
299 OutputStorageType;
300 typedef CompletionCallbackWithOutput<OutputStorageType> CallbackType;
301 typedef DispatcherWithOutput0<
302 typename CallbackType::TraitsType,
303 OutputStorageType,
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
316 OutputStorageType;
317 typedef ext::ExtCompletionCallbackWithOutput<OutputStorageType>
318 CallbackType;
319 typedef DispatcherWithOutput0<
320 typename CallbackType::TraitsType,
321 OutputStorageType,
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
336 /// runs.
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
356 /// runs.
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);
363 return cc;
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
373 /// operation.
375 /// @param[in] a Passed to <code>method</code> when the completion callback
376 /// runs.
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),
383 const A& a) {
384 typedef typename internal::TypeUnwrapper<Output>::StorageType
385 OutputStorageType;
386 typedef CompletionCallbackWithOutput<OutputStorageType> CallbackType;
387 typedef DispatcherWithOutput1<
388 typename CallbackType::TraitsType,
389 OutputStorageType,
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),
402 const A& a) {
403 typedef typename internal::TypeUnwrapper<Output>::StorageType
404 OutputStorageType;
405 typedef ext::ExtCompletionCallbackWithOutput<OutputStorageType>
406 CallbackType;
407 typedef DispatcherWithOutput1<
408 typename CallbackType::TraitsType,
409 OutputStorageType,
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
425 /// runs.
427 /// @param[in] b Passed to <code>method</code> when the completion callback
428 /// runs.
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
444 /// type:
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
448 /// runs.
450 /// @param[in] b Passed to <code>method</code> when the completion callback
451 /// runs.
453 /// @return A <code>CompletionCallback</code>.
454 template <typename Method, typename A, typename B>
455 CompletionCallback NewOptionalCallback(Method method, const A& a,
456 const B& b) {
457 CompletionCallback cc = NewCallback(method, a, b);
458 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
459 return cc;
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
469 /// operation.
471 /// @param[in] a Passed to <code>method</code> when the completion callback
472 /// runs.
474 /// @param[in] b Passed to <code>method</code> when the completion callback
475 /// runs.
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),
482 const A& a,
483 const B& b) {
484 typedef typename internal::TypeUnwrapper<Output>::StorageType
485 OutputStorageType;
486 typedef CompletionCallbackWithOutput<OutputStorageType> CallbackType;
487 typedef DispatcherWithOutput2<
488 typename CallbackType::TraitsType,
489 OutputStorageType,
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),
503 const A& a,
504 const B& b) {
505 typedef typename internal::TypeUnwrapper<Output>::StorageType
506 OutputStorageType;
507 typedef ext::ExtCompletionCallbackWithOutput<OutputStorageType>
508 CallbackType;
509 typedef DispatcherWithOutput2<
510 typename CallbackType::TraitsType,
511 OutputStorageType,
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:
525 /// <code>
526 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
527 /// </code>
529 /// @param[in] a Passed to <code>method</code> when the completion callback
530 /// runs.
532 /// @param[in] b Passed to <code>method</code> when the completion callback
533 /// runs.
535 /// @param[in] c Passed to <code>method</code> when the completion callback
536 /// runs.
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,
541 const C& c) {
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
553 /// type:
554 /// <code>
555 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
556 /// </code>
558 /// @param[in] a Passed to <code>method</code> when the completion callback
559 /// runs.
561 /// @param[in] b Passed to <code>method</code> when the completion callback
562 /// runs.
564 /// @param[in] c Passed to <code>method</code> when the completion callback
565 /// runs.
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);
573 return cc;
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
585 /// runs.
587 /// @param[in] b Passed to <code>method</code> when the completion callback
588 /// runs.
590 /// @param[in] c Passed to <code>method</code> when the completion callback
591 /// runs.
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),
598 const A& a,
599 const B& b,
600 const C& c) {
601 typedef typename internal::TypeUnwrapper<Output>::StorageType
602 OutputStorageType;
603 typedef CompletionCallbackWithOutput<OutputStorageType> CallbackType;
604 typedef DispatcherWithOutput3<
605 typename CallbackType::TraitsType,
606 OutputStorageType,
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),
621 const A& a,
622 const B& b,
623 const C& c) {
624 typedef typename internal::TypeUnwrapper<Output>::StorageType
625 OutputStorageType;
626 typedef ext::ExtCompletionCallbackWithOutput<OutputStorageType>
627 CallbackType;
628 typedef DispatcherWithOutput3<
629 typename CallbackType::TraitsType,
630 OutputStorageType,
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));
639 private:
640 class BackPointer {
641 public:
642 typedef CompletionCallbackFactory<T, ThreadTraits> FactoryType;
644 explicit BackPointer(FactoryType* factory)
645 : factory_(factory) {
648 void AddRef() {
649 ref_.AddRef();
652 void Release() {
653 if (ref_.Release() == 0)
654 delete this;
657 void DropFactory() {
658 factory_ = NULL;
661 T* GetObject() {
662 return factory_ ? factory_->GetObject() : NULL;
665 private:
666 typename ThreadTraits::RefCount ref_;
667 FactoryType* factory_;
670 template <typename Dispatcher>
671 class CallbackData {
672 public:
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();
680 ~CallbackData() {
681 back_pointer_->Release();
682 delete dispatcher_;
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);
696 delete self;
699 private:
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>
710 class Dispatcher0 {
711 public:
712 Dispatcher0() : method_(NULL) {}
713 explicit Dispatcher0(Method method) : method_(method) {
715 void operator()(T* object, int32_t result) {
716 if (object)
717 (object->*method_)(result);
719 private:
720 Method method_;
723 template <typename Traits, typename Output, typename Method>
724 class DispatcherWithOutput0 {
725 public:
726 typedef Output OutputType;
728 DispatcherWithOutput0()
729 : method_(NULL),
730 output_() {
731 Traits::Initialize(&output_);
733 DispatcherWithOutput0(Method method)
734 : method_(method),
735 output_() {
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.
741 if (object)
742 (object->*method_)(result, Traits::StorageToPluginArg(output_));
743 else
744 Traits::StorageToPluginArg(output_);
746 typename Traits::StorageType* output() {
747 return &output_;
749 private:
750 Method method_;
752 typename Traits::StorageType output_;
755 template <typename Method, typename A>
756 class Dispatcher1 {
757 public:
758 Dispatcher1()
759 : method_(NULL),
760 a_() {
762 Dispatcher1(Method method, const A& a)
763 : method_(method),
764 a_(a) {
766 void operator()(T* object, int32_t result) {
767 if (object)
768 (object->*method_)(result, a_);
770 private:
771 Method method_;
772 A a_;
775 template <typename Traits, typename Output, typename Method, typename A>
776 class DispatcherWithOutput1 {
777 public:
778 typedef Output OutputType;
780 DispatcherWithOutput1()
781 : method_(NULL),
782 a_(),
783 output_() {
784 Traits::Initialize(&output_);
786 DispatcherWithOutput1(Method method, const A& a)
787 : method_(method),
788 a_(a),
789 output_() {
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.
795 if (object)
796 (object->*method_)(result, Traits::StorageToPluginArg(output_), a_);
797 else
798 Traits::StorageToPluginArg(output_);
800 typename Traits::StorageType* output() {
801 return &output_;
803 private:
804 Method method_;
805 A a_;
807 typename Traits::StorageType output_;
810 template <typename Method, typename A, typename B>
811 class Dispatcher2 {
812 public:
813 Dispatcher2()
814 : method_(NULL),
815 a_(),
816 b_() {
818 Dispatcher2(Method method, const A& a, const B& b)
819 : method_(method),
820 a_(a),
821 b_(b) {
823 void operator()(T* object, int32_t result) {
824 if (object)
825 (object->*method_)(result, a_, b_);
827 private:
828 Method method_;
829 A a_;
830 B b_;
833 template <typename Traits,
834 typename Output,
835 typename Method,
836 typename A,
837 typename B>
838 class DispatcherWithOutput2 {
839 public:
840 typedef Output OutputType;
842 DispatcherWithOutput2()
843 : method_(NULL),
844 a_(),
845 b_(),
846 output_() {
847 Traits::Initialize(&output_);
849 DispatcherWithOutput2(Method method, const A& a, const B& b)
850 : method_(method),
851 a_(a),
852 b_(b),
853 output_() {
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.
859 if (object)
860 (object->*method_)(result, Traits::StorageToPluginArg(output_), a_, b_);
861 else
862 Traits::StorageToPluginArg(output_);
864 typename Traits::StorageType* output() {
865 return &output_;
867 private:
868 Method method_;
869 A a_;
870 B b_;
872 typename Traits::StorageType output_;
875 template <typename Method, typename A, typename B, typename C>
876 class Dispatcher3 {
877 public:
878 Dispatcher3()
879 : method_(NULL),
880 a_(),
881 b_(),
882 c_() {
884 Dispatcher3(Method method, const A& a, const B& b, const C& c)
885 : method_(method),
886 a_(a),
887 b_(b),
888 c_(c) {
890 void operator()(T* object, int32_t result) {
891 if (object)
892 (object->*method_)(result, a_, b_, c_);
894 private:
895 Method method_;
896 A a_;
897 B b_;
898 C c_;
901 template <typename Traits,
902 typename Output,
903 typename Method,
904 typename A,
905 typename B,
906 typename C>
907 class DispatcherWithOutput3 {
908 public:
909 typedef Output OutputType;
911 DispatcherWithOutput3()
912 : method_(NULL),
913 a_(),
914 b_(),
915 c_(),
916 output_() {
917 Traits::Initialize(&output_);
919 DispatcherWithOutput3(Method method, const A& a, const B& b, const C& c)
920 : method_(method),
921 a_(a),
922 b_(b),
923 c_(c),
924 output_() {
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.
930 if (object) {
931 (object->*method_)(result, Traits::StorageToPluginArg(output_),
932 a_, b_, c_);
933 } else {
934 Traits::StorageToPluginArg(output_);
937 typename Traits::StorageType* output() {
938 return &output_;
940 private:
941 Method method_;
942 A a_;
943 B b_;
944 C c_;
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,
985 data,
986 data->dispatcher()->output());
989 // Disallowed:
990 CompletionCallbackFactory(const CompletionCallbackFactory&);
991 CompletionCallbackFactory& operator=(const CompletionCallbackFactory&);
993 // Never changed once initialized so does not need protection by the lock.
994 T* object_;
996 // Protects the back pointer.
997 typename ThreadTraits::Lock lock_;
999 // Protected by the lock. This will get reset when you do CancelAll, for
1000 // example.
1001 BackPointer* back_pointer_;
1004 } // namespace pp
1006 #endif // PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_