// Registrar.h -- Registrar template class // (c) Copyright Schlumberger Technology Corp., unpublished work, created // 1999. This computer program includes Confidential, Proprietary // Information and is a Trade Secret of Schlumberger Technology Corp. All // use, disclosure, and/or reproduction is prohibited unless authorized // in writing. All Rights Reserved. #if !defined(SLBCSP_REGISTRAR_H) #define SLBCSP_REGISTRAR_H #include #include #include #include "Guarded.h" #include "Registry.h" #include "MasterLock.h" template > class Registrar { public: // Types typedef T *EnrolleeType; typedef Key KeyType; typedef std::map CollectionType; typedef Registry RegistryType; typedef Registry ConstRegistryType; // C'tors/D'tors // Operators // Operations // Removes the enrollee identified by the key from the registry. static void Discard(Key const &rkey); // Return the enrollee identified by the key, creating it if it // doesn't exist. static EnrolleeType Instance(Key const &rkey); // Access // Return the enrollee identified by the key if it exists, 0 otherwise. static EnrolleeType Find(Key const &rKey); static ConstRegistryType & Registry(); // Predicates protected: // Types // C'tors/D'tors explicit Registrar(Key const &rkey); // allow subclassing virtual ~Registrar() = 0; // make base abstract // Operators // Operations // Puts the enrollee into the registry identified by the key if // not already listed. static void Enroll(Key const &rkey, EnrolleeType enrollee); // Removes an entry from the registry. static void RemoveEnrollee(Key const &rkey); // Inserts an entry into the registry. static void InsertEnrollee(Key const &rkey, EnrolleeType enrollee); // Operation to perform after removing the enrollee from the // registry. Default does nothing. virtual void DiscardHook(); // Subclass must define // Factory Method, operation returning a new enrollee for the key static EnrolleeType DoInstantiation(Key const &rkey); // Operation to perform after putting the enrollee into the // registry. Default does nothing. virtual void EnrollHook(); // Access // Predicates // Returns true if the enrollee should remain in the registry; // false otherwise. Default returns true. virtual bool KeepEnrolled(); // Static Variables // Variables private: // Types typedef typename Registrar *BaseType; typedef CollectionType::iterator Iterator; typedef CollectionType::value_type ValueType; // C'tors/D'tors Registrar(Registrar const &); // don't allow copies // Operators Registrar & operator=(Registrar const &); // don't allow initialization // Operations static void Discard(Iterator const &rit); static void RemoveEnrollee(Iterator const &rit); static EnrolleeType FindEnrollee(Key const &rkey); static void SetupRegistry(); // Access static CollectionType & Collection(); // Predicates static bool PassesReview(EnrolleeType enrollee); // Variables static RegistryType *m_pregistry; }; ///////////////////////// TEMPLATE METHODS /////////////////////////////// /////////////////////////// PUBLIC ///////////////////////////////// // C'tors/D'tors // Operators // Operations template void Registrar::Discard(Key const &rkey) { if (m_pregistry) { Guarded gregistry(m_pregistry); // serialize registry access CollectionType &rcollection = Collection(); Iterator it = rcollection.find(rkey); if (rcollection.end() != it) Discard(it); } } template Registrar::EnrolleeType Registrar::Instance(Key const &rkey) { // The Template Method pattern is used to allow the instantiator // of the template to specify how the the enrollee is found and, // if necessary, created. Template Method can be found in "Design // Patterns: Elements of Reusable Object-Oriented Software," // Gamma, Helm, Johnson, Vlissides, Addison-Wesley SetupRegistry(); Guarded gregistry(m_pregistry); // serialize registry access EnrolleeType enrollee = FindEnrollee(rkey); if (EnrolleeType() == enrollee) { enrollee = T::DoInstantiation(rkey); Enroll(rkey, enrollee); } return enrollee; } // Access template Registrar::EnrolleeType Registrar::Find(Key const &rkey) { EnrolleeType enrollee = EnrolleeType(); if (m_pregistry) { Guarded guard(m_pregistry); // serialize registry access enrollee = FindEnrollee(rkey); } return enrollee; } template Registrar::ConstRegistryType & Registrar::Registry() { SetupRegistry(); // this "safe" cast is necessary to enforce the constness of the collection return reinterpret_cast(*m_pregistry); } // Predicates // Static Variables /////////////////////////// PROTECTED ///////////////////////////////// // C'tors/D'tors template Registrar::Registrar(Key const &rkey) {} template Registrar::~Registrar() {} // Operators // Operations template void Registrar::DiscardHook() {} template void Registrar::EnrollHook() {} template void Registrar::RemoveEnrollee(Key const &rkey) { if (m_pregistry) { Guarded gregistry(m_pregistry); // serialize registry access CollectionType &rcollection = Collection(); Iterator it = rcollection.find(rkey); if (rcollection.end() != it) RemoveEnrollee(it); } } template void Registrar::InsertEnrollee(Key const &rkey, Registrar::EnrolleeType enrollee) { ValueType registration(rkey, enrollee); Guarded guard(m_pregistry); // serialize registry access Collection().insert(registration); } // Access // Predicates template bool Registrar::KeepEnrolled() { return true; } template void Registrar::Enroll(Key const &rkey, Registrar::EnrolleeType enrollee) { Guarded guard(m_pregistry); // serialize registry access InsertEnrollee(rkey, enrollee); BaseType base = enrollee; base->EnrollHook(); } /////////////////////////// PRIVATE ///////////////////////////////// // C'tors/D'tors // Operators // Operations template void Registrar::Discard(Registrar::Iterator const &rit) { BaseType base = rit->second; RemoveEnrollee(rit); base->DiscardHook(); } template void Registrar::RemoveEnrollee(Registrar::Iterator const &rit) { Collection().erase(rit); } template Registrar::EnrolleeType Registrar::FindEnrollee(Key const &rkey) { EnrolleeType enrollee = EnrolleeType(); CollectionType &rcollection = Collection(); if (!rcollection.empty()) { Iterator it = rcollection.find(rkey); if (rcollection.end() != it) { enrollee = it->second; if (!PassesReview(enrollee)) { Discard(it); enrollee = EnrolleeType(); } } } return enrollee; } template void Registrar::SetupRegistry() { // Use Double-Checked Lock pattern for proper setup in the case of // preemptive multi-threading if (!m_pregistry) { Guarded gmaster(&TheMasterLock()); if (!m_pregistry) m_pregistry = new RegistryType; } } // Access template Registrar::CollectionType & Registrar::Collection() { return (*m_pregistry)(); } // Predicates template bool Registrar::PassesReview(Registrar::EnrolleeType enrollee) { bool fPassed = false; if (EnrolleeType() != enrollee) { BaseType base = enrollee; fPassed = base->KeepEnrolled(); } return fPassed; } #endif // SLBCSP_REGISTRAR_H