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

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

Issue 10696157: Add support for threadsafe completion callback factory. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 5 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) 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
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
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
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
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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698