OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ | 5 #ifndef PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ |
6 #define PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ | 6 #define PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ |
7 | 7 |
8 #include "ppapi/cpp/completion_callback.h" | 8 #include "ppapi/cpp/completion_callback.h" |
9 #include "ppapi/utility/non_thread_safe_ref_count.h" | 9 #include "ppapi/utility/completion_callback_factory_thread_traits.h" |
10 | 10 |
11 /// @file | 11 /// @file |
12 /// This file defines the API to create CompletionCallback objects that are | 12 /// This file defines the API to create CompletionCallback objects that are |
13 /// bound to member functions. | 13 /// bound to member functions. |
14 namespace pp { | 14 namespace pp { |
15 | 15 |
16 // TypeUnwrapper -------------------------------------------------------------- | 16 // TypeUnwrapper -------------------------------------------------------------- |
17 | 17 |
18 namespace internal { | 18 namespace internal { |
19 | 19 |
(...skipping 16 matching lines...) Expand all Loading... | |
36 | 36 |
37 /// CompletionCallbackFactory<T> may be used to create CompletionCallback | 37 /// CompletionCallbackFactory<T> may be used to create CompletionCallback |
38 /// objects that are bound to member functions. | 38 /// objects that are bound to member functions. |
39 /// | 39 /// |
40 /// If a factory is destroyed, then any pending callbacks will be cancelled | 40 /// If a factory is destroyed, then any pending callbacks will be cancelled |
41 /// preventing any bound member functions from being called. The CancelAll() | 41 /// preventing any bound member functions from being called. The CancelAll() |
42 /// method allows pending callbacks to be cancelled without destroying the | 42 /// method allows pending callbacks to be cancelled without destroying the |
43 /// factory. | 43 /// factory. |
44 /// | 44 /// |
45 /// <strong>Note: </strong><code>CompletionCallbackFactory<T></code> isn't | 45 /// <strong>Note: </strong><code>CompletionCallbackFactory<T></code> isn't |
46 /// thread safe, but you can make it more thread-friendly by passing a | 46 /// thread safe, but it is somewhat thread-friendly when used with a |
47 /// thread-safe refcounting class as the second template element. However, it | 47 /// thread-safe traits class as the second template element. However, it |
48 /// only guarantees safety for creating a callback from another thread, the | 48 /// only guarantees safety for creating a callback from another thread, the |
49 /// callback itself needs to execute on the same thread as the thread that | 49 /// callback itself needs to execute on the same thread as the thread that |
50 /// creates/destroys the factory. With this restriction, it is safe to create | 50 /// creates/destroys the factory. With this restriction, it is safe to create |
51 /// the <code>CompletionCallbackFactory</code> on the main thread, create | 51 /// the <code>CompletionCallbackFactory</code> on the main thread, create |
52 /// callbacks from any thread and pass them to CallOnMainThread(). | 52 /// callbacks from any thread and pass them to CallOnMainThread(). |
53 /// | 53 /// |
54 /// <strong>Example: </strong> | 54 /// <strong>Example: </strong> |
55 /// | 55 /// |
56 /// @code | 56 /// @code |
57 /// class MyClass { | 57 /// class MyClass { |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
178 /// As with regular completion callbacks, you can optionally add up to three | 178 /// As with regular completion callbacks, you can optionally add up to three |
179 /// bound arguments. These are passed following the output argument. | 179 /// bound arguments. These are passed following the output argument. |
180 /// | 180 /// |
181 /// Your callback may take the output argument as a copy (common for small | 181 /// Your callback may take the output argument as a copy (common for small |
182 /// types like integers, a const reference (common for structures and | 182 /// types like integers, a const reference (common for structures and |
183 /// resources to avoid an extra copy), or as a non-const reference. One | 183 /// resources to avoid an extra copy), or as a non-const reference. One |
184 /// optimization you can do if your callback function may take large arrays | 184 /// optimization you can do if your callback function may take large arrays |
185 /// is to accept your output argument as a non-const reference and to swap() | 185 /// is to accept your output argument as a non-const reference and to swap() |
186 /// the argument with a vector of your own to store it. This means you don't | 186 /// the argument with a vector of your own to store it. This means you don't |
187 /// have to copy the buffer to consume it. | 187 /// have to copy the buffer to consume it. |
188 template <typename T, typename RefCount = NonThreadSafeRefCount> | 188 template <typename T, typename ThreadTraits = ThreadSafeThreadTraits> |
189 class CompletionCallbackFactory { | 189 class CompletionCallbackFactory { |
190 public: | 190 public: |
191 | 191 |
192 /// This constructor creates a <code>CompletionCallbackFactory</code> | 192 /// This constructor creates a <code>CompletionCallbackFactory</code> |
193 /// bound to an object. If the constructor is called without an argument, | 193 /// bound to an object. If the constructor is called without an argument, |
194 /// the default value of <code>NULL</code> is used. The user then must call | 194 /// the default value of <code>NULL</code> is used. The user then must call |
195 /// Initialize() to initialize the object. | 195 /// Initialize() to initialize the object. |
196 /// | 196 /// |
197 /// param[in] object Optional parameter. An object whose member functions | 197 /// param[in] object Optional parameter. An object whose member functions |
198 /// are to be bound to CompletionCallbacks created by this | 198 /// are to be bound to CompletionCallbacks created by this |
199 /// <code>CompletionCallbackFactory</code>. The default value of this | 199 /// <code>CompletionCallbackFactory</code>. The default value of this |
200 /// parameter is <code>NULL</code>. | 200 /// parameter is <code>NULL</code>. |
201 explicit CompletionCallbackFactory(T* object = NULL) | 201 explicit CompletionCallbackFactory(T* object = NULL) |
202 : object_(object) { | 202 : object_(object) { |
203 // Assume that we don't need to lock since construction should be complete | |
204 // before the pointer is used on another thread. | |
203 InitBackPointer(); | 205 InitBackPointer(); |
204 } | 206 } |
205 | 207 |
206 /// Destructor. | 208 /// Destructor. |
207 ~CompletionCallbackFactory() { | 209 ~CompletionCallbackFactory() { |
210 // Assume that we don't need to lock since this object should not be used | |
211 // from multiple threads during destruction. | |
208 ResetBackPointer(); | 212 ResetBackPointer(); |
209 } | 213 } |
210 | 214 |
211 /// CancelAll() cancels all <code>CompletionCallbacks</code> allocated from | 215 /// CancelAll() cancels all <code>CompletionCallbacks</code> allocated from |
212 /// this factory. | 216 /// this factory. |
213 void CancelAll() { | 217 void CancelAll() { |
218 ThreadTraits::AutoLock lock(lock_); | |
219 | |
214 ResetBackPointer(); | 220 ResetBackPointer(); |
215 InitBackPointer(); | 221 InitBackPointer(); |
216 } | 222 } |
223 | |
217 /// Initialize() binds the <code>CallbackFactory</code> to a particular | 224 /// Initialize() binds the <code>CallbackFactory</code> to a particular |
218 /// object. Use this when the object is not available at | 225 /// object. Use this when the object is not available at |
219 /// <code>CallbackFactory</code> creation, and the <code>NULL</code> default | 226 /// <code>CallbackFactory</code> creation, and the <code>NULL</code> default |
220 /// is passed to the constructor. The object may only be initialized once, | 227 /// is passed to the constructor. The object may only be initialized once, |
221 /// either by the constructor, or by a call to Initialize(). | 228 /// either by the constructor, or by a call to Initialize(). |
222 /// | 229 /// |
223 /// @param[in] object The object whose member functions are to be bound to | 230 /// @param[in] object The object whose member functions are to be bound to |
224 /// the <code>CompletionCallback</code> created by this | 231 /// the <code>CompletionCallback</code> created by this |
225 /// <code>CompletionCallbackFactory</code>. | 232 /// <code>CompletionCallbackFactory</code>. |
226 void Initialize(T* object) { | 233 void Initialize(T* object) { |
227 PP_DCHECK(object); | 234 PP_DCHECK(object); |
viettrungluu
2012/07/10 22:47:58
Maybe you should have a comment about the non-thre
| |
228 PP_DCHECK(!object_); // May only initialize once! | 235 PP_DCHECK(!object_); // May only initialize once! |
229 object_ = object; | 236 object_ = object; |
230 } | 237 } |
231 | 238 |
232 /// GetObject() returns the object that was passed at initialization to | 239 /// GetObject() returns the object that was passed at initialization to |
233 /// Intialize(). | 240 /// Intialize(). |
234 /// | 241 /// |
235 /// @return the object passed to the constructor or Intialize(). | 242 /// @return the object passed to the constructor or Intialize(). |
236 T* GetObject() { | 243 T* GetObject() { |
237 return object_; | 244 return object_; |
238 } | 245 } |
239 | 246 |
240 /// NewCallback allocates a new, single-use <code>CompletionCallback</code>. | 247 /// NewCallback allocates a new, single-use <code>CompletionCallback</code>. |
241 /// The <code>CompletionCallback</code> must be run in order for the memory | 248 /// The <code>CompletionCallback</code> must be run in order for the memory |
242 /// allocated by the methods to be freed. | 249 /// allocated by the methods to be freed. |
243 /// | 250 /// |
244 /// @param[in] method The method to be invoked upon completion of the | 251 /// @param[in] method The method to be invoked upon completion of the |
245 /// operation. | 252 /// operation. |
246 /// | 253 /// |
247 /// @return A <code>CompletionCallback</code>. | 254 /// @return A <code>CompletionCallback</code>. |
248 template <typename Method> | 255 template <typename Method> |
249 CompletionCallback NewCallback(Method method) { | 256 CompletionCallback NewCallback(Method method) { |
250 PP_DCHECK(object_); | 257 PP_DCHECK(object_); |
viettrungluu
2012/07/10 22:47:58
While you're here, I believe this dcheck is wholly
| |
251 return NewCallbackHelper(new Dispatcher0<Method>(method)); | 258 return NewCallbackHelper(new Dispatcher0<Method>(method)); |
252 } | 259 } |
253 | 260 |
254 /// NewOptionalCallback() allocates a new, single-use | 261 /// NewOptionalCallback() allocates a new, single-use |
255 /// <code>CompletionCallback</code> that might not run if the method | 262 /// <code>CompletionCallback</code> that might not run if the method |
256 /// taking it can complete synchronously. Thus, if after passing the | 263 /// taking it can complete synchronously. Thus, if after passing the |
257 /// CompletionCallback to a Pepper method, the method does not return | 264 /// CompletionCallback to a Pepper method, the method does not return |
258 /// PP_OK_COMPLETIONPENDING, then you should manually call the | 265 /// PP_OK_COMPLETIONPENDING, then you should manually call the |
259 /// CompletionCallback's Run method, or memory will be leaked. | 266 /// CompletionCallback's Run method, or memory will be leaked. |
260 /// | 267 /// |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
295 /// @param[in] method The method to be invoked upon completion of the | 302 /// @param[in] method The method to be invoked upon completion of the |
296 /// operation. Method should be of type: | 303 /// operation. Method should be of type: |
297 /// <code>void (T::*)(int32_t result, const A& a)</code> | 304 /// <code>void (T::*)(int32_t result, const A& a)</code> |
298 /// | 305 /// |
299 /// @param[in] a Passed to <code>method</code> when the completion callback | 306 /// @param[in] a Passed to <code>method</code> when the completion callback |
300 /// runs. | 307 /// runs. |
301 /// | 308 /// |
302 /// @return A <code>CompletionCallback</code>. | 309 /// @return A <code>CompletionCallback</code>. |
303 template <typename Method, typename A> | 310 template <typename Method, typename A> |
304 CompletionCallback NewCallback(Method method, const A& a) { | 311 CompletionCallback NewCallback(Method method, const A& a) { |
305 PP_DCHECK(object_); | 312 PP_DCHECK(object_); |
viettrungluu
2012/07/10 22:47:58
"
| |
306 return NewCallbackHelper(new Dispatcher1<Method, A>(method, a)); | 313 return NewCallbackHelper(new Dispatcher1<Method, A>(method, a)); |
307 } | 314 } |
308 | 315 |
309 /// NewOptionalCallback() allocates a new, single-use | 316 /// NewOptionalCallback() allocates a new, single-use |
310 /// <code>CompletionCallback</code> that might not run if the method | 317 /// <code>CompletionCallback</code> that might not run if the method |
311 /// taking it can complete synchronously. Thus, if after passing the | 318 /// taking it can complete synchronously. Thus, if after passing the |
312 /// CompletionCallback to a Pepper method, the method does not return | 319 /// CompletionCallback to a Pepper method, the method does not return |
313 /// PP_OK_COMPLETIONPENDING, then you should manually call the | 320 /// PP_OK_COMPLETIONPENDING, then you should manually call the |
314 /// CompletionCallback's Run method, or memory will be leaked. | 321 /// CompletionCallback's Run method, or memory will be leaked. |
315 /// | 322 /// |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
362 /// | 369 /// |
363 /// @param[in] a Passed to <code>method</code> when the completion callback | 370 /// @param[in] a Passed to <code>method</code> when the completion callback |
364 /// runs. | 371 /// runs. |
365 /// | 372 /// |
366 /// @param[in] b Passed to <code>method</code> when the completion callback | 373 /// @param[in] b Passed to <code>method</code> when the completion callback |
367 /// runs. | 374 /// runs. |
368 /// | 375 /// |
369 /// @return A <code>CompletionCallback</code>. | 376 /// @return A <code>CompletionCallback</code>. |
370 template <typename Method, typename A, typename B> | 377 template <typename Method, typename A, typename B> |
371 CompletionCallback NewCallback(Method method, const A& a, const B& b) { | 378 CompletionCallback NewCallback(Method method, const A& a, const B& b) { |
372 PP_DCHECK(object_); | 379 PP_DCHECK(object_); |
viettrungluu
2012/07/10 22:47:58
"
| |
373 return NewCallbackHelper(new Dispatcher2<Method, A, B>(method, a, b)); | 380 return NewCallbackHelper(new Dispatcher2<Method, A, B>(method, a, b)); |
374 } | 381 } |
375 | 382 |
376 /// NewOptionalCallback() allocates a new, single-use | 383 /// NewOptionalCallback() allocates a new, single-use |
377 /// <code>CompletionCallback</code> that might not run if the method | 384 /// <code>CompletionCallback</code> that might not run if the method |
378 /// taking it can complete synchronously. Thus, if after passing the | 385 /// taking it can complete synchronously. Thus, if after passing the |
379 /// CompletionCallback to a Pepper method, the method does not return | 386 /// CompletionCallback to a Pepper method, the method does not return |
380 /// PP_OK_COMPLETIONPENDING, then you should manually call the | 387 /// PP_OK_COMPLETIONPENDING, then you should manually call the |
381 /// CompletionCallback's Run method, or memory will be leaked. | 388 /// CompletionCallback's Run method, or memory will be leaked. |
382 /// | 389 /// |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
444 /// @param[in] b Passed to <code>method</code> when the completion callback | 451 /// @param[in] b Passed to <code>method</code> when the completion callback |
445 /// runs. | 452 /// runs. |
446 /// | 453 /// |
447 /// @param[in] c Passed to <code>method</code> when the completion callback | 454 /// @param[in] c Passed to <code>method</code> when the completion callback |
448 /// runs. | 455 /// runs. |
449 /// | 456 /// |
450 /// @return A <code>CompletionCallback</code>. | 457 /// @return A <code>CompletionCallback</code>. |
451 template <typename Method, typename A, typename B, typename C> | 458 template <typename Method, typename A, typename B, typename C> |
452 CompletionCallback NewCallback(Method method, const A& a, const B& b, | 459 CompletionCallback NewCallback(Method method, const A& a, const B& b, |
453 const C& c) { | 460 const C& c) { |
454 PP_DCHECK(object_); | 461 PP_DCHECK(object_); |
viettrungluu
2012/07/10 22:47:58
"
| |
455 return NewCallbackHelper(new Dispatcher3<Method, A, B, C>(method, a, b, c)); | 462 return NewCallbackHelper(new Dispatcher3<Method, A, B, C>(method, a, b, c)); |
456 } | 463 } |
457 | 464 |
458 /// NewOptionalCallback() allocates a new, single-use | 465 /// NewOptionalCallback() allocates a new, single-use |
459 /// <code>CompletionCallback</code> that might not run if the method | 466 /// <code>CompletionCallback</code> that might not run if the method |
460 /// taking it can complete synchronously. Thus, if after passing the | 467 /// taking it can complete synchronously. Thus, if after passing the |
461 /// CompletionCallback to a Pepper method, the method does not return | 468 /// CompletionCallback to a Pepper method, the method does not return |
462 /// PP_OK_COMPLETIONPENDING, then you should manually call the | 469 /// PP_OK_COMPLETIONPENDING, then you should manually call the |
463 /// CompletionCallback's Run method, or memory will be leaked. | 470 /// CompletionCallback's Run method, or memory will be leaked. |
464 /// | 471 /// |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
515 typename internal::TypeUnwrapper<Output>::StorageType, | 522 typename internal::TypeUnwrapper<Output>::StorageType, |
516 void (T::*)(int32_t, Output, A, B, C), | 523 void (T::*)(int32_t, Output, A, B, C), |
517 typename internal::TypeUnwrapper<A>::StorageType, | 524 typename internal::TypeUnwrapper<A>::StorageType, |
518 typename internal::TypeUnwrapper<B>::StorageType, | 525 typename internal::TypeUnwrapper<B>::StorageType, |
519 typename internal::TypeUnwrapper<C>::StorageType>(method, a, b, c)); | 526 typename internal::TypeUnwrapper<C>::StorageType>(method, a, b, c)); |
520 } | 527 } |
521 | 528 |
522 private: | 529 private: |
523 class BackPointer { | 530 class BackPointer { |
524 public: | 531 public: |
525 typedef CompletionCallbackFactory<T, RefCount> FactoryType; | 532 typedef CompletionCallbackFactory<T, ThreadTraits> FactoryType; |
526 | 533 |
527 explicit BackPointer(FactoryType* factory) | 534 explicit BackPointer(FactoryType* factory) |
528 : factory_(factory) { | 535 : factory_(factory) { |
529 } | 536 } |
530 | 537 |
531 void AddRef() { | 538 void AddRef() { |
532 ref_.AddRef(); | 539 ref_.AddRef(); |
533 } | 540 } |
534 | 541 |
535 void Release() { | 542 void Release() { |
536 if (ref_.Release() == 0) | 543 if (ref_.Release() == 0) |
537 delete this; | 544 delete this; |
538 } | 545 } |
539 | 546 |
540 void DropFactory() { | 547 void DropFactory() { |
541 factory_ = NULL; | 548 factory_ = NULL; |
viettrungluu
2012/07/10 22:47:58
*** It's not entirely obvious to me why factory_ d
| |
542 } | 549 } |
543 | 550 |
544 T* GetObject() { | 551 T* GetObject() { |
545 return factory_ ? factory_->GetObject() : NULL; | 552 return factory_ ? factory_->GetObject() : NULL; |
viettrungluu
2012/07/10 22:47:58
But then I worry about this....
| |
546 } | 553 } |
547 | 554 |
548 private: | 555 private: |
549 RefCount ref_; | 556 typename ThreadTraits::RefCount ref_; |
550 FactoryType* factory_; | 557 FactoryType* factory_; |
551 }; | 558 }; |
552 | 559 |
553 template <typename Dispatcher> | 560 template <typename Dispatcher> |
554 class CallbackData { | 561 class CallbackData { |
555 public: | 562 public: |
556 // Takes ownership of the given dispatcher pointer. | 563 // Takes ownership of the given dispatcher pointer. |
557 CallbackData(BackPointer* back_pointer, Dispatcher* dispatcher) | 564 CallbackData(BackPointer* back_pointer, Dispatcher* dispatcher) |
558 : back_pointer_(back_pointer), | 565 : back_pointer_(back_pointer), |
559 dispatcher_(dispatcher) { | 566 dispatcher_(dispatcher) { |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
810 } | 817 } |
811 private: | 818 private: |
812 Method method_; | 819 Method method_; |
813 A a_; | 820 A a_; |
814 B b_; | 821 B b_; |
815 C c_; | 822 C c_; |
816 | 823 |
817 typename Traits::StorageType output_; | 824 typename Traits::StorageType output_; |
818 }; | 825 }; |
819 | 826 |
827 // Creates the back pointer object and takes a reference to it. This assumes | |
828 // either that the lock is held or that it is not needed. | |
820 void InitBackPointer() { | 829 void InitBackPointer() { |
821 back_pointer_ = new BackPointer(this); | 830 back_pointer_ = new BackPointer(this); |
822 back_pointer_->AddRef(); | 831 back_pointer_->AddRef(); |
823 } | 832 } |
824 | 833 |
834 // Releases our reference to the back pointer object and clears the pointer. | |
835 // This assumes either that the lock is held or that it is not needed. | |
825 void ResetBackPointer() { | 836 void ResetBackPointer() { |
826 back_pointer_->DropFactory(); | 837 back_pointer_->DropFactory(); |
827 back_pointer_->Release(); | 838 back_pointer_->Release(); |
839 back_pointer_ = NULL; | |
828 } | 840 } |
829 | 841 |
830 // Takes ownership of the dispatcher pointer, which should be heap allocated. | 842 // Takes ownership of the dispatcher pointer, which should be heap allocated. |
831 template <typename Dispatcher> | 843 template <typename Dispatcher> |
832 CompletionCallback NewCallbackHelper(Dispatcher* dispatcher) { | 844 CompletionCallback NewCallbackHelper(Dispatcher* dispatcher) { |
845 ThreadTraits::AutoLock lock(lock_); | |
846 | |
833 PP_DCHECK(object_); // Expects a non-null object! | 847 PP_DCHECK(object_); // Expects a non-null object! |
834 return CompletionCallback( | 848 return CompletionCallback( |
835 &CallbackData<Dispatcher>::Thunk, | 849 &CallbackData<Dispatcher>::Thunk, |
836 new CallbackData<Dispatcher>(back_pointer_, dispatcher)); | 850 new CallbackData<Dispatcher>(back_pointer_, dispatcher)); |
837 } | 851 } |
838 | 852 |
839 // Takes ownership of the dispatcher pointer, which should be heap allocated. | 853 // Takes ownership of the dispatcher pointer, which should be heap allocated. |
840 template <typename Dispatcher> CompletionCallbackWithOutput< | 854 template <typename Dispatcher> CompletionCallbackWithOutput< |
841 typename internal::TypeUnwrapper< | 855 typename internal::TypeUnwrapper< |
842 typename Dispatcher::OutputType>::StorageType> | 856 typename Dispatcher::OutputType>::StorageType> |
843 NewCallbackWithOutputHelper(Dispatcher* dispatcher) { | 857 NewCallbackWithOutputHelper(Dispatcher* dispatcher) { |
858 ThreadTraits::AutoLock lock(lock_); | |
859 | |
844 PP_DCHECK(object_); // Expects a non-null object! | 860 PP_DCHECK(object_); // Expects a non-null object! |
845 CallbackData<Dispatcher>* data = | 861 CallbackData<Dispatcher>* data = |
846 new CallbackData<Dispatcher>(back_pointer_, dispatcher); | 862 new CallbackData<Dispatcher>(back_pointer_, dispatcher); |
847 | 863 |
848 return CompletionCallbackWithOutput<typename Dispatcher::OutputType>( | 864 return CompletionCallbackWithOutput<typename Dispatcher::OutputType>( |
849 &CallbackData<Dispatcher>::Thunk, | 865 &CallbackData<Dispatcher>::Thunk, |
850 data, | 866 data, |
851 data->dispatcher()->output()); | 867 data->dispatcher()->output()); |
852 } | 868 } |
853 | 869 |
854 // Disallowed: | 870 // Disallowed: |
855 CompletionCallbackFactory(const CompletionCallbackFactory&); | 871 CompletionCallbackFactory(const CompletionCallbackFactory&); |
856 CompletionCallbackFactory& operator=(const CompletionCallbackFactory&); | 872 CompletionCallbackFactory& operator=(const CompletionCallbackFactory&); |
857 | 873 |
858 T* object_; | 874 T* object_; |
viettrungluu
2012/07/10 22:47:58
Maybe this should have a comment that this is only
| |
875 | |
876 typename ThreadTraits::Lock lock_; | |
viettrungluu
2012/07/10 22:47:58
Probably should indicate that this protects back_p
| |
877 | |
859 BackPointer* back_pointer_; | 878 BackPointer* back_pointer_; |
860 }; | 879 }; |
861 | 880 |
862 } // namespace pp | 881 } // namespace pp |
863 | 882 |
864 #endif // PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ | 883 #endif // PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ |
OLD | NEW |