OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 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_.NewCallback( | 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) { | 77 /// pp::CompletionCallbackFactory<MyClass> factory_; |
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_; | |
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 | 188 |
99 /// This constructor creates a <code>CompletionCallbackFactory</code> | 189 /// This constructor creates a <code>CompletionCallbackFactory</code> |
100 /// bound to an object. If the constructor is called without an argument, | 190 /// 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 | 191 /// the default value of <code>NULL</code> is used. The user then must call |
102 /// Initialize() to initialize the object. | 192 /// Initialize() to initialize the object. |
103 /// | 193 /// |
104 /// param[in] object Optional parameter. An object whose member functions | 194 /// param[in] object Optional parameter. An object whose member functions |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 /// The <code>CompletionCallback</code> must be run in order for the memory | 238 /// The <code>CompletionCallback</code> must be run in order for the memory |
149 /// allocated by the methods to be freed. | 239 /// allocated by the methods to be freed. |
150 /// | 240 /// |
151 /// @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 |
152 /// operation. | 242 /// operation. |
153 /// | 243 /// |
154 /// @return A <code>CompletionCallback</code>. | 244 /// @return A <code>CompletionCallback</code>. |
155 template <typename Method> | 245 template <typename Method> |
156 CompletionCallback NewCallback(Method method) { | 246 CompletionCallback NewCallback(Method method) { |
157 PP_DCHECK(object_); | 247 PP_DCHECK(object_); |
158 return NewCallbackHelper(Dispatcher0<Method>(method)); | 248 return NewCallbackHelper(new Dispatcher0<Method>(method)); |
159 } | 249 } |
160 | 250 |
161 /// NewOptionalCallback() allocates a new, single-use | 251 /// NewOptionalCallback() allocates a new, single-use |
162 /// <code>CompletionCallback</code> that might not run if the method | 252 /// <code>CompletionCallback</code> that might not run if the method |
163 /// taking it can complete synchronously. Thus, if after passing the | 253 /// taking it can complete synchronously. Thus, if after passing the |
164 /// CompletionCallback to a Pepper method, the method does not return | 254 /// CompletionCallback to a Pepper method, the method does not return |
165 /// PP_OK_COMPLETIONPENDING, then you should manually call the | 255 /// PP_OK_COMPLETIONPENDING, then you should manually call the |
166 /// CompletionCallback's Run method, or memory will be leaked. | 256 /// CompletionCallback's Run method, or memory will be leaked. |
167 /// | 257 /// |
168 /// @param[in] method The method to be invoked upon completion of the | 258 /// @param[in] method The method to be invoked upon completion of the |
169 /// operation. | 259 /// operation. |
170 /// | 260 /// |
171 /// @return A <code>CompletionCallback</code>. | 261 /// @return A <code>CompletionCallback</code>. |
172 template <typename Method> | 262 template <typename Method> |
173 CompletionCallback NewOptionalCallback(Method method) { | 263 CompletionCallback NewOptionalCallback(Method method) { |
174 CompletionCallback cc = NewCallback(method); | 264 CompletionCallback cc = NewCallback(method); |
175 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); | 265 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
176 return cc; | 266 return cc; |
177 } | 267 } |
178 | 268 |
| 269 /// NewCallbackWithOutput() allocates a new, single-use |
| 270 /// <code>CompletionCallback</code> where the browser will pass an additional |
| 271 /// parameter comtaining the result of the request. The |
| 272 /// <code>CompletionCallback</code> must be run in order for the memory |
| 273 /// allocated by the methods to be freed. |
| 274 /// |
| 275 /// @param[in] method The method to be invoked upon completion of the |
| 276 /// operation. |
| 277 /// |
| 278 /// @return A <code>CompletionCallback</code>. |
| 279 template <typename Output> |
| 280 CompletionCallbackWithOutput< |
| 281 typename internal::TypeUnwrapper<Output>::StorageType> |
| 282 NewCallbackWithOutput(void (T::*method)(int32_t, Output)) { |
| 283 return NewCallbackWithOutputHelper(new DispatcherWithOutput0< |
| 284 typename internal::TypeUnwrapper<Output>::StorageType, |
| 285 void (T::*)(int32_t, Output)>(method)); |
| 286 } |
| 287 |
179 /// NewCallback() allocates a new, single-use <code>CompletionCallback</code>. | 288 /// NewCallback() allocates a new, single-use <code>CompletionCallback</code>. |
180 /// The <code>CompletionCallback</code> must be run in order for the memory | 289 /// The <code>CompletionCallback</code> must be run in order for the memory |
181 /// allocated by the methods to be freed. | 290 /// allocated by the methods to be freed. |
182 /// | 291 /// |
183 /// @param[in] method The method to be invoked upon completion of the | 292 /// @param[in] method The method to be invoked upon completion of the |
184 /// operation. Method should be of type: | 293 /// operation. Method should be of type: |
185 /// <code>void (T::*)(int32_t result, const A& a)</code> | 294 /// <code>void (T::*)(int32_t result, const A& a)</code> |
186 /// | 295 /// |
187 /// @param[in] a Passed to <code>method</code> when the completion callback | 296 /// @param[in] a Passed to <code>method</code> when the completion callback |
188 /// runs. | 297 /// runs. |
189 /// | 298 /// |
190 /// @return A <code>CompletionCallback</code>. | 299 /// @return A <code>CompletionCallback</code>. |
191 template <typename Method, typename A> | 300 template <typename Method, typename A> |
192 CompletionCallback NewCallback(Method method, const A& a) { | 301 CompletionCallback NewCallback(Method method, const A& a) { |
193 PP_DCHECK(object_); | 302 PP_DCHECK(object_); |
194 return NewCallbackHelper(Dispatcher1<Method, A>(method, a)); | 303 return NewCallbackHelper(new Dispatcher1<Method, A>(method, a)); |
195 } | 304 } |
196 | 305 |
197 /// NewOptionalCallback() allocates a new, single-use | 306 /// NewOptionalCallback() allocates a new, single-use |
198 /// <code>CompletionCallback</code> that might not run if the method | 307 /// <code>CompletionCallback</code> that might not run if the method |
199 /// taking it can complete synchronously. Thus, if after passing the | 308 /// taking it can complete synchronously. Thus, if after passing the |
200 /// CompletionCallback to a Pepper method, the method does not return | 309 /// CompletionCallback to a Pepper method, the method does not return |
201 /// PP_OK_COMPLETIONPENDING, then you should manually call the | 310 /// PP_OK_COMPLETIONPENDING, then you should manually call the |
202 /// CompletionCallback's Run method, or memory will be leaked. | 311 /// CompletionCallback's Run method, or memory will be leaked. |
203 /// | 312 /// |
204 /// @param[in] method The method to be invoked upon completion of the | 313 /// @param[in] method The method to be invoked upon completion of the |
205 /// operation. Method should be of type: | 314 /// operation. Method should be of type: |
206 /// <code>void (T::*)(int32_t result, const A& a)</code> | 315 /// <code>void (T::*)(int32_t result, const A& a)</code> |
207 /// | 316 /// |
208 /// @param[in] a Passed to <code>method</code> when the completion callback | 317 /// @param[in] a Passed to <code>method</code> when the completion callback |
209 /// runs. | 318 /// runs. |
210 /// | 319 /// |
211 /// @return A <code>CompletionCallback</code>. | 320 /// @return A <code>CompletionCallback</code>. |
212 template <typename Method, typename A> | 321 template <typename Method, typename A> |
213 CompletionCallback NewOptionalCallback(Method method, const A& a) { | 322 CompletionCallback NewOptionalCallback(Method method, const A& a) { |
214 CompletionCallback cc = NewCallback(method, a); | 323 CompletionCallback cc = NewCallback(method, a); |
215 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); | 324 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
216 return cc; | 325 return cc; |
217 } | 326 } |
218 | 327 |
| 328 /// NewCallbackWithOutput() allocates a new, single-use |
| 329 /// <code>CompletionCallback</code> where the browser will pass an additional |
| 330 /// parameter comtaining the result of the request. The |
| 331 /// <code>CompletionCallback</code> must be run in order for the memory |
| 332 /// allocated by the methods to be freed. |
| 333 /// |
| 334 /// @param[in] method The method to be invoked upon completion of the |
| 335 /// operation. |
| 336 /// |
| 337 /// @param[in] a Passed to <code>method</code> when the completion callback |
| 338 /// runs. |
| 339 /// |
| 340 /// @return A <code>CompletionCallback</code>. |
| 341 template <typename Output, typename A> |
| 342 CompletionCallbackWithOutput< |
| 343 typename internal::TypeUnwrapper<Output>::StorageType> |
| 344 NewCallbackWithOutput(void (T::*method)(int32_t, Output, A), |
| 345 const A& a) { |
| 346 return NewCallbackWithOutputHelper(new DispatcherWithOutput1< |
| 347 typename internal::TypeUnwrapper<Output>::StorageType, |
| 348 void (T::*)(int32_t, Output, A), |
| 349 typename internal::TypeUnwrapper<A>::StorageType>(method, a)); |
| 350 } |
| 351 |
219 /// NewCallback() allocates a new, single-use | 352 /// NewCallback() allocates a new, single-use |
220 /// <code>CompletionCallback</code>. | 353 /// <code>CompletionCallback</code>. |
221 /// The <code>CompletionCallback</code> must be run in order for the memory | 354 /// The <code>CompletionCallback</code> must be run in order for the memory |
222 /// allocated by the methods to be freed. | 355 /// allocated by the methods to be freed. |
223 /// | 356 /// |
224 /// @param method The method taking the callback. Method should be of type: | 357 /// @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> | 358 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code> |
226 /// | 359 /// |
227 /// @param[in] a Passed to <code>method</code> when the completion callback | 360 /// @param[in] a Passed to <code>method</code> when the completion callback |
228 /// runs. | 361 /// runs. |
229 /// | 362 /// |
230 /// @param[in] b Passed to <code>method</code> when the completion callback | 363 /// @param[in] b Passed to <code>method</code> when the completion callback |
231 /// runs. | 364 /// runs. |
232 /// | 365 /// |
233 /// @return A <code>CompletionCallback</code>. | 366 /// @return A <code>CompletionCallback</code>. |
234 template <typename Method, typename A, typename B> | 367 template <typename Method, typename A, typename B> |
235 CompletionCallback NewCallback(Method method, const A& a, const B& b) { | 368 CompletionCallback NewCallback(Method method, const A& a, const B& b) { |
236 PP_DCHECK(object_); | 369 PP_DCHECK(object_); |
237 return NewCallbackHelper(Dispatcher2<Method, A, B>(method, a, b)); | 370 return NewCallbackHelper(new Dispatcher2<Method, A, B>(method, a, b)); |
238 } | 371 } |
239 | 372 |
240 /// NewOptionalCallback() allocates a new, single-use | 373 /// NewOptionalCallback() allocates a new, single-use |
241 /// <code>CompletionCallback</code> that might not run if the method | 374 /// <code>CompletionCallback</code> that might not run if the method |
242 /// taking it can complete synchronously. Thus, if after passing the | 375 /// taking it can complete synchronously. Thus, if after passing the |
243 /// CompletionCallback to a Pepper method, the method does not return | 376 /// CompletionCallback to a Pepper method, the method does not return |
244 /// PP_OK_COMPLETIONPENDING, then you should manually call the | 377 /// PP_OK_COMPLETIONPENDING, then you should manually call the |
245 /// CompletionCallback's Run method, or memory will be leaked. | 378 /// CompletionCallback's Run method, or memory will be leaked. |
246 /// | 379 /// |
247 /// @param[in] method The method taking the callback. Method should be of | 380 /// @param[in] method The method taking the callback. Method should be of |
248 /// type: | 381 /// type: |
249 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code> | 382 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code> |
250 /// | 383 /// |
251 /// @param[in] a Passed to <code>method</code> when the completion callback | 384 /// @param[in] a Passed to <code>method</code> when the completion callback |
252 /// runs. | 385 /// runs. |
253 /// | 386 /// |
254 /// @param[in] b Passed to <code>method</code> when the completion callback | 387 /// @param[in] b Passed to <code>method</code> when the completion callback |
255 /// runs. | 388 /// runs. |
256 /// | 389 /// |
257 /// @return A <code>CompletionCallback</code>. | 390 /// @return A <code>CompletionCallback</code>. |
258 template <typename Method, typename A, typename B> | 391 template <typename Method, typename A, typename B> |
259 CompletionCallback NewOptionalCallback(Method method, const A& a, | 392 CompletionCallback NewOptionalCallback(Method method, const A& a, |
260 const B& b) { | 393 const B& b) { |
261 CompletionCallback cc = NewCallback(method, a, b); | 394 CompletionCallback cc = NewCallback(method, a, b); |
262 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); | 395 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
263 return cc; | 396 return cc; |
264 } | 397 } |
265 | 398 |
| 399 /// NewCallbackWithOutput() allocates a new, single-use |
| 400 /// <code>CompletionCallback</code> where the browser will pass an additional |
| 401 /// parameter comtaining the result of the request. The |
| 402 /// <code>CompletionCallback</code> must be run in order for the memory |
| 403 /// allocated by the methods to be freed. |
| 404 /// |
| 405 /// @param[in] method The method to be invoked upon completion of the |
| 406 /// operation. |
| 407 /// |
| 408 /// @param[in] a Passed to <code>method</code> when the completion callback |
| 409 /// runs. |
| 410 /// |
| 411 /// @param[in] b Passed to <code>method</code> when the completion callback |
| 412 /// runs. |
| 413 /// |
| 414 /// @return A <code>CompletionCallback</code>. |
| 415 template <typename Output, typename A, typename B> |
| 416 CompletionCallbackWithOutput< |
| 417 typename internal::TypeUnwrapper<Output>::StorageType> |
| 418 NewCallbackWithOutput(void (T::*method)(int32_t, Output, A, B), |
| 419 const A& a, |
| 420 const B& b) { |
| 421 return NewCallbackWithOutputHelper(new DispatcherWithOutput2< |
| 422 typename internal::TypeUnwrapper<Output>::StorageType, |
| 423 void (T::*)(int32_t, Output, A, B), |
| 424 typename internal::TypeUnwrapper<A>::StorageType, |
| 425 typename internal::TypeUnwrapper<B>::StorageType>(method, a, b)); |
| 426 } |
| 427 |
266 /// NewCallback() allocates a new, single-use | 428 /// NewCallback() allocates a new, single-use |
267 /// <code>CompletionCallback</code>. | 429 /// <code>CompletionCallback</code>. |
268 /// The <code>CompletionCallback</code> must be run in order for the memory | 430 /// The <code>CompletionCallback</code> must be run in order for the memory |
269 /// allocated by the methods to be freed. | 431 /// allocated by the methods to be freed. |
270 /// | 432 /// |
271 /// @param method The method taking the callback. Method should be of type: | 433 /// @param method The method taking the callback. Method should be of type: |
272 /// <code> | 434 /// <code> |
273 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) | 435 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) |
274 /// </code> | 436 /// </code> |
275 /// | 437 /// |
276 /// @param[in] a Passed to <code>method</code> when the completion callback | 438 /// @param[in] a Passed to <code>method</code> when the completion callback |
277 /// runs. | 439 /// runs. |
278 /// | 440 /// |
279 /// @param[in] b Passed to <code>method</code> when the completion callback | 441 /// @param[in] b Passed to <code>method</code> when the completion callback |
280 /// runs. | 442 /// runs. |
281 /// | 443 /// |
282 /// @param[in] c Passed to <code>method</code> when the completion callback | 444 /// @param[in] c Passed to <code>method</code> when the completion callback |
283 /// runs. | 445 /// runs. |
284 /// | 446 /// |
285 /// @return A <code>CompletionCallback</code>. | 447 /// @return A <code>CompletionCallback</code>. |
286 template <typename Method, typename A, typename B, typename C> | 448 template <typename Method, typename A, typename B, typename C> |
287 CompletionCallback NewCallback(Method method, const A& a, const B& b, | 449 CompletionCallback NewCallback(Method method, const A& a, const B& b, |
288 const C& c) { | 450 const C& c) { |
289 PP_DCHECK(object_); | 451 PP_DCHECK(object_); |
290 return NewCallbackHelper(Dispatcher3<Method, A, B, C>(method, a, b, c)); | 452 return NewCallbackHelper(new Dispatcher3<Method, A, B, C>(method, a, b, c)); |
291 } | 453 } |
292 | 454 |
293 /// NewOptionalCallback() allocates a new, single-use | 455 /// NewOptionalCallback() allocates a new, single-use |
294 /// <code>CompletionCallback</code> that might not run if the method | 456 /// <code>CompletionCallback</code> that might not run if the method |
295 /// taking it can complete synchronously. Thus, if after passing the | 457 /// taking it can complete synchronously. Thus, if after passing the |
296 /// CompletionCallback to a Pepper method, the method does not return | 458 /// CompletionCallback to a Pepper method, the method does not return |
297 /// PP_OK_COMPLETIONPENDING, then you should manually call the | 459 /// PP_OK_COMPLETIONPENDING, then you should manually call the |
298 /// CompletionCallback's Run method, or memory will be leaked. | 460 /// CompletionCallback's Run method, or memory will be leaked. |
299 /// | 461 /// |
300 /// @param[in] method The method taking the callback. Method should be of | 462 /// @param[in] method The method taking the callback. Method should be of |
(...skipping 13 matching lines...) Expand all Loading... |
314 /// | 476 /// |
315 /// @return A <code>CompletionCallback</code>. | 477 /// @return A <code>CompletionCallback</code>. |
316 template <typename Method, typename A, typename B, typename C> | 478 template <typename Method, typename A, typename B, typename C> |
317 CompletionCallback NewOptionalCallback(Method method, const A& a, | 479 CompletionCallback NewOptionalCallback(Method method, const A& a, |
318 const B& b, const C& c) { | 480 const B& b, const C& c) { |
319 CompletionCallback cc = NewCallback(method, a, b, c); | 481 CompletionCallback cc = NewCallback(method, a, b, c); |
320 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); | 482 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
321 return cc; | 483 return cc; |
322 } | 484 } |
323 | 485 |
| 486 /// NewCallbackWithOutput() allocates a new, single-use |
| 487 /// <code>CompletionCallback</code> where the browser will pass an additional |
| 488 /// parameter comtaining the result of the request. The |
| 489 /// <code>CompletionCallback</code> must be run in order for the memory |
| 490 /// allocated by the methods to be freed. |
| 491 /// |
| 492 /// @param method The method to be run. |
| 493 /// |
| 494 /// @param[in] a Passed to <code>method</code> when the completion callback |
| 495 /// runs. |
| 496 /// |
| 497 /// @param[in] b Passed to <code>method</code> when the completion callback |
| 498 /// runs. |
| 499 /// |
| 500 /// @param[in] c Passed to <code>method</code> when the completion callback |
| 501 /// runs. |
| 502 /// |
| 503 /// @return A <code>CompletionCallback</code>. |
| 504 template <typename Output, typename A, typename B, typename C> |
| 505 CompletionCallbackWithOutput< |
| 506 typename internal::TypeUnwrapper<Output>::StorageType> |
| 507 NewCallbackWithOutput(void (T::*method)(int32_t, Output, A, B, C), |
| 508 const A& a, |
| 509 const B& b, |
| 510 const C& c) { |
| 511 return NewCallbackWithOutputHelper(new DispatcherWithOutput3< |
| 512 typename internal::TypeUnwrapper<Output>::StorageType, |
| 513 void (T::*)(int32_t, Output, A, B, C), |
| 514 typename internal::TypeUnwrapper<A>::StorageType, |
| 515 typename internal::TypeUnwrapper<B>::StorageType, |
| 516 typename internal::TypeUnwrapper<C>::StorageType>(method, a, b, c)); |
| 517 } |
| 518 |
324 private: | 519 private: |
325 class BackPointer { | 520 class BackPointer { |
326 public: | 521 public: |
327 typedef CompletionCallbackFactory<T, RefCount> FactoryType; | 522 typedef CompletionCallbackFactory<T, RefCount> FactoryType; |
328 | 523 |
329 BackPointer(FactoryType* factory) | 524 explicit BackPointer(FactoryType* factory) |
330 : factory_(factory) { | 525 : factory_(factory) { |
331 } | 526 } |
332 | 527 |
333 void AddRef() { | 528 void AddRef() { |
334 ref_.AddRef(); | 529 ref_.AddRef(); |
335 } | 530 } |
336 | 531 |
337 void Release() { | 532 void Release() { |
338 if (ref_.Release() == 0) | 533 if (ref_.Release() == 0) |
339 delete this; | 534 delete this; |
340 } | 535 } |
341 | 536 |
342 void DropFactory() { | 537 void DropFactory() { |
343 factory_ = NULL; | 538 factory_ = NULL; |
344 } | 539 } |
345 | 540 |
346 T* GetObject() { | 541 T* GetObject() { |
347 return factory_ ? factory_->GetObject() : NULL; | 542 return factory_ ? factory_->GetObject() : NULL; |
348 } | 543 } |
349 | 544 |
350 private: | 545 private: |
351 RefCount ref_; | 546 RefCount ref_; |
352 FactoryType* factory_; | 547 FactoryType* factory_; |
353 }; | 548 }; |
354 | 549 |
355 template <typename Dispatcher> | 550 template <typename Dispatcher> |
356 class CallbackData { | 551 class CallbackData { |
357 public: | 552 public: |
358 CallbackData(BackPointer* back_pointer, const Dispatcher& dispatcher) | 553 // Takes ownership of the given dispatcher pointer. |
| 554 CallbackData(BackPointer* back_pointer, Dispatcher* dispatcher) |
359 : back_pointer_(back_pointer), | 555 : back_pointer_(back_pointer), |
360 dispatcher_(dispatcher) { | 556 dispatcher_(dispatcher) { |
361 back_pointer_->AddRef(); | 557 back_pointer_->AddRef(); |
362 } | 558 } |
363 | 559 |
364 ~CallbackData() { | 560 ~CallbackData() { |
365 back_pointer_->Release(); | 561 back_pointer_->Release(); |
| 562 delete dispatcher_; |
366 } | 563 } |
367 | 564 |
| 565 Dispatcher* dispatcher() { return dispatcher_; } |
| 566 |
368 static void Thunk(void* user_data, int32_t result) { | 567 static void Thunk(void* user_data, int32_t result) { |
369 Self* self = static_cast<Self*>(user_data); | 568 Self* self = static_cast<Self*>(user_data); |
370 T* object = self->back_pointer_->GetObject(); | 569 T* object = self->back_pointer_->GetObject(); |
371 if (object) | 570 if (object) |
372 self->dispatcher_(object, result); | 571 (*self->dispatcher_)(object, result); |
373 delete self; | 572 delete self; |
374 } | 573 } |
375 | 574 |
376 private: | 575 private: |
377 typedef CallbackData<Dispatcher> Self; | 576 typedef CallbackData<Dispatcher> Self; |
378 BackPointer* back_pointer_; | 577 BackPointer* back_pointer_; // We own a ref to this refcounted object. |
379 Dispatcher dispatcher_; | 578 Dispatcher* dispatcher_; // We own this pointer. |
| 579 |
| 580 // Disallow copying & assignment. |
| 581 CallbackData(const CallbackData<Dispatcher>&); |
| 582 CallbackData<Dispatcher>& operator=(const CallbackData<Dispatcher>&); |
380 }; | 583 }; |
381 | 584 |
382 template <typename Method> | 585 template <typename Method> |
383 class Dispatcher0 { | 586 class Dispatcher0 { |
384 public: | 587 public: |
385 Dispatcher0(Method method) : method_(method) { | 588 Dispatcher0() : method_(NULL) {} |
| 589 explicit Dispatcher0(Method method) : method_(method) { |
386 } | 590 } |
387 void operator()(T* object, int32_t result) { | 591 void operator()(T* object, int32_t result) { |
388 (object->*method_)(result); | 592 (object->*method_)(result); |
389 } | 593 } |
390 private: | 594 private: |
391 Method method_; | 595 Method method_; |
392 }; | 596 }; |
393 | 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) { |
| 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 private: |
| 614 Method method_; |
| 615 |
| 616 typename Traits::StorageType output_; |
| 617 }; |
| 618 |
394 template <typename Method, typename A> | 619 template <typename Method, typename A> |
395 class Dispatcher1 { | 620 class Dispatcher1 { |
396 public: | 621 public: |
| 622 Dispatcher1() : method_(NULL) {} |
397 Dispatcher1(Method method, const A& a) | 623 Dispatcher1(Method method, const A& a) |
398 : method_(method), | 624 : method_(method), |
399 a_(a) { | 625 a_(a) { |
400 } | 626 } |
401 void operator()(T* object, int32_t result) { | 627 void operator()(T* object, int32_t result) { |
402 (object->*method_)(result, a_); | 628 (object->*method_)(result, a_); |
403 } | 629 } |
404 private: | 630 private: |
405 Method method_; | 631 Method method_; |
406 A a_; | 632 A a_; |
407 }; | 633 }; |
408 | 634 |
| 635 template <typename Output, typename Method, typename A> |
| 636 class DispatcherWithOutput1 { |
| 637 public: |
| 638 typedef Output OutputType; |
| 639 typedef internal::CallbackOutputTraits<Output> Traits; |
| 640 |
| 641 DispatcherWithOutput1() : method_(NULL) {} |
| 642 DispatcherWithOutput1(Method method, const A& a) |
| 643 : method_(method), |
| 644 a_(a) { |
| 645 } |
| 646 void operator()(T* object, int32_t result) { |
| 647 (object->*method_)(result, Traits::StorageToPluginArg(output_), a_); |
| 648 } |
| 649 typename Traits::StorageType* output() { |
| 650 return &output_; |
| 651 } |
| 652 private: |
| 653 Method method_; |
| 654 A a_; |
| 655 |
| 656 typename Traits::StorageType output_; |
| 657 }; |
| 658 |
409 template <typename Method, typename A, typename B> | 659 template <typename Method, typename A, typename B> |
410 class Dispatcher2 { | 660 class Dispatcher2 { |
411 public: | 661 public: |
| 662 Dispatcher2() : method_(NULL) {} |
412 Dispatcher2(Method method, const A& a, const B& b) | 663 Dispatcher2(Method method, const A& a, const B& b) |
413 : method_(method), | 664 : method_(method), |
414 a_(a), | 665 a_(a), |
415 b_(b) { | 666 b_(b) { |
416 } | 667 } |
417 void operator()(T* object, int32_t result) { | 668 void operator()(T* object, int32_t result) { |
418 (object->*method_)(result, a_, b_); | 669 (object->*method_)(result, a_, b_); |
419 } | 670 } |
420 private: | 671 private: |
421 Method method_; | 672 Method method_; |
422 A a_; | 673 A a_; |
423 B b_; | 674 B b_; |
424 }; | 675 }; |
425 | 676 |
| 677 template <typename Output, typename Method, typename A, typename B> |
| 678 class DispatcherWithOutput2 { |
| 679 public: |
| 680 typedef Output OutputType; |
| 681 typedef internal::CallbackOutputTraits<Output> Traits; |
| 682 |
| 683 DispatcherWithOutput2() : method_(NULL) {} |
| 684 DispatcherWithOutput2(Method method, const A& a, const B& b) |
| 685 : method_(method), |
| 686 a_(a), |
| 687 b_(b) { |
| 688 } |
| 689 void operator()(T* object, int32_t result) { |
| 690 (object->*method_)(result, Traits::StorageToPluginArg(output_), a_, b_); |
| 691 } |
| 692 typename Traits::StorageType* output() { |
| 693 return &output_; |
| 694 } |
| 695 private: |
| 696 Method method_; |
| 697 A a_; |
| 698 B b_; |
| 699 |
| 700 typename Traits::StorageType output_; |
| 701 }; |
| 702 |
426 template <typename Method, typename A, typename B, typename C> | 703 template <typename Method, typename A, typename B, typename C> |
427 class Dispatcher3 { | 704 class Dispatcher3 { |
428 public: | 705 public: |
| 706 Dispatcher3() : method_(NULL) {} |
429 Dispatcher3(Method method, const A& a, const B& b, const C& c) | 707 Dispatcher3(Method method, const A& a, const B& b, const C& c) |
430 : method_(method), | 708 : method_(method), |
431 a_(a), | 709 a_(a), |
432 b_(b), | 710 b_(b), |
433 c_(c) { | 711 c_(c) { |
434 } | 712 } |
435 void operator()(T* object, int32_t result) { | 713 void operator()(T* object, int32_t result) { |
436 (object->*method_)(result, a_, b_, c_); | 714 (object->*method_)(result, a_, b_, c_); |
437 } | 715 } |
438 private: | 716 private: |
439 Method method_; | 717 Method method_; |
440 A a_; | 718 A a_; |
441 B b_; | 719 B b_; |
442 C c_; | 720 C c_; |
443 }; | 721 }; |
444 | 722 |
| 723 template <typename Output, typename Method, typename A, typename B, |
| 724 typename C> |
| 725 class DispatcherWithOutput3 { |
| 726 public: |
| 727 typedef Output OutputType; |
| 728 typedef internal::CallbackOutputTraits<Output> Traits; |
| 729 |
| 730 DispatcherWithOutput3() : method_(NULL) {} |
| 731 DispatcherWithOutput3(Method method, const A& a, const B& b, const C& c) |
| 732 : method_(method), |
| 733 a_(a), |
| 734 b_(b), |
| 735 c_(c) { |
| 736 } |
| 737 void operator()(T* object, int32_t result) { |
| 738 (object->*method_)(result, Traits::StorageToPluginArg(output_), |
| 739 a_, b_, c_); |
| 740 } |
| 741 typename Traits::StorageType* output() { |
| 742 return &output_; |
| 743 } |
| 744 private: |
| 745 Method method_; |
| 746 A a_; |
| 747 B b_; |
| 748 C c_; |
| 749 |
| 750 typename Traits::StorageType output_; |
| 751 }; |
| 752 |
445 void InitBackPointer() { | 753 void InitBackPointer() { |
446 back_pointer_ = new BackPointer(this); | 754 back_pointer_ = new BackPointer(this); |
447 back_pointer_->AddRef(); | 755 back_pointer_->AddRef(); |
448 } | 756 } |
449 | 757 |
450 void ResetBackPointer() { | 758 void ResetBackPointer() { |
451 back_pointer_->DropFactory(); | 759 back_pointer_->DropFactory(); |
452 back_pointer_->Release(); | 760 back_pointer_->Release(); |
453 } | 761 } |
454 | 762 |
| 763 // Takes ownership of the dispatcher pointer, which should be heap allocated. |
455 template <typename Dispatcher> | 764 template <typename Dispatcher> |
456 CompletionCallback NewCallbackHelper(const Dispatcher& dispatcher) { | 765 CompletionCallback NewCallbackHelper(Dispatcher* dispatcher) { |
457 PP_DCHECK(object_); // Expects a non-null object! | 766 PP_DCHECK(object_); // Expects a non-null object! |
458 return CompletionCallback( | 767 return CompletionCallback( |
459 &CallbackData<Dispatcher>::Thunk, | 768 &CallbackData<Dispatcher>::Thunk, |
460 new CallbackData<Dispatcher>(back_pointer_, dispatcher)); | 769 new CallbackData<Dispatcher>(back_pointer_, dispatcher)); |
461 } | 770 } |
462 | 771 |
| 772 // Takes ownership of the dispatcher pointer, which should be heap allocated. |
| 773 template <typename Dispatcher> CompletionCallbackWithOutput< |
| 774 typename internal::TypeUnwrapper< |
| 775 typename Dispatcher::OutputType>::StorageType> |
| 776 NewCallbackWithOutputHelper(Dispatcher* dispatcher) { |
| 777 PP_DCHECK(object_); // Expects a non-null object! |
| 778 CallbackData<Dispatcher>* data = |
| 779 new CallbackData<Dispatcher>(back_pointer_, dispatcher); |
| 780 |
| 781 return CompletionCallbackWithOutput<typename Dispatcher::OutputType>( |
| 782 &CallbackData<Dispatcher>::Thunk, |
| 783 data, |
| 784 data->dispatcher()->output()); |
| 785 } |
| 786 |
463 // Disallowed: | 787 // Disallowed: |
464 CompletionCallbackFactory(const CompletionCallbackFactory&); | 788 CompletionCallbackFactory(const CompletionCallbackFactory&); |
465 CompletionCallbackFactory& operator=(const CompletionCallbackFactory&); | 789 CompletionCallbackFactory& operator=(const CompletionCallbackFactory&); |
466 | 790 |
467 T* object_; | 791 T* object_; |
468 BackPointer* back_pointer_; | 792 BackPointer* back_pointer_; |
469 }; | 793 }; |
470 | 794 |
471 } // namespace pp | 795 } // namespace pp |
472 | 796 |
473 #endif // PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ | 797 #endif // PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ |
OLD | NEW |