1 /* 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef WEBRTC_BASE_REFERENCECOUNTEDSINGLETONFACTORY_H_ 12 #define WEBRTC_BASE_REFERENCECOUNTEDSINGLETONFACTORY_H_ 13 14 #include "webrtc/base/common.h" 15 #include "webrtc/base/criticalsection.h" 16 #include "webrtc/base/logging.h" 17 #include "webrtc/base/scoped_ptr.h" 18 19 namespace rtc { 20 21 template <typename Interface> class rcsf_ptr; 22 23 // A ReferenceCountedSingletonFactory is an object which owns another object, 24 // and doles out the owned object to consumers in a reference-counted manner. 25 // Thus, the factory owns at most one object of the desired kind, and 26 // hands consumers a special pointer to it, through which they can access it. 27 // When the consumers delete the pointer, the reference count goes down, 28 // and if the reference count hits zero, the factory can throw the object 29 // away. If a consumer requests the pointer and the factory has none, 30 // it can create one on the fly and pass it back. 31 template <typename Interface> 32 class ReferenceCountedSingletonFactory { 33 friend class rcsf_ptr<Interface>; 34 public: ReferenceCountedSingletonFactory()35 ReferenceCountedSingletonFactory() : ref_count_(0) {} 36 ~ReferenceCountedSingletonFactory()37 virtual ~ReferenceCountedSingletonFactory() { 38 ASSERT(ref_count_ == 0); 39 } 40 41 protected: 42 // Must be implemented in a sub-class. The sub-class may choose whether or not 43 // to cache the instance across lifetimes by either reset()'ing or not 44 // reset()'ing the scoped_ptr in CleanupInstance(). 45 virtual bool SetupInstance() = 0; 46 virtual void CleanupInstance() = 0; 47 48 scoped_ptr<Interface> instance_; 49 50 private: GetInstance()51 Interface* GetInstance() { 52 rtc::CritScope cs(&crit_); 53 if (ref_count_ == 0) { 54 if (!SetupInstance()) { 55 LOG(LS_VERBOSE) << "Failed to setup instance"; 56 return NULL; 57 } 58 ASSERT(instance_.get() != NULL); 59 } 60 ++ref_count_; 61 62 LOG(LS_VERBOSE) << "Number of references: " << ref_count_; 63 return instance_.get(); 64 } 65 ReleaseInstance()66 void ReleaseInstance() { 67 rtc::CritScope cs(&crit_); 68 ASSERT(ref_count_ > 0); 69 ASSERT(instance_.get() != NULL); 70 --ref_count_; 71 LOG(LS_VERBOSE) << "Number of references: " << ref_count_; 72 if (ref_count_ == 0) { 73 CleanupInstance(); 74 } 75 } 76 77 CriticalSection crit_; 78 int ref_count_; 79 80 RTC_DISALLOW_COPY_AND_ASSIGN(ReferenceCountedSingletonFactory); 81 }; 82 83 template <typename Interface> 84 class rcsf_ptr { 85 public: 86 // Create a pointer that uses the factory to get the instance. 87 // This is lazy - it won't generate the instance until it is requested. rcsf_ptr(ReferenceCountedSingletonFactory<Interface> * factory)88 explicit rcsf_ptr(ReferenceCountedSingletonFactory<Interface>* factory) 89 : instance_(NULL), 90 factory_(factory) { 91 } 92 ~rcsf_ptr()93 ~rcsf_ptr() { 94 release(); 95 } 96 97 Interface& operator*() { 98 EnsureAcquired(); 99 return *instance_; 100 } 101 102 Interface* operator->() { 103 EnsureAcquired(); 104 return instance_; 105 } 106 107 // Gets the pointer, creating the singleton if necessary. May return NULL if 108 // creation failed. get()109 Interface* get() { 110 Acquire(); 111 return instance_; 112 } 113 114 // Set instance to NULL and tell the factory we aren't using the instance 115 // anymore. release()116 void release() { 117 if (instance_) { 118 instance_ = NULL; 119 factory_->ReleaseInstance(); 120 } 121 } 122 123 // Lets us know whether instance is valid or not right now. 124 // Even though attempts to use the instance will automatically create it, it 125 // is advisable to check this because creation can fail. valid()126 bool valid() const { 127 return instance_ != NULL; 128 } 129 130 // Returns the factory that this pointer is using. factory()131 ReferenceCountedSingletonFactory<Interface>* factory() const { 132 return factory_; 133 } 134 135 private: EnsureAcquired()136 void EnsureAcquired() { 137 Acquire(); 138 ASSERT(instance_ != NULL); 139 } 140 Acquire()141 void Acquire() { 142 // Since we're getting a singleton back, acquire is a noop if instance is 143 // already populated. 144 if (!instance_) { 145 instance_ = factory_->GetInstance(); 146 } 147 } 148 149 Interface* instance_; 150 ReferenceCountedSingletonFactory<Interface>* factory_; 151 152 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(rcsf_ptr); 153 }; 154 155 }; // namespace rtc 156 157 #endif // WEBRTC_BASE_REFERENCECOUNTEDSINGLETONFACTORY_H_ 158