Chromium Code Reviews| 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 |