|  | /* | 
|  | *  Copyright 2004 The WebRTC Project Authors. All rights reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  |  | 
|  | #ifndef WEBRTC_BASE_REFERENCECOUNTEDSINGLETONFACTORY_H_ | 
|  | #define WEBRTC_BASE_REFERENCECOUNTEDSINGLETONFACTORY_H_ | 
|  |  | 
|  | #include "webrtc/base/common.h" | 
|  | #include "webrtc/base/criticalsection.h" | 
|  | #include "webrtc/base/logging.h" | 
|  | #include "webrtc/base/scoped_ptr.h" | 
|  |  | 
|  | namespace rtc { | 
|  |  | 
|  | template <typename Interface> class rcsf_ptr; | 
|  |  | 
|  | // A ReferenceCountedSingletonFactory is an object which owns another object, | 
|  | // and doles out the owned object to consumers in a reference-counted manner. | 
|  | // Thus, the factory owns at most one object of the desired kind, and | 
|  | // hands consumers a special pointer to it, through which they can access it. | 
|  | // When the consumers delete the pointer, the reference count goes down, | 
|  | // and if the reference count hits zero, the factory can throw the object | 
|  | // away.  If a consumer requests the pointer and the factory has none, | 
|  | // it can create one on the fly and pass it back. | 
|  | template <typename Interface> | 
|  | class ReferenceCountedSingletonFactory { | 
|  | friend class rcsf_ptr<Interface>; | 
|  | public: | 
|  | ReferenceCountedSingletonFactory() : ref_count_(0) {} | 
|  |  | 
|  | virtual ~ReferenceCountedSingletonFactory() { | 
|  | ASSERT(ref_count_ == 0); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | // Must be implemented in a sub-class. The sub-class may choose whether or not | 
|  | // to cache the instance across lifetimes by either reset()'ing or not | 
|  | // reset()'ing the scoped_ptr in CleanupInstance(). | 
|  | virtual bool SetupInstance() = 0; | 
|  | virtual void CleanupInstance() = 0; | 
|  |  | 
|  | scoped_ptr<Interface> instance_; | 
|  |  | 
|  | private: | 
|  | Interface* GetInstance() { | 
|  | rtc::CritScope cs(&crit_); | 
|  | if (ref_count_ == 0) { | 
|  | if (!SetupInstance()) { | 
|  | LOG(LS_VERBOSE) << "Failed to setup instance"; | 
|  | return NULL; | 
|  | } | 
|  | ASSERT(instance_.get() != NULL); | 
|  | } | 
|  | ++ref_count_; | 
|  |  | 
|  | LOG(LS_VERBOSE) << "Number of references: " << ref_count_; | 
|  | return instance_.get(); | 
|  | } | 
|  |  | 
|  | void ReleaseInstance() { | 
|  | rtc::CritScope cs(&crit_); | 
|  | ASSERT(ref_count_ > 0); | 
|  | ASSERT(instance_.get() != NULL); | 
|  | --ref_count_; | 
|  | LOG(LS_VERBOSE) << "Number of references: " << ref_count_; | 
|  | if (ref_count_ == 0) { | 
|  | CleanupInstance(); | 
|  | } | 
|  | } | 
|  |  | 
|  | CriticalSection crit_; | 
|  | int ref_count_; | 
|  |  | 
|  | RTC_DISALLOW_COPY_AND_ASSIGN(ReferenceCountedSingletonFactory); | 
|  | }; | 
|  |  | 
|  | template <typename Interface> | 
|  | class rcsf_ptr { | 
|  | public: | 
|  | // Create a pointer that uses the factory to get the instance. | 
|  | // This is lazy - it won't generate the instance until it is requested. | 
|  | explicit rcsf_ptr(ReferenceCountedSingletonFactory<Interface>* factory) | 
|  | : instance_(NULL), | 
|  | factory_(factory) { | 
|  | } | 
|  |  | 
|  | ~rcsf_ptr() { | 
|  | release(); | 
|  | } | 
|  |  | 
|  | Interface& operator*() { | 
|  | EnsureAcquired(); | 
|  | return *instance_; | 
|  | } | 
|  |  | 
|  | Interface* operator->() { | 
|  | EnsureAcquired(); | 
|  | return instance_; | 
|  | } | 
|  |  | 
|  | // Gets the pointer, creating the singleton if necessary. May return NULL if | 
|  | // creation failed. | 
|  | Interface* get() { | 
|  | Acquire(); | 
|  | return instance_; | 
|  | } | 
|  |  | 
|  | // Set instance to NULL and tell the factory we aren't using the instance | 
|  | // anymore. | 
|  | void release() { | 
|  | if (instance_) { | 
|  | instance_ = NULL; | 
|  | factory_->ReleaseInstance(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Lets us know whether instance is valid or not right now. | 
|  | // Even though attempts to use the instance will automatically create it, it | 
|  | // is advisable to check this because creation can fail. | 
|  | bool valid() const { | 
|  | return instance_ != NULL; | 
|  | } | 
|  |  | 
|  | // Returns the factory that this pointer is using. | 
|  | ReferenceCountedSingletonFactory<Interface>* factory() const { | 
|  | return factory_; | 
|  | } | 
|  |  | 
|  | private: | 
|  | void EnsureAcquired() { | 
|  | Acquire(); | 
|  | ASSERT(instance_ != NULL); | 
|  | } | 
|  |  | 
|  | void Acquire() { | 
|  | // Since we're getting a singleton back, acquire is a noop if instance is | 
|  | // already populated. | 
|  | if (!instance_) { | 
|  | instance_ = factory_->GetInstance(); | 
|  | } | 
|  | } | 
|  |  | 
|  | Interface* instance_; | 
|  | ReferenceCountedSingletonFactory<Interface>* factory_; | 
|  |  | 
|  | RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(rcsf_ptr); | 
|  | }; | 
|  |  | 
|  | };  // namespace rtc | 
|  |  | 
|  | #endif  // WEBRTC_BASE_REFERENCECOUNTEDSINGLETONFACTORY_H_ |