Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(561)

Side by Side Diff: ppapi/utility/completion_callback_factory.h

Issue 9651002: Add C++ wrappers for output parameters. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: With swapping Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698