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) { |
(...skipping 288 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; |
542 } | 549 } |
543 | 550 |
544 T* GetObject() { | 551 T* GetObject() { |
545 return factory_ ? factory_->GetObject() : NULL; | 552 return factory_ ? factory_->GetObject() : NULL; |
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_; |
| 875 |
| 876 typename ThreadTraits::Lock lock_; |
| 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 |