diff --git a/src/client/pv/pvAccess.h b/src/client/pv/pvAccess.h index 937c54a..d8430f7 100644 --- a/src/client/pv/pvAccess.h +++ b/src/client/pv/pvAccess.h @@ -958,41 +958,124 @@ public: } }; +//! Simple ChannelProviderFactory which requires the existance of a ctor +//! Provider(const std::tr1::shared_ptr& conf) +//! which is called with a Configuration instance or NULL (use some defaults) +template +struct SimpleChannelProviderFactory : public ChannelProviderFactory +{ + SimpleChannelProviderFactory(const std::string& name) :pname(name) {} + virtual ~SimpleChannelProviderFactory() {} + + virtual std::string getFactoryName() { return pname; } + + virtual ChannelProvider::shared_pointer sharedInstance() + { + epics::pvData::Lock L(sharedM); + if(!shared) { + std::tr1::shared_ptr empty; + shared.reset(new Provider(empty)); + } + return shared; + } + + virtual ChannelProvider::shared_pointer newInstance(const std::tr1::shared_ptr& conf) + { + ChannelProvider::shared_pointer ret(new Provider(conf)); + return ret; + } + +private: + const std::string pname; + epics::pvData::Mutex sharedM; + std::tr1::shared_ptr shared; +}; + /** * Interface for locating channel providers. */ -class epicsShareClass ChannelProviderRegistry : private epics::pvData::NoDefaultMethods { +class epicsShareClass ChannelProviderRegistry { public: POINTER_DEFINITIONS(ChannelProviderRegistry); typedef std::vector stringVector_t; - virtual ~ChannelProviderRegistry() {}; - /** * Get a shared instance of the provider with the specified name. * @param providerName The name of the provider. * @return The interface for the provider or null if the provider is not known. */ - virtual ChannelProvider::shared_pointer getProvider(std::string const & providerName) = 0; + ChannelProvider::shared_pointer getProvider(std::string const & providerName); /** * Creates a new instanceof the provider with the specified name. * @param providerName The name of the provider. * @return The interface for the provider or null if the provider is not known. */ - virtual ChannelProvider::shared_pointer createProvider(std::string const & providerName) = 0; + ChannelProvider::shared_pointer createProvider(std::string const & providerName); + + /** + * Creates a new instanceof the provider with the specified name. + * @param providerName The name of the provider. + * @return The interface for the provider or null if the provider is not known. + */ + ChannelProvider::shared_pointer createProvider(std::string const & providerName, + const std::tr1::shared_ptr& conf); + + /** + * Fetch provider factor with the specified name. + * @param providerName The name of the provider. + * @return The factor or null if the provider is not known. + */ + ChannelProviderFactory::shared_pointer getFactory(std::string const & providerName); /** * Get a array of the names of all the known providers. * @return The names. Be sure to delete vector instance. */ - virtual std::auto_ptr getProviderNames() = 0; + std::auto_ptr getProviderNames(); + + + static ChannelProviderRegistry::shared_pointer build() { + ChannelProviderRegistry::shared_pointer ret(new ChannelProviderRegistry); + return ret; + } + + //! Add new factory. if replace=false and name already in use, return false with no change + //! in other cases insert provided factory and return true. + bool add(const ChannelProviderFactory::shared_pointer& fact, bool replace=true); + + //! Add a new Provider which will be built using SimpleChannelProviderFactory + template + bool add(const std::string& name, bool replace=true) + { + typedef SimpleChannelProviderFactory Factory; + typename Factory::shared_pointer fact(new Factory(name)); + return add(fact, replace); + } + + //! Attempt to remove named factory. Return Factory which was removed, or NULL if not found. + ChannelProviderFactory::shared_pointer remove(const std::string& name); + + //! Drop all factories + void clear() + { + providers.clear(); + } + +private: + ChannelProviderRegistry() {} + + epics::pvData::Mutex mutex; + typedef std::map providers_t; + providers_t providers; }; +//! never returns NULL epicsShareFunc ChannelProviderRegistry::shared_pointer getChannelProviderRegistry(); epicsShareFunc void registerChannelProviderFactory(ChannelProviderFactory::shared_pointer const & channelProviderFactory); epicsShareFunc void unregisterChannelProviderFactory(ChannelProviderFactory::shared_pointer const & channelProviderFactory); +epicsShareFunc void unregisterAllChannelProviderFactory(); /** diff --git a/src/factory/ChannelAccessFactory.cpp b/src/factory/ChannelAccessFactory.cpp index 1c18b51..97f0a8d 100644 --- a/src/factory/ChannelAccessFactory.cpp +++ b/src/factory/ChannelAccessFactory.cpp @@ -21,76 +21,100 @@ using std::string; namespace epics { namespace pvAccess { -static ChannelProviderRegistry::shared_pointer ChannelProviderRegistry; +ChannelProvider::shared_pointer ChannelProviderRegistry::getProvider(std::string const & providerName) { + ChannelProviderFactory::shared_pointer fact(getFactory(providerName)); + if(fact) + return fact->sharedInstance(); + else + return ChannelProvider::shared_pointer(); +} -static Mutex channelProviderMutex; +ChannelProvider::shared_pointer ChannelProviderRegistry::createProvider(std::string const & providerName) { + ChannelProviderFactory::shared_pointer fact(getFactory(providerName)); + if(fact) + return fact->newInstance(); + else + return ChannelProvider::shared_pointer(); +} -typedef std::map ChannelProviderFactoryMap; -static ChannelProviderFactoryMap channelProviders; +ChannelProvider::shared_pointer ChannelProviderRegistry::createProvider(std::string const & providerName, + const std::tr1::shared_ptr& conf) { + ChannelProviderFactory::shared_pointer fact(getFactory(providerName)); + if(fact) + return fact->newInstance(conf); + else + return ChannelProvider::shared_pointer(); +} +ChannelProviderFactory::shared_pointer ChannelProviderRegistry::getFactory(std::string const & providerName) +{ + Lock G(mutex); + providers_t::const_iterator iter = providers.find(providerName); + if (iter == providers.end()) + return ChannelProviderFactory::shared_pointer(); + else + return iter->second; +} -class ChannelProviderRegistryImpl : public ChannelProviderRegistry { -public: +std::auto_ptr ChannelProviderRegistry::getProviderNames() +{ + Lock G(mutex); + std::auto_ptr ret(new stringVector_t); + for (providers_t::const_iterator iter = providers.begin(); + iter != providers.end(); iter++) + ret->push_back(iter->first); - ChannelProvider::shared_pointer getProvider(std::string const & providerName) { + return ret; +} - ChannelProviderFactory::shared_pointer providerFactory; - { - Lock guard(channelProviderMutex); - ChannelProviderFactoryMap::const_iterator iter = channelProviders.find(providerName); - if (iter == channelProviders.end()) - return ChannelProvider::shared_pointer(); - else - providerFactory = iter->second; - } - return providerFactory->sharedInstance(); +bool ChannelProviderRegistry::add(const ChannelProviderFactory::shared_pointer& fact, bool replace) +{ + Lock G(mutex); + std::string name(fact->getFactoryName()); + if(!replace && providers.find(name)!=providers.end()) + throw false; + providers[name] = fact; + return true; +} + +ChannelProviderFactory::shared_pointer ChannelProviderRegistry::remove(const std::string& name) +{ + ChannelProviderFactory::shared_pointer ret; + providers_t::iterator iter(providers.find(name)); + if(iter!=providers.end()) { + ret = iter->second; + providers.erase(iter); } - - ChannelProvider::shared_pointer createProvider(std::string const & providerName) { - - ChannelProviderFactory::shared_pointer providerFactory; - { - Lock guard(channelProviderMutex); - ChannelProviderFactoryMap::const_iterator iter = channelProviders.find(providerName); - if (iter == channelProviders.end()) - return ChannelProvider::shared_pointer(); - else - providerFactory = iter->second; - } - return providerFactory->newInstance(); - } - - std::auto_ptr getProviderNames() { - Lock guard(channelProviderMutex); - std::auto_ptr providers(new stringVector_t()); - for (ChannelProviderFactoryMap::const_iterator i = channelProviders.begin(); - i != channelProviders.end(); i++) - providers->push_back(i->first); - - return providers; - } -}; + return ret; +} ChannelProviderRegistry::shared_pointer getChannelProviderRegistry() { static Mutex mutex; + static ChannelProviderRegistry::shared_pointer global_reg; Lock guard(mutex); - if(ChannelProviderRegistry.get()==0) { - ChannelProviderRegistry.reset(new ChannelProviderRegistryImpl()); + if(!global_reg) { + global_reg = ChannelProviderRegistry::build(); } - return ChannelProviderRegistry; + return global_reg; } void registerChannelProviderFactory(ChannelProviderFactory::shared_pointer const & channelProviderFactory) { - Lock guard(channelProviderMutex); - channelProviders[channelProviderFactory->getFactoryName()] = channelProviderFactory; + assert(channelProviderFactory); + getChannelProviderRegistry()->add(channelProviderFactory); } void unregisterChannelProviderFactory(ChannelProviderFactory::shared_pointer const & channelProviderFactory) { - Lock guard(channelProviderMutex); - channelProviders.erase(channelProviderFactory->getFactoryName()); + assert(channelProviderFactory); + getChannelProviderRegistry()->remove(channelProviderFactory->getFactoryName()); } +epicsShareFunc void unregisterAllChannelProviderFactory() +{ + getChannelProviderRegistry()->clear(); +} + + } } diff --git a/testApp/remote/testServerContext.cpp b/testApp/remote/testServerContext.cpp index 4584fcb..697dee3 100644 --- a/testApp/remote/testServerContext.cpp +++ b/testApp/remote/testServerContext.cpp @@ -17,6 +17,7 @@ public: return "local"; }; + TestChannelProvider(const std::tr1::shared_ptr&) {} ChannelFind::shared_pointer channelFind(std::string const & /*channelName*/, ChannelFindRequester::shared_pointer const & channelFindRequester) @@ -57,41 +58,12 @@ public: } }; - -class TestChannelProviderRegistry : public ChannelProviderRegistry { -public: - - virtual ~TestChannelProviderRegistry() {}; - - ChannelProvider::shared_pointer getProvider(std::string const & providerName) - { - if (providerName == "local") - { - return ChannelProvider::shared_pointer(new TestChannelProvider()); - } - else - return ChannelProvider::shared_pointer(); - } - - ChannelProvider::shared_pointer createProvider(std::string const & providerName) - { - return getProvider(providerName); - } - - std::auto_ptr getProviderNames() - { - std::auto_ptr pn(new stringVector_t()); - pn->push_back("local"); - return pn; - } -}; - void testServerContext() { - ServerContextImpl::shared_pointer ctx = ServerContextImpl::create(); - ChannelProviderRegistry::shared_pointer ca(new TestChannelProviderRegistry()); + ChannelProviderRegistry::shared_pointer ca(ChannelProviderRegistry::build()); + ca->add("local"); ctx->initialize(ca); ctx->printInfo();