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