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 |