Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1458)

Side by Side Diff: ppapi/utility/completion_callback_factory.h

Issue 9651002: Add C++ wrappers for output parameters. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« ppapi/cpp/output_traits.h ('K') | « ppapi/ppapi_sources.gypi ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ 5 #ifndef PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_
6 #define PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ 6 #define PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_
7 7
8 #include "ppapi/cpp/completion_callback.h" 8 #include "ppapi/cpp/completion_callback.h"
9 #include "ppapi/utility/non_thread_safe_ref_count.h" 9 #include "ppapi/utility/non_thread_safe_ref_count.h"
10 10
11 namespace pp { 11 namespace pp {
12 12
13 // TypeUnwrapper --------------------------------------------------------------
14
15 namespace internal {
16
17 // The TypeUnwrapper converts references and const references to the
18 // underlying type used for storage and passing as an argument. It is for
19 // internal use only.
20 template <typename T> struct TypeUnwrapper {
21 typedef const T& ForwardType;
dmichael (off chromium) 2012/03/09 18:23:27 You don't appear to use ForwardType
22 typedef T StorageType;
23 typedef const T& ParamType;
dmichael (off chromium) 2012/03/09 18:23:27 And ParamType is unnecessary; you can just use "co
24 };
25 template <typename T> struct TypeUnwrapper<T&> {
26 typedef T& ForwardType;
27 typedef T StorageType;
28 typedef const T& ParamType;
29 };
30 template <typename T> struct TypeUnwrapper<const T&> {
31 typedef const T& ForwardType;
32 typedef T StorageType;
33 typedef const T& ParamType;
34 };
35
36 } // namespace internal
37
38 // ----------------------------------------------------------------------------
39
13 /// CompletionCallbackFactory<T> may be used to create CompletionCallback 40 /// CompletionCallbackFactory<T> may be used to create CompletionCallback
14 /// objects that are bound to member functions. 41 /// objects that are bound to member functions.
15 /// 42 ///
16 /// If a factory is destroyed, then any pending callbacks will be cancelled 43 /// If a factory is destroyed, then any pending callbacks will be cancelled
17 /// preventing any bound member functions from being called. The CancelAll() 44 /// preventing any bound member functions from being called. The CancelAll()
18 /// method allows pending callbacks to be cancelled without destroying the 45 /// method allows pending callbacks to be cancelled without destroying the
19 /// factory. 46 /// factory.
20 /// 47 ///
21 /// <strong>Note: </strong><code>CompletionCallbackFactory<T></code> isn't 48 /// <strong>Note: </strong><code>CompletionCallbackFactory<T></code> isn't
22 /// thread safe, but you can make it more thread-friendly by passing a 49 /// thread safe, but you can make it more thread-friendly by passing a
23 /// thread-safe refcounting class as the second template element. However, it 50 /// thread-safe refcounting class as the second template element. However, it
24 /// only guarantees safety for creating a callback from another thread, the 51 /// only guarantees safety for creating a callback from another thread, the
25 /// callback itself needs to execute on the same thread as the thread that 52 /// callback itself needs to execute on the same thread as the thread that
26 /// creates/destroys the factory. With this restriction, it is safe to create 53 /// creates/destroys the factory. With this restriction, it is safe to create
27 /// the <code>CompletionCallbackFactory</code> on the main thread, create 54 /// the <code>CompletionCallbackFactory</code> on the main thread, create
28 /// callbacks from any thread and pass them to CallOnMainThread(). 55 /// callbacks from any thread and pass them to CallOnMainThread().
29 /// 56 ///
30 /// <strong>Example: </strong> 57 /// <strong>Example: </strong>
31 /// 58 ///
32 /// @code 59 /// @code
33 /// 60 /// class MyClass {
34 /// class MyHandler {
35 /// public: 61 /// public:
36 /// // If an compiler warns on following using |this| in the initializer 62 /// // If an compiler warns on following using |this| in the initializer
37 /// // list, use PP_ALLOW_THIS_IN_INITIALIZER_LIST macro. 63 /// // list, use PP_ALLOW_THIS_IN_INITIALIZER_LIST macro.
38 /// MyHandler() : factory_(this), offset_(0) { 64 /// MyClass() : factory_(this) {
39 /// } 65 /// }
40 /// 66 ///
41 /// void ProcessFile(const FileRef& file) { 67 /// void OpenFile(const pp::FileRef& file) {
42 /// CompletionCallback cc = factory_.NewCallback( 68 /// pp::CompletionCallback cc = factory_.NewCallback(&MyClass::DidOpen);
43 /// &MyHandler::DidOpen); 69 /// int32_t rv = file_io_.Open(file, PP_FileOpenFlag_Read, cc);
44 /// int32_t rv = fio_.Open(file, PP_FileOpenFlag_Read, cc);
45 /// CHECK(rv == PP_OK_COMPLETIONPENDING); 70 /// CHECK(rv == PP_OK_COMPLETIONPENDING);
46 /// } 71 /// }
47 /// 72 ///
48 /// private: 73 /// private:
49 /// CompletionCallback NewCallback() {
50 /// return factory_.NewCallback(&MyHandler::DidCompleteIO);
51 /// }
52 ///
53 /// void DidOpen(int32_t result) { 74 /// void DidOpen(int32_t result) {
54 /// if (result == PP_OK) { 75 /// if (result == PP_OK) {
55 /// // The file is open, and we can begin reading. 76 /// // The file is open, and we can begin reading.
56 /// offset_ = 0; 77 /// // ...
57 /// ReadMore();
58 /// } else { 78 /// } else {
59 /// // Failed to open the file with error given by 'result'. 79 /// // Failed to open the file with error given by 'result'.
60 /// } 80 /// }
61 /// } 81 /// }
62 /// 82 ///
63 /// void DidRead(int32_t result) {
64 /// if (result > 0) {
65 /// // buf_ now contains 'result' number of bytes from the file.
66 /// ProcessBytes(buf_, result);
67 /// offset_ += result;
68 /// ReadMore();
69 /// } else {
70 /// // Done reading (possibly with an error given by 'result').
71 /// }
72 /// }
73 ///
74 /// void ReadMore() {
75 /// CompletionCallback cc =
76 /// factory_.NewOptionalCallback(&MyHandler::DidRead);
77 /// int32_t rv = fio_.Read(offset_, buf_, sizeof(buf_),
78 /// cc.pp_completion_callback());
79 /// if (rv != PP_OK_COMPLETIONPENDING)
80 /// cc.Run(rv);
81 /// }
82 ///
83 /// void ProcessBytes(const char* bytes, int32_t length) {
84 /// // Do work ...
85 /// }
86 ///
87 /// pp::CompletionCallbackFactory<MyHandler> factory_; 83 /// pp::CompletionCallbackFactory<MyHandler> factory_;
88 /// pp::FileIO fio_;
89 /// char buf_[4096];
90 /// int64_t offset_;
91 /// }; 84 /// };
92 ///
93 /// @endcode 85 /// @endcode
94 /// 86 ///
87 /// <strong>Passing additional parameters to your callback</strong>
88 ///
89 /// As a convenience, the <code>CompletionCallbackFactory</code> can optionally
90 /// create a closure with up to three bound parameters that it will pass to
91 /// your callback function. This can be useful for passing information about
92 /// the request to your callback function, which is especially useful if your
93 /// class has multiple asynchronous callbacks pending.
94 ///
95 /// For the above example, of opening a file, let's say you want to keep some
96 /// description associated with your request, you might implement your OpenFile
97 /// and DidOpen callback as follows:
98 ///
99 /// @code
100 /// void OpenFile(const pp::FileRef& file) {
101 /// std::string message = "Opening file!";
102 /// pp::CompletionCallback cc = factory_.NewCallback(&MyClass::DidOpen,
103 /// message);
104 /// int32_t rv = file_io_.Open(file, PP_FileOpenFlag_Read, cc);
105 /// CHECK(rv == PP_OK_COMPLETIONPENDING);
106 /// }
107 /// void DidOpen(int32_t result, const std::string& message) {
108 /// // "message" will be "Opening file!".
109 /// ...
110 /// }
111 /// @endcode
112 ///
113 /// <strong>Optional versus required callbacks</strong>
114 ///
115 /// When you create an "optional" callback, the browser may return the results
116 /// synchronously if they are available. This can allow for higher performance
117 /// in some cases if data is available quickly (for example, for network loads
118 /// where there may be a lot of data coming quickly). In this case, the
119 /// callback will never be run.
120 ///
121 /// When creating a new callback with the factory, there will be data allocated
122 /// on the heap that tracks the callback information and any bound arguments.
123 /// This data is freed when the callback executes. In the case of optional
124 /// callbacks, since the browser will never issue the callback, the internal
125 /// tracking data will be leaked.
126 ///
127 /// Therefore, if you use optional callbacks, it's important to manually
128 /// issue the callback to free up this data. The typical pattern is:
129 ///
130 /// @code
131 /// pp::CompletionCallback callback = callback_factory.NewOptionalCallback(
132 /// &MyClass::OnDataReady);
133 /// int32_t result = interface->GetData(callback);
134 /// if (result != PP_OK_COMPLETIONPENDING)
135 /// callback.Run(result);
136 /// @endcode
137 ///
138 /// Because of this additional complexity, it's generally recommended that
139 /// you not use optional callbacks except when performance is more important
140 /// (such as loading large resources from the network). In most other cases,
141 /// the performance difference will not be worth the additional complexity,
142 /// and most functions may never actually have the ability to complete
143 /// synchronously.
144 ///
145 /// <strong>Completion callbacks with output</strong>
146 ///
147 /// For some API calls, the browser returns data to the caller via an output
148 /// parameter. These can be difficult to manage since the output parameter
149 /// must remain valid for as long as the callback is pending. Note also that
150 /// CancelAll (or destroying the callback factory) does <i>not</i> cancel the
151 /// callback from the browser's perspective, only the execution of the callback
152 /// in the plugin code, and the output parameter will still be written to!
153 /// This means that you can't use class members as output parameters without
154 /// risking crashes.
155 ///
156 /// To make this case easier, the CompletionCallbackFactory can allocate and
157 /// manage the output data for you and pass it to your callback function. This
158 /// makes such calls more natural and less error-prone.
159 ///
160 /// To create such a callback, use NewCallbackWithOutput and specify a callback
161 /// function that takes the output parameter as its second argument. Let's say
162 /// you're calling a function GetFile which asynchronously returns a
163 /// pp::FileRef. GetFile's signature will be <code>int32_t GetFile(const
164 /// CompletionCallbackWithOutput<pp::FileRef>& callback);</code> and your
165 /// calling code would look like this:
166 ///
167 /// @code
168 /// void RequestFile() {
169 /// file_interface->GetFile(callback_factory_.NewCallbackWithOutput(
170 /// &MyClass::GotFile));
171 /// }
172 /// void GotFile(int32_t result, const pp::FileRef& file) {
173 /// if (result == PP_OK) {
174 /// ...use file...
175 /// } else {
176 /// ...handle error...
177 /// }
178 /// }
179 /// @endcode
180 ///
181 /// As with regular completion callbacks, you can optionally add up to three
182 /// bound arguments. These are passed following the output argument.
183 ///
184 /// Your callback may take the output argument as a copy (common for small
185 /// types like integers, a const reference (common for structures and
186 /// resources to avoid an extra copy), or as a non-const reference. One
187 /// optimization you can do if your callback function may take large arrays
188 /// is to accept your output argument as a non-const reference and to swap()
189 /// the argument with a vector of your own to store it. This means you don't
190 /// have to copy the buffer to consume it.
95 template <typename T, typename RefCount = NonThreadSafeRefCount> 191 template <typename T, typename RefCount = NonThreadSafeRefCount>
96 class CompletionCallbackFactory { 192 class CompletionCallbackFactory {
97 public: 193 public:
98
99 /// This constructor creates a <code>CompletionCallbackFactory</code> 194 /// This constructor creates a <code>CompletionCallbackFactory</code>
100 /// bound to an object. If the constructor is called without an argument, 195 /// bound to an object. If the constructor is called without an argument,
101 /// the default value of <code>NULL</code> is used. The user then must call 196 /// the default value of <code>NULL</code> is used. The user then must call
102 /// Initialize() to initialize the object. 197 /// Initialize() to initialize the object.
103 /// 198 ///
104 /// param[in] object Optional parameter. An object whose member functions 199 /// param[in] object Optional parameter. An object whose member functions
105 /// are to be bound to CompletionCallbacks created by this 200 /// are to be bound to CompletionCallbacks created by this
106 /// <code>CompletionCallbackFactory</code>. The default value of this 201 /// <code>CompletionCallbackFactory</code>. The default value of this
107 /// parameter is <code>NULL</code>. 202 /// parameter is <code>NULL</code>.
108 explicit CompletionCallbackFactory(T* object = NULL) 203 explicit CompletionCallbackFactory(T* object = NULL)
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 /// operation. 265 /// operation.
171 /// 266 ///
172 /// @return A <code>CompletionCallback</code>. 267 /// @return A <code>CompletionCallback</code>.
173 template <typename Method> 268 template <typename Method>
174 CompletionCallback NewOptionalCallback(Method method) { 269 CompletionCallback NewOptionalCallback(Method method) {
175 CompletionCallback cc = NewCallback(method); 270 CompletionCallback cc = NewCallback(method);
176 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); 271 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
177 return cc; 272 return cc;
178 } 273 }
179 274
275 /// NewCallbackWithOutput() allocates a new, single-use
276 /// <code>CompletionCallback</code> where the browser will pass an additional
277 /// parameter comtaining the result of the request. The
278 /// <code>CompletionCallback</code> must be run in order for the memory
279 /// allocated by the methods to be freed.
280 ///
281 /// @param[in] method The method to be invoked upon completion of the
282 /// operation.
283 ///
284 /// @return A <code>CompletionCallback</code>.
285 template <typename Output>
286 CompletionCallbackWithOutput<
287 typename internal::TypeUnwrapper<Output>::StorageType>
288 NewCallbackWithOutput(void (T::*method)(int32_t, Output)) {
289 return NewCallbackWithOutputHelper(DispatcherWithOutput0<
290 typename internal::TypeUnwrapper<Output>::StorageType,
291 void (T::*)(int32_t, Output)>(method));
292 }
293
180 /// NewCallback() allocates a new, single-use <code>CompletionCallback</code>. 294 /// NewCallback() allocates a new, single-use <code>CompletionCallback</code>.
181 /// The <code>CompletionCallback</code> must be run in order for the memory 295 /// The <code>CompletionCallback</code> must be run in order for the memory
182 /// allocated by the methods to be freed. 296 /// allocated by the methods to be freed.
183 /// 297 ///
184 /// @param[in] method The method to be invoked upon completion of the 298 /// @param[in] method The method to be invoked upon completion of the
185 /// operation. Method should be of type: 299 /// operation. Method should be of type:
186 /// <code>void (T::*)(int32_t result, const A& a)</code> 300 /// <code>void (T::*)(int32_t result, const A& a)</code>
187 /// 301 ///
188 /// @param[in] a Passed to <code>method</code> when the completion callback 302 /// @param[in] a Passed to <code>method</code> when the completion callback
189 /// runs. 303 /// runs.
(...skipping 19 matching lines...) Expand all
209 /// runs. 323 /// runs.
210 /// 324 ///
211 /// @return A <code>CompletionCallback</code>. 325 /// @return A <code>CompletionCallback</code>.
212 template <typename Method, typename A> 326 template <typename Method, typename A>
213 CompletionCallback NewOptionalCallback(Method method, const A& a) { 327 CompletionCallback NewOptionalCallback(Method method, const A& a) {
214 CompletionCallback cc = NewCallback(method, a); 328 CompletionCallback cc = NewCallback(method, a);
215 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); 329 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
216 return cc; 330 return cc;
217 } 331 }
218 332
333 /// NewCallbackWithOutput() allocates a new, single-use
334 /// <code>CompletionCallback</code> where the browser will pass an additional
335 /// parameter comtaining the result of the request. The
336 /// <code>CompletionCallback</code> must be run in order for the memory
337 /// allocated by the methods to be freed.
338 ///
339 /// @param[in] method The method to be invoked upon completion of the
340 /// operation.
341 ///
342 /// @param[in] a Passed to <code>method</code> when the completion callback
343 /// runs.
344 ///
345 /// @return A <code>CompletionCallback</code>.
346 template <typename Output, typename A>
347 CompletionCallbackWithOutput<
348 typename internal::TypeUnwrapper<Output>::StorageType>
349 NewCallbackWithOutput(void (T::*method)(int32_t, Output, A),
350 typename internal::TypeUnwrapper<A>::ParamType a) {
351 return NewCallbackWithOutputHelper(DispatcherWithOutput1<
352 typename internal::TypeUnwrapper<Output>::StorageType,
353 void (T::*)(int32_t, Output, A),
354 typename internal::TypeUnwrapper<A>::StorageType>(method, a));
355 }
356
219 /// NewCallback() allocates a new, single-use 357 /// NewCallback() allocates a new, single-use
220 /// <code>CompletionCallback</code>. 358 /// <code>CompletionCallback</code>.
221 /// The <code>CompletionCallback</code> must be run in order for the memory 359 /// The <code>CompletionCallback</code> must be run in order for the memory
222 /// allocated by the methods to be freed. 360 /// allocated by the methods to be freed.
223 /// 361 ///
224 /// @param method The method taking the callback. Method should be of type: 362 /// @param method The method taking the callback. Method should be of type:
225 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code> 363 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
226 /// 364 ///
227 /// @param[in] a Passed to <code>method</code> when the completion callback 365 /// @param[in] a Passed to <code>method</code> when the completion callback
228 /// runs. 366 /// runs.
(...skipping 27 matching lines...) Expand all
256 /// 394 ///
257 /// @return A <code>CompletionCallback</code>. 395 /// @return A <code>CompletionCallback</code>.
258 template <typename Method, typename A, typename B> 396 template <typename Method, typename A, typename B>
259 CompletionCallback NewOptionalCallback(Method method, const A& a, 397 CompletionCallback NewOptionalCallback(Method method, const A& a,
260 const B& b) { 398 const B& b) {
261 CompletionCallback cc = NewCallback(method, a, b); 399 CompletionCallback cc = NewCallback(method, a, b);
262 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); 400 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
263 return cc; 401 return cc;
264 } 402 }
265 403
404 /// NewCallbackWithOutput() allocates a new, single-use
405 /// <code>CompletionCallback</code> where the browser will pass an additional
406 /// parameter comtaining the result of the request. The
407 /// <code>CompletionCallback</code> must be run in order for the memory
408 /// allocated by the methods to be freed.
409 ///
410 /// @param[in] method The method to be run.
411 ///
412 /// @param[in] a Passed to <code>method</code> when the completion callback
413 /// runs.
414 ///
415 /// @param[in] b Passed to <code>method</code> when the completion callback
416 /// runs.
417 ///
418 /// @return A <code>CompletionCallback</code>.
419 template <typename Output, typename A, typename B>
420 CompletionCallbackWithOutput<
421 typename internal::TypeUnwrapper<Output>::StorageType>
422 NewCallbackWithOutput(void (T::*method)(int32_t, Output, A, B),
423 typename internal::TypeUnwrapper<A>::ParamType a,
424 typename internal::TypeUnwrapper<B>::ParamType b) {
425 return NewCallbackWithOutputHelper(DispatcherWithOutput2<
426 typename internal::TypeUnwrapper<Output>::StorageType,
427 void (T::*)(int32_t, Output, A, B),
428 typename internal::TypeUnwrapper<A>::StorageType,
429 typename internal::TypeUnwrapper<B>::StorageType>(method, a, b));
430 }
431
266 /// NewCallback() allocates a new, single-use 432 /// NewCallback() allocates a new, single-use
267 /// <code>CompletionCallback</code>. 433 /// <code>CompletionCallback</code>.
268 /// The <code>CompletionCallback</code> must be run in order for the memory 434 /// The <code>CompletionCallback</code> must be run in order for the memory
269 /// allocated by the methods to be freed. 435 /// allocated by the methods to be freed.
270 /// 436 ///
271 /// @param method The method taking the callback. Method should be of type: 437 /// @param method The method taking the callback. Method should be of type:
272 /// <code> 438 /// <code>
273 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) 439 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
274 /// </code> 440 /// </code>
275 /// 441 ///
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 /// 480 ///
315 /// @return A <code>CompletionCallback</code>. 481 /// @return A <code>CompletionCallback</code>.
316 template <typename Method, typename A, typename B, typename C> 482 template <typename Method, typename A, typename B, typename C>
317 CompletionCallback NewOptionalCallback(Method method, const A& a, 483 CompletionCallback NewOptionalCallback(Method method, const A& a,
318 const B& b, const C& c) { 484 const B& b, const C& c) {
319 CompletionCallback cc = NewCallback(method, a, b, c); 485 CompletionCallback cc = NewCallback(method, a, b, c);
320 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); 486 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
321 return cc; 487 return cc;
322 } 488 }
323 489
490 /// NewCallbackWithOutput() allocates a new, single-use
491 /// <code>CompletionCallback</code> where the browser will pass an additional
492 /// parameter comtaining the result of the request. The
493 /// <code>CompletionCallback</code> must be run in order for the memory
494 /// allocated by the methods to be freed.
495 ///
496 /// @param method The method to be run.
497 ///
498 /// @param[in] a Passed to <code>method</code> when the completion callback
499 /// runs.
500 ///
501 /// @param[in] b Passed to <code>method</code> when the completion callback
502 /// runs.
503 ///
504 /// @param[in] c Passed to <code>method</code> when the completion callback
505 /// runs.
506 ///
507 /// @return A <code>CompletionCallback</code>.
508 template <typename Output, typename A, typename B, typename C>
509 CompletionCallbackWithOutput<
510 typename internal::TypeUnwrapper<Output>::StorageType>
511 NewCallbackWithOutput(void (T::*method)(int32_t, Output, A, B, C),
512 typename internal::TypeUnwrapper<A>::ParamType a,
513 typename internal::TypeUnwrapper<B>::ParamType b,
514 typename internal::TypeUnwrapper<C>::ParamType c) {
515 return NewCallbackWithOutputHelper(DispatcherWithOutput3<
516 typename internal::TypeUnwrapper<Output>::StorageType,
517 void (T::*)(int32_t, Output, A, B, C),
518 typename internal::TypeUnwrapper<A>::StorageType,
519 typename internal::TypeUnwrapper<B>::StorageType,
520 typename internal::TypeUnwrapper<C>::StorageType>(method, a, b, c));
521 }
522
324 private: 523 private:
325 class BackPointer { 524 class BackPointer {
326 public: 525 public:
327 typedef CompletionCallbackFactory<T, RefCount> FactoryType; 526 typedef CompletionCallbackFactory<T, RefCount> FactoryType;
328 527
329 BackPointer(FactoryType* factory) 528 BackPointer(FactoryType* factory)
dmichael (off chromium) 2012/03/09 18:23:27 nit: explicit
330 : factory_(factory) { 529 : factory_(factory) {
331 } 530 }
332 531
333 void AddRef() { 532 void AddRef() {
334 ref_.AddRef(); 533 ref_.AddRef();
335 } 534 }
336 535
337 void Release() { 536 void Release() {
338 if (ref_.Release() == 0) 537 if (ref_.Release() == 0)
339 delete this; 538 delete this;
(...skipping 18 matching lines...) Expand all
358 CallbackData(BackPointer* back_pointer, const Dispatcher& dispatcher) 557 CallbackData(BackPointer* back_pointer, const Dispatcher& dispatcher)
359 : back_pointer_(back_pointer), 558 : back_pointer_(back_pointer),
360 dispatcher_(dispatcher) { 559 dispatcher_(dispatcher) {
361 back_pointer_->AddRef(); 560 back_pointer_->AddRef();
362 } 561 }
363 562
364 ~CallbackData() { 563 ~CallbackData() {
365 back_pointer_->Release(); 564 back_pointer_->Release();
366 } 565 }
367 566
567 Dispatcher& dispatcher() { return dispatcher_; }
568
368 static void Thunk(void* user_data, int32_t result) { 569 static void Thunk(void* user_data, int32_t result) {
369 Self* self = static_cast<Self*>(user_data); 570 Self* self = static_cast<Self*>(user_data);
370 T* object = self->back_pointer_->GetObject(); 571 T* object = self->back_pointer_->GetObject();
371 if (object) 572 if (object)
372 self->dispatcher_(object, result); 573 self->dispatcher_(object, result);
373 delete self; 574 delete self;
374 } 575 }
375 576
376 private: 577 private:
377 typedef CallbackData<Dispatcher> Self; 578 typedef CallbackData<Dispatcher> Self;
378 BackPointer* back_pointer_; 579 BackPointer* back_pointer_;
379 Dispatcher dispatcher_; 580 Dispatcher dispatcher_;
380 }; 581 };
381 582
382 template <typename Method> 583 template <typename Method>
383 class Dispatcher0 { 584 class Dispatcher0 {
384 public: 585 public:
385 Dispatcher0(Method method) : method_(method) { 586 Dispatcher0(Method method) : method_(method) {
386 } 587 }
387 void operator()(T* object, int32_t result) { 588 void operator()(T* object, int32_t result) {
388 (object->*method_)(result); 589 (object->*method_)(result);
389 } 590 }
390 private: 591 private:
391 Method method_; 592 Method method_;
392 }; 593 };
393 594
595 template <typename Output, typename Method>
596 class DispatcherWithOutput0 {
597 public:
598 typedef Output OutputType;
599 typedef internal::CallbackOutputTraits<Output> Traits;
600 DispatcherWithOutput0(Method method) : method_(method) {
dmichael (off chromium) 2012/03/09 18:23:27 nit: explicit
601 }
602 void operator()(T* object, int32_t result) {
603 (object->*method_)(result, Traits::StorageToPluginArg(output_));
604 }
605 typename Traits::StorageType* output() {
606 return &output_;
607 }
608 private:
609 Method method_;
610
611 typename Traits::StorageType output_;
612 };
613
394 template <typename Method, typename A> 614 template <typename Method, typename A>
395 class Dispatcher1 { 615 class Dispatcher1 {
396 public: 616 public:
397 Dispatcher1(Method method, const A& a) 617 Dispatcher1(Method method, const A& a)
398 : method_(method), 618 : method_(method),
399 a_(a) { 619 a_(a) {
400 } 620 }
401 void operator()(T* object, int32_t result) { 621 void operator()(T* object, int32_t result) {
402 (object->*method_)(result, a_); 622 (object->*method_)(result, a_);
403 } 623 }
404 private: 624 private:
405 Method method_; 625 Method method_;
406 A a_; 626 A a_;
407 }; 627 };
408 628
629 template <typename Output, typename Method, typename A>
630 class DispatcherWithOutput1 {
631 public:
632 typedef Output OutputType;
633 typedef internal::CallbackOutputTraits<Output> Traits;
634 DispatcherWithOutput1(Method method, const A& a)
635 : method_(method),
636 a_(a) {
637 }
638 void operator()(T* object, int32_t result) {
639 (object->*method_)(result, Traits::StorageToPluginArg(output_), a_);
640 }
641 typename Traits::StorageType* output() {
642 return &output_;
643 }
644 private:
645 Method method_;
646 A a_;
647
648 typename Traits::StorageType output_;
649 };
650
409 template <typename Method, typename A, typename B> 651 template <typename Method, typename A, typename B>
410 class Dispatcher2 { 652 class Dispatcher2 {
411 public: 653 public:
412 Dispatcher2(Method method, const A& a, const B& b) 654 Dispatcher2(Method method, const A& a, const B& b)
413 : method_(method), 655 : method_(method),
414 a_(a), 656 a_(a),
415 b_(b) { 657 b_(b) {
416 } 658 }
417 void operator()(T* object, int32_t result) { 659 void operator()(T* object, int32_t result) {
418 (object->*method_)(result, a_, b_); 660 (object->*method_)(result, a_, b_);
419 } 661 }
420 private: 662 private:
421 Method method_; 663 Method method_;
422 A a_; 664 A a_;
423 B b_; 665 B b_;
424 }; 666 };
425 667
668 template <typename Output, typename Method, typename A, typename B>
669 class DispatcherWithOutput2 {
670 public:
671 typedef Output OutputType;
672 typedef internal::CallbackOutputTraits<Output> Traits;
673 DispatcherWithOutput2(Method method, const A& a, const B& b)
674 : method_(method),
675 a_(a),
676 b_(b) {
677 }
678 void operator()(T* object, int32_t result) {
679 (object->*method_)(result, Traits::StorageToPluginArg(output_), a_, b_);
680 }
681 typename Traits::StorageType* output() {
682 return &output_;
683 }
684 private:
685 Method method_;
686 A a_;
687 B b_;
688
689 typename Traits::StorageType output_;
690 };
691
426 template <typename Method, typename A, typename B, typename C> 692 template <typename Method, typename A, typename B, typename C>
427 class Dispatcher3 { 693 class Dispatcher3 {
428 public: 694 public:
429 Dispatcher3(Method method, const A& a, const B& b, const C& c) 695 Dispatcher3(Method method, const A& a, const B& b, const C& c)
430 : method_(method), 696 : method_(method),
431 a_(a), 697 a_(a),
432 b_(b), 698 b_(b),
433 c_(c) { 699 c_(c) {
434 } 700 }
435 void operator()(T* object, int32_t result) { 701 void operator()(T* object, int32_t result) {
436 (object->*method_)(result, a_, b_, c_); 702 (object->*method_)(result, a_, b_, c_);
437 } 703 }
438 private: 704 private:
439 Method method_; 705 Method method_;
440 A a_; 706 A a_;
441 B b_; 707 B b_;
442 C c_; 708 C c_;
443 }; 709 };
444 710
711 template <typename Output, typename Method, typename A, typename B,
712 typename C>
713 class DispatcherWithOutput3 {
714 public:
715 typedef Output OutputType;
716 typedef internal::CallbackOutputTraits<Output> Traits;
717 DispatcherWithOutput3(Method method, const A& a, const B& b, const C& c)
718 : method_(method),
719 a_(a),
720 b_(b),
721 c_(c) {
722 }
723 void operator()(T* object, int32_t result) {
724 (object->*method_)(result, Traits::StorageToPluginArg(output_),
725 a_, b_, c_);
726 }
727 typename Traits::StorageType* output() {
728 return &output_;
729 }
730 private:
731 Method method_;
732 A a_;
733 B b_;
734 C c_;
735
736 typename Traits::StorageType output_;
737 };
738
445 void InitBackPointer() { 739 void InitBackPointer() {
446 back_pointer_ = new BackPointer(this); 740 back_pointer_ = new BackPointer(this);
447 back_pointer_->AddRef(); 741 back_pointer_->AddRef();
448 } 742 }
449 743
450 void ResetBackPointer() { 744 void ResetBackPointer() {
451 back_pointer_->DropFactory(); 745 back_pointer_->DropFactory();
452 back_pointer_->Release(); 746 back_pointer_->Release();
453 } 747 }
454 748
455 template <typename Dispatcher> 749 template <typename Dispatcher>
456 CompletionCallback NewCallbackHelper(const Dispatcher& dispatcher) { 750 CompletionCallback NewCallbackHelper(const Dispatcher& dispatcher) {
457 PP_DCHECK(object_); // Expects a non-null object! 751 PP_DCHECK(object_); // Expects a non-null object!
458 return CompletionCallback( 752 return CompletionCallback(
459 &CallbackData<Dispatcher>::Thunk, 753 &CallbackData<Dispatcher>::Thunk,
460 new CallbackData<Dispatcher>(back_pointer_, dispatcher)); 754 new CallbackData<Dispatcher>(back_pointer_, dispatcher));
461 } 755 }
462 756
757 template <typename Dispatcher> CompletionCallbackWithOutput<
758 typename internal::TypeUnwrapper<
759 typename Dispatcher::OutputType>::StorageType>
760 NewCallbackWithOutputHelper(const Dispatcher& dispatcher) {
761 PP_DCHECK(object_); // Expects a non-null object!
762 CallbackData<Dispatcher>* data =
763 new CallbackData<Dispatcher>(back_pointer_, dispatcher);
764
765 return CompletionCallbackWithOutput<typename Dispatcher::OutputType>(
766 &CallbackData<Dispatcher>::Thunk,
767 data,
768 data->dispatcher().output());
769 }
770
463 // Disallowed: 771 // Disallowed:
464 CompletionCallbackFactory(const CompletionCallbackFactory&); 772 CompletionCallbackFactory(const CompletionCallbackFactory&);
465 CompletionCallbackFactory& operator=(const CompletionCallbackFactory&); 773 CompletionCallbackFactory& operator=(const CompletionCallbackFactory&);
466 774
467 T* object_; 775 T* object_;
468 BackPointer* back_pointer_; 776 BackPointer* back_pointer_;
469 }; 777 };
470 778
471 } // namespace pp 779 } // namespace pp
472 780
473 #endif // PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ 781 #endif // PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_
OLDNEW
« ppapi/cpp/output_traits.h ('K') | « ppapi/ppapi_sources.gypi ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698