| 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 |