| /* |
| * 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_ |