addded caching of EasyChannel and EasyGet; more work on lifecycle; EasyPut next

This commit is contained in:
Marty Kraimer
2015-03-03 15:26:02 -05:00
parent be69a74094
commit 5dc5e746f4
21 changed files with 547 additions and 107 deletions
+65 -7
View File
@@ -10,6 +10,7 @@
*/
#define epicsExportSharedSymbols
#include <map>
#include <sstream>
#include <pv/event.h>
#include <pv/lock.h>
@@ -24,6 +25,41 @@ using namespace std;
namespace epics { namespace easyPVA {
class EasyGetCache;
typedef std::tr1::shared_ptr<EasyGetCache> EasyGetCachePtr;
class EasyGetCache
{
public:
EasyGetCache(){}
~EasyGetCache();
void destroy() {
easyGetMap.clear();
}
EasyGetPtr getGet(string const & request);
void addGet(string const & request,EasyGetPtr const & easyGet);
private:
map<string,EasyGetPtr> easyGetMap;
};
EasyGetCache::~EasyGetCache()
{
destroy();
}
EasyGetPtr EasyGetCache::getGet(string const & request)
{
map<string,EasyGetPtr>::iterator iter = easyGetMap.find(request);
if(iter!=easyGetMap.end()) return iter->second;
return EasyGetPtr();
}
void EasyGetCache::addGet(string const & request,EasyGetPtr const & easyGet)
{
easyGetMap.insert(std::pair<string,EasyGetPtr>(
request,easyGet));
}
class epicsShareClass EasyChannelImpl :
public EasyChannel,
public std::tr1::enable_shared_from_this<EasyChannelImpl>
@@ -33,7 +69,7 @@ public:
EasyPVAPtr const &pva,
string const & channelName,
string const & providerName);
~EasyChannelImpl();
virtual ~EasyChannelImpl();
// from EasyChannel
void channelCreated(const Status& status, Channel::shared_pointer const & channel);
void channelStateChange(
@@ -54,6 +90,8 @@ public:
virtual EasyProcessPtr createProcess();
virtual EasyProcessPtr createProcess(string const & request);
virtual EasyProcessPtr createProcess(PVStructurePtr const & pvRequest);
virtual EasyGetPtr get() {return get("value,alarm,timeStamp");}
virtual EasyGetPtr get(string const & request);
virtual EasyGetPtr createGet();
virtual EasyGetPtr createGet(string const & request);
virtual EasyGetPtr createGet(PVStructurePtr const & pvRequest);
@@ -79,13 +117,14 @@ public:
}
private:
enum ConnectState {connectIdle,connectActive,notConnected,connected};
EasyPVAPtr easyPVA;
EasyPVA::weak_pointer easyPVA;
string channelName;
string providerName;
ConnectState connectState;
bool isDestroyed;
CreateRequest::shared_pointer createRequest;
EasyGetCachePtr easyGetCache;
Status channelConnectStatus;
Mutex mutex;
@@ -132,7 +171,8 @@ EasyChannelImpl::EasyChannelImpl(
providerName(providerName),
connectState(connectIdle),
isDestroyed(false),
createRequest(CreateRequest::create())
createRequest(CreateRequest::create()),
easyGetCache(new EasyGetCache())
{}
EasyChannelImpl::~EasyChannelImpl()
@@ -177,7 +217,9 @@ tr1::shared_ptr<Channel> EasyChannelImpl::getChannel()
string EasyChannelImpl::getRequesterName()
{
return easyPVA->getRequesterName();
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("EasyPVA was destroyed");
return yyy->getRequesterName();
}
void EasyChannelImpl::message(
@@ -185,7 +227,9 @@ void EasyChannelImpl::message(
MessageType messageType)
{
if(isDestroyed) throw std::runtime_error("easyChannel was destroyed");
easyPVA->message(message, messageType);
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("EasyPVA was destroyed");
yyy->message(message, messageType);
}
void EasyChannelImpl::destroy()
@@ -197,6 +241,7 @@ void EasyChannelImpl::destroy()
}
if(channel) channel->destroy();
channel.reset();
easyGetCache.reset();
}
string EasyChannelImpl::getChannelName()
@@ -274,6 +319,17 @@ EasyProcessPtr EasyChannelImpl::createProcess(PVStructurePtr const & pvRequest)
throw std::runtime_error("EasyChannel::createProcess not implemented");
}
EasyGetPtr EasyChannelImpl::get(string const & request)
{
EasyGetPtr easyGet = easyGetCache->getGet(request);
if(easyGet) return easyGet;
easyGet = createGet(request);
easyGet->connect();
easyGet->get();
easyGetCache->addGet(request,easyGet);
return easyGet;
}
EasyGetPtr EasyChannelImpl::createGet()
{
return EasyChannelImpl::createGet("value,alarm,timeStamp");
@@ -295,7 +351,9 @@ EasyGetPtr EasyChannelImpl::createGet(PVStructurePtr const & pvRequest)
{
if(connectState!=connected) connect(5.0);
if(connectState!=connected) throw std::runtime_error("EasyChannel::creatGet not connected");
return EasyGetFactory::createEasyGet(easyPVA,getPtrSelf(),channel,pvRequest);
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("EasyPVA was destroyed");
return EasyGetFactory::createEasyGet(yyy,getPtrSelf(),channel,pvRequest);
}
EasyPutPtr EasyChannelImpl::createPut()
+30 -26
View File
@@ -104,8 +104,8 @@ private:
void checkGetState();
enum GetConnectState {connectIdle,connectActive,connected};
EasyPVAPtr easyPVA;
EasyChannelPtr easyChannel;
EasyPVA::weak_pointer easyPVA;
EasyChannel::weak_pointer easyChannel;
Channel::shared_pointer channel;
ChannelGetRequester::shared_pointer getRequester;
PVStructurePtr pvRequest;
@@ -129,28 +129,28 @@ private:
};
namespace easyGet {
class ChannelGetRequesterImpl : public ChannelGetRequester
{
EasyGetImpl * easyGet;
public:
ChannelGetRequesterImpl(EasyGetImpl * easyGet)
: easyGet(easyGet) {}
virtual string getRequesterName()
{return easyGet->getRequesterName();}
virtual void message(string const & message,MessageType messageType)
{easyGet->message(message,messageType);}
virtual void channelGetConnect(
const Status& status,
ChannelGet::shared_pointer const & channelGet,
StructureConstPtr const & structure)
{easyGet->channelGetConnect(status,channelGet,structure);}
virtual void getDone(
const Status& status,
ChannelGet::shared_pointer const & channelGet,
PVStructurePtr const & pvStructure,
BitSetPtr const & bitSet)
{easyGet->getDone(status,channelGet,pvStructure,bitSet);}
};
class ChannelGetRequesterImpl : public ChannelGetRequester
{
EasyGetImpl * easyGet;
public:
ChannelGetRequesterImpl(EasyGetImpl * easyGet)
: easyGet(easyGet) {}
virtual string getRequesterName()
{return easyGet->getRequesterName();}
virtual void message(string const & message,MessageType messageType)
{easyGet->message(message,messageType);}
virtual void channelGetConnect(
const Status& status,
ChannelGet::shared_pointer const & channelGet,
StructureConstPtr const & structure)
{easyGet->channelGetConnect(status,channelGet,structure);}
virtual void getDone(
const Status& status,
ChannelGet::shared_pointer const & channelGet,
PVStructurePtr const & pvStructure,
BitSetPtr const & bitSet)
{easyGet->getDone(status,channelGet,pvStructure,bitSet);}
};
} // namespace easyGet
using namespace epics::easyPVA::easyGet;
@@ -187,13 +187,17 @@ void EasyGetImpl::checkGetState()
// from ChannelGetRequester
string EasyGetImpl::getRequesterName()
{
return easyPVA->getRequesterName();
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("easyPVA was destroyed");
return yyy->getRequesterName();
}
void EasyGetImpl::message(string const & message,MessageType messageType)
{
if(isDestroyed) throw std::runtime_error("easyGet was destroyed");
easyPVA->message(message, messageType);
EasyPVAPtr yyy = easyPVA.lock();
if(!yyy) throw std::runtime_error("easyPVA was destroyed");
yyy->message(message, messageType);
}
void EasyGetImpl::channelGetConnect(
+82 -43
View File
@@ -8,7 +8,9 @@
* @author mrk
* @date 2015.02
*/
#define epicsExportSharedSymbols
#define epicsExportSharedSymbols
#include <map>
#include <pv/easyPVA.h>
#include <pv/createRequest.h>
#include <pv/clientFactory.h>
@@ -27,35 +29,71 @@ static UnionConstPtr variantUnion = fieldCreate->createVariantUnion();
namespace easyPVAPvt {
static size_t numberEasyPVA = 0;
static bool firstTime = true;
static Mutex mutex;
class StartStopClientFactory {
public:
static void EasyPVABeingConstructed()
{
bool saveFirst = false;
{
Lock xx(mutex);
++numberEasyPVA;
saveFirst = firstTime;
firstTime = false;
}
if(saveFirst) ClientFactory::start();
}
static void EasyPVABeingDestroyed() {
size_t numLeft = 0;
static size_t numberEasyPVA = 0;
static bool firstTime = true;
static Mutex mutex;
class StartStopClientFactory {
public:
static void EasyPVABeingConstructed()
{
Lock xx(mutex);
--numberEasyPVA;
numLeft = numberEasyPVA;
bool saveFirst = false;
{
Lock xx(mutex);
++numberEasyPVA;
saveFirst = firstTime;
firstTime = false;
}
if(saveFirst) ClientFactory::start();
}
if(numLeft<=0) ClientFactory::stop();
static void EasyPVABeingDestroyed() {
size_t numLeft = 0;
{
Lock xx(mutex);
--numberEasyPVA;
numLeft = numberEasyPVA;
}
if(numLeft<=0) ClientFactory::stop();
}
};
} // namespace easyPVAPvt
class EasyChannelCache
{
public:
EasyChannelCache(){}
~EasyChannelCache(){
destroy();
}
void destroy() {
easyChannelMap.clear();
}
EasyChannelPtr getChannel(string const & channelName);
void addChannel(EasyChannelPtr const & easyChannel);
void removeChannel(string const & channelName);
private:
map<string,EasyChannelPtr> easyChannelMap;
};
EasyChannelPtr EasyChannelCache::getChannel(string const & channelName)
{
map<string,EasyChannelPtr>::iterator iter = easyChannelMap.find(channelName);
if(iter!=easyChannelMap.end()) return iter->second;
return EasyChannelPtr();
}
void EasyChannelCache::addChannel(EasyChannelPtr const & easyChannel)
{
easyChannelMap.insert(std::pair<string,EasyChannelPtr>(
easyChannel->getChannelName(),easyChannel));
}
void EasyChannelCache::removeChannel(string const & channelName)
{
map<string,EasyChannelPtr>::iterator iter = easyChannelMap.find(channelName);
if(iter!=easyChannelMap.end()) easyChannelMap.erase(iter);
}
using namespace epics::easyPVA::easyPVAPvt;
@@ -79,7 +117,8 @@ PVStructurePtr EasyPVA::createRequest(string const &request)
}
EasyPVA::EasyPVA()
: isDestroyed(false)
: easyChannelCache(new EasyChannelCache()),
isDestroyed(false)
{
}
@@ -94,22 +133,9 @@ void EasyPVA::destroy()
if(isDestroyed) return;
isDestroyed = true;
}
std::list<EasyChannelPtr>::iterator channelIter;
while(true) {
channelIter = channelList.begin();
if(channelIter==channelList.end()) break;
channelList.erase(channelIter);
(*channelIter)->destroy();
}
#ifdef NOTDONE
std::list<EasyMultiChannelPtr>::iterator multiChannelIter;
while(true) {
multiChannelIter = multiChannelList.begin();
if(multiChannelIter==multiChannelList.end()) break;
multiChannelList.erase(multiChannelIter);
(*multiChannelIter)->destroy();
}
#endif
easyChannelCache.reset();
channelList.clear();
multiChannelList.clear();
StartStopClientFactory::EasyPVABeingDestroyed();
}
@@ -131,6 +157,19 @@ EasyPVStructurePtr EasyPVA::createEasyPVStructure()
return EasyPVStructureFactory::createEasyPVStructure();
}
EasyChannelPtr EasyPVA::channel(
std::string const & channelName,
std::string const & providerName,
double timeOut)
{
EasyChannelPtr easyChannel = easyChannelCache->getChannel(channelName);
if(easyChannel) return easyChannel;
easyChannel = createChannel(channelName,providerName);
easyChannel->connect(timeOut);
easyChannelCache->addChannel(easyChannel);
return easyChannel;
}
EasyChannelPtr EasyPVA::createChannel(string const & channelName)
{
return EasyChannelFactory::createEasyChannel(getPtrSelf(),channelName);
+42 -4
View File
@@ -74,6 +74,10 @@ typedef std::tr1::shared_ptr<EasyMultiPut> EasyMultiPutPtr;
class EasyMultiMonitor;
typedef std::tr1::shared_ptr<EasyMultiMonitor> EasyMultiMonitorPtr;
// following are private to easyPVA
class EasyChannelCache;
typedef std::tr1::shared_ptr<EasyChannelCache> EasyChannelCachePtr;
/**
* @brief EasyPVA is an easy to use interface to pvAccess.
*
@@ -89,7 +93,7 @@ public:
/**
* Destructor
*/
~EasyPVA();
virtual ~EasyPVA();
/**
* @brief Create an instance of EasyPVA
* @return shared_ptr to new instance.
@@ -119,8 +123,27 @@ public:
* @return The interface to the EasyPVStructure.
*/
EasyPVStructurePtr createEasyPVStructure();
/**
* @brief get a cached channel or create and connect to a new channel.
* The provider is pva. The timeout is 5 seconds.
* If connection can not be made an exception is thrown.
* @param channelName The channelName.
* @return The interface.
*/
EasyChannelPtr channel(std::string const & channelName)
{ return channel(channelName,"pva", 5.0); }
/**
* @brief Create an EasyChannel. The provider is pvAccess.
* @brief get a cached channel or create and connect to a new channel.
* If connection can not be made an exception is thrown.
* @param channelName The channelName.
* @return The interface.
*/
EasyChannelPtr channel(
std::string const & channelName,
std::string const &providerName,
double timeOut);
/**
* @brief Create an EasyChannel. The provider is pva.
* @param channelName The channelName.
* @return The interface.
*/
@@ -179,11 +202,12 @@ public:
}
private:
EasyPVA();
epics::pvData::PVStructurePtr createRequest(std::string const &request);
EasyChannelCachePtr easyChannelCache;
epics::pvData::PVStructurePtr createRequest(std::string const &request);
std::list<EasyChannelPtr> channelList;
std::list<EasyMultiChannelPtr> multiChannelList;
epics::pvData::RequesterPtr requester;
epics::pvData::Requester::weak_pointer requester;
bool isDestroyed;
epics::pvData::Mutex mutex;
};
@@ -197,6 +221,7 @@ class epicsShareClass EasyChannel
{
public:
POINTER_DEFINITIONS(EasyChannel);
virtual ~EasyChannel() { }
/**
* @brief Destroy the pvAccess connection.
*/
@@ -251,6 +276,19 @@ public:
* @return The interface.
*/
virtual EasyProcessPtr createProcess(epics::pvData::PVStructurePtr const & pvRequest) = 0;
/**
* @brief Call the next method with request = "field(value,alarm,timeStamp)"
* @return The interface.
*/
virtual EasyGetPtr get() = 0;
/**
* @brief get a cached EasyGet or create and connect to a new EasyGet.
* Then call it's get method.
* If connection can not be made an exception is thrown.
* @param request The request as described in package org.epics.pvdata.copy
* @return The interface.
*/
virtual EasyGetPtr get(std::string const & request) = 0;
/**
* @brief Call the next method with request = "field(value,alarm,timeStamp)"
* @return The interface.