OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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_ |
OLD | NEW |