Home | History | Annotate | Download | only in base
      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:
     35   ReferenceCountedSingletonFactory() : ref_count_(0) {}
     36 
     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:
     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 
     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.
     88   explicit rcsf_ptr(ReferenceCountedSingletonFactory<Interface>* factory)
     89       : instance_(NULL),
     90         factory_(factory) {
     91   }
     92 
     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.
    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.
    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.
    126   bool valid() const {
    127     return instance_ != NULL;
    128   }
    129 
    130   // Returns the factory that this pointer is using.
    131   ReferenceCountedSingletonFactory<Interface>* factory() const {
    132     return factory_;
    133   }
    134 
    135  private:
    136   void EnsureAcquired() {
    137     Acquire();
    138     ASSERT(instance_ != NULL);
    139   }
    140 
    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