pvaTestClient: channel cache

This commit is contained in:
Michael Davidsaver
2017-07-10 15:03:19 +02:00
parent f564a60fa1
commit 7c1ac4ef00
2 changed files with 70 additions and 7 deletions

View File

@@ -17,6 +17,8 @@ class Monitor;
class Configuration;
}}//namespace epics::pvAccess
class TestClientProvider;
//! Information on get/put/rpc completion
struct epicsShareClass TestOperation
{
@@ -109,11 +111,15 @@ class epicsShareClass TestClientChannel
{
struct Impl;
std::tr1::shared_ptr<Impl> impl;
friend class TestClientProvider;
TestClientChannel(const std::tr1::shared_ptr<Impl>& i) :impl(i) {}
public:
struct Options {
short priority;
std::string address;
Options();
bool operator<(const Options&) const;
};
TestClientChannel() {}
@@ -186,7 +192,8 @@ private:
//! Central client context.
class epicsShareClass TestClientProvider
{
std::tr1::shared_ptr<epics::pvAccess::ChannelProvider> provider;
struct Impl;
std::tr1::shared_ptr<Impl> impl;
public:
TestClientProvider(const std::string& providerName,
@@ -195,8 +202,17 @@ public:
//! Get a new Channel
//! Does not block.
//! Never returns NULL.
//! Uses internal Channel cache.
TestClientChannel connect(const std::string& name,
const TestClientChannel::Options& conf = TestClientChannel::Options());
//! Remove from channel cache
bool disconnect(const std::string& name,
const TestClientChannel::Options& conf = TestClientChannel::Options());
//! Clear channel cache
void disconnect();
};
#endif // PVATESTCLIENT_H

View File

@@ -67,6 +67,11 @@ TestClientChannel::Options::Options()
,address()
{}
bool TestClientChannel::Options::operator<(const Options& O) const
{
return priority<O.priority || (priority==O.priority && address<O.address);
}
TestOperation::TestOperation(const std::tr1::shared_ptr<Impl>& i)
:impl(i)
{}
@@ -138,14 +143,24 @@ std::tr1::shared_ptr<epics::pvAccess::Channel>
TestClientChannel::getChannel()
{ return impl->channel; }
struct TestClientProvider::Impl
{
pva::ChannelProvider::shared_pointer provider;
epicsMutex mutex;
typedef std::map<std::pair<std::string, TestClientChannel::Options>, std::tr1::weak_ptr<TestClientChannel::Impl> > channels_t;
channels_t channels;
};
TestClientProvider::TestClientProvider(const std::string& providerName,
const std::tr1::shared_ptr<epics::pvAccess::Configuration>& conf)
:provider(pva::ChannelProviderRegistry::clients()->createProvider(providerName,
conf ? conf : pva::ConfigurationBuilder()
.push_env()
.build()))
:impl(new Impl)
{
if(!provider)
impl->provider = pva::ChannelProviderRegistry::clients()->createProvider(providerName,
conf ? conf : pva::ConfigurationBuilder()
.push_env()
.build());
if(!impl->provider)
THROW_EXCEPTION2(std::invalid_argument, providerName);
}
@@ -155,5 +170,37 @@ TestClientChannel
TestClientProvider::connect(const std::string& name,
const TestClientChannel::Options& conf)
{
return TestClientChannel(provider, name, conf);
Guard G(impl->mutex);
Impl::channels_t::key_type K(name, conf);
Impl::channels_t::iterator it(impl->channels.find(K));
if(it!=impl->channels.end()) {
// cache hit
std::tr1::shared_ptr<TestClientChannel::Impl> chan(it->second.lock());
if(chan)
return TestClientChannel(chan);
else
impl->channels.erase(it); // remove stale
}
// cache miss
TestClientChannel ret(impl->provider, name, conf);
impl->channels[K] = ret.impl;
return ret;
}
bool TestClientProvider::disconnect(const std::string& name,
const TestClientChannel::Options& conf)
{
Guard G(impl->mutex);
Impl::channels_t::iterator it(impl->channels.find(std::make_pair(name, conf)));
bool found = it!=impl->channels.end();
if(found)
impl->channels.erase(it);
return found;
}
void TestClientProvider::disconnect()
{
Guard G(impl->mutex);
impl->channels.clear();
}