#ifndef UTILITIES_H #define UTILITIES_H #include #include #include #include #include #include #include #include #include "pvahelper.h" #include "weakmap.h" #include "weakset.h" #include struct TestPV; struct TestPVChannel; struct TestPVMonitor; struct TestProvider; // minimally useful boilerplate which must appear *everywhere* #define DUMBREQUESTER(NAME) \ virtual std::string getRequesterName() OVERRIDE { return #NAME; } template inline std::string toString(const T& tbs) { std::ostringstream oss; oss << tbs; return oss.str(); } // Boilerplate reduction for accessing a scalar field template struct ScalarAccessor { epics::pvData::PVScalar::shared_pointer field; typedef T value_type; ScalarAccessor(const epics::pvData::PVStructurePtr& s, const char *name) :field(s->getSubFieldT(name)) {} operator value_type() { return field->getAs(); } ScalarAccessor& operator=(T v) { field->putFrom(v); return *this; } ScalarAccessor& operator+=(T v) { field->putFrom(field->getAs()+v); return *this; } }; struct epicsShareClass TestChannelRequester : public epics::pvAccess::ChannelRequester { POINTER_DEFINITIONS(TestChannelRequester); DUMBREQUESTER(TestChannelRequester) epicsMutex lock; epicsEvent wait; epics::pvAccess::Channel::shared_pointer chan; epics::pvData::Status status; epics::pvAccess::Channel::ConnectionState laststate; TestChannelRequester(); virtual ~TestChannelRequester(); virtual void channelCreated(const epics::pvData::Status& status, epics::pvAccess::Channel::shared_pointer const & channel); virtual void channelStateChange(epics::pvAccess::Channel::shared_pointer const & channel, epics::pvAccess::Channel::ConnectionState connectionState); bool waitForConnect(); }; struct epicsShareClass TestChannelFieldRequester : public epics::pvAccess::GetFieldRequester { POINTER_DEFINITIONS(TestChannelFieldRequester); DUMBREQUESTER(TestChannelFieldRequester) bool done; epics::pvData::Status status; epics::pvData::FieldConstPtr fielddesc; TestChannelFieldRequester() :done(false) {} virtual ~TestChannelFieldRequester() {} virtual void getDone( const epics::pvData::Status& status, epics::pvData::FieldConstPtr const & field) { this->status = status; fielddesc = field; done = true; } }; struct epicsShareClass TestChannelGetRequester : public epics::pvAccess::ChannelGetRequester { POINTER_DEFINITIONS(TestChannelGetRequester); DUMBREQUESTER(TestChannelGetRequester) bool connected, done; epics::pvData::Status statusConnect, statusDone; epics::pvAccess::ChannelGet::shared_pointer channelGet; epics::pvData::Structure::const_shared_pointer fielddesc; epics::pvData::PVStructure::shared_pointer value; epics::pvData::BitSet::shared_pointer changed; TestChannelGetRequester(); virtual ~TestChannelGetRequester(); virtual void channelGetConnect( const epics::pvData::Status& status, epics::pvAccess::ChannelGet::shared_pointer const & channelGet, epics::pvData::Structure::const_shared_pointer const & structure); virtual void getDone( const epics::pvData::Status& status, epics::pvAccess::ChannelGet::shared_pointer const & channelGet, epics::pvData::PVStructure::shared_pointer const & pvStructure, epics::pvData::BitSet::shared_pointer const & bitSet); }; struct epicsShareClass TestChannelPutRequester : public epics::pvAccess::ChannelPutRequester { POINTER_DEFINITIONS(TestChannelPutRequester); DUMBREQUESTER(TestChannelPutRequester) bool connected, doneGet, donePut; epics::pvData::Status statusConnect, statusPut, statusGet; epics::pvAccess::ChannelPut::shared_pointer put; epics::pvData::Structure::const_shared_pointer fielddesc; epics::pvData::PVStructure::shared_pointer value; epics::pvData::BitSet::shared_pointer changed; TestChannelPutRequester(); virtual ~TestChannelPutRequester(); virtual void channelPutConnect( const epics::pvData::Status& status, epics::pvAccess::ChannelPut::shared_pointer const & channelPut, epics::pvData::Structure::const_shared_pointer const & structure); virtual void putDone( const epics::pvData::Status& status, epics::pvAccess::ChannelPut::shared_pointer const & channelPut); virtual void getDone( const epics::pvData::Status& status, epics::pvAccess::ChannelPut::shared_pointer const & channelPut, epics::pvData::PVStructure::shared_pointer const & pvStructure, epics::pvData::BitSet::shared_pointer const & bitSet); }; struct epicsShareClass TestChannelMonitorRequester : public epics::pvData::MonitorRequester { POINTER_DEFINITIONS(TestChannelMonitorRequester); DUMBREQUESTER(TestChannelMonitorRequester) epicsMutex lock; epicsEvent wait; bool connected; bool unlistend; size_t eventCnt; epics::pvData::Status connectStatus; epics::pvData::MonitorPtr mon; epics::pvData::StructureConstPtr dtype; TestChannelMonitorRequester(); virtual ~TestChannelMonitorRequester(); virtual void monitorConnect(epics::pvData::Status const & status, epics::pvData::MonitorPtr const & monitor, epics::pvData::StructureConstPtr const & structure); virtual void monitorEvent(epics::pvData::MonitorPtr const & monitor); virtual void unlisten(epics::pvData::MonitorPtr const & monitor); bool waitForConnect(); bool waitForEvent(); }; struct epicsShareClass TestPVChannel : public BaseChannel { POINTER_DEFINITIONS(TestPVChannel); DUMBREQUESTER(TestPVChannel) std::tr1::weak_ptr weakself; const std::tr1::shared_ptr pv; ConnectionState state; typedef weak_set monitors_t; monitors_t monitors; TestPVChannel(const std::tr1::shared_ptr& pv, const std::tr1::shared_ptr& req); virtual ~TestPVChannel(); virtual std::string getRemoteAddress() { return "localhost:1234"; } virtual ConnectionState getConnectionState(); virtual void getField(epics::pvAccess::GetFieldRequester::shared_pointer const & requester,std::string const & subField); virtual epics::pvData::Monitor::shared_pointer createMonitor( epics::pvData::MonitorRequester::shared_pointer const & monitorRequester, epics::pvData::PVStructure::shared_pointer const & pvRequest); virtual void printInfo(std::ostream& out) {} }; struct epicsShareClass TestPVMonitor : public epics::pvData::Monitor { POINTER_DEFINITIONS(TestPVMonitor); std::tr1::weak_ptr weakself; const TestPVChannel::shared_pointer channel; const epics::pvData::MonitorRequester::weak_pointer requester; bool running; bool finalize; bool inoverflow; bool needWakeup; TestPVMonitor(const TestPVChannel::shared_pointer& ch, const epics::pvData::MonitorRequester::shared_pointer& req, size_t bsize); virtual ~TestPVMonitor(); virtual void destroy(); virtual epics::pvData::Status start(); virtual epics::pvData::Status stop(); virtual epics::pvData::MonitorElementPtr poll(); virtual void release(epics::pvData::MonitorElementPtr const & monitorElement); std::deque buffer, free; epics::pvData::MonitorElementPtr overflow; }; struct epicsShareClass TestPV { POINTER_DEFINITIONS(TestPV); std::tr1::weak_ptr weakself; const std::string name; std::tr1::weak_ptr const provider; epics::pvData::PVDataCreatePtr factory; const epics::pvData::StructureConstPtr dtype; epics::pvData::PVStructurePtr value; TestPV(const std::string& name, const std::tr1::shared_ptr& provider, const epics::pvData::StructureConstPtr& dtype); ~TestPV(); void post(bool notify = true); void post(const epics::pvData::BitSet& changed, bool notify = true); void disconnect(); mutable epicsMutex lock; typedef weak_set channels_t; channels_t channels; friend struct TestProvider; }; struct epicsShareClass TestProvider : public epics::pvAccess::ChannelProvider, std::tr1::enable_shared_from_this { POINTER_DEFINITIONS(TestProvider); virtual std::string getProviderName() { return "TestProvider"; } virtual void destroy(); virtual epics::pvAccess::ChannelFind::shared_pointer channelFind(std::string const & channelName, epics::pvAccess::ChannelFindRequester::shared_pointer const & channelFindRequester); virtual epics::pvAccess::ChannelFind::shared_pointer channelList(epics::pvAccess::ChannelListRequester::shared_pointer const & channelListRequester); virtual epics::pvAccess::Channel::shared_pointer createChannel(std::string const & channelName,epics::pvAccess::ChannelRequester::shared_pointer const & channelRequester, short priority = PRIORITY_DEFAULT); virtual epics::pvAccess::Channel::shared_pointer createChannel(std::string const & channelName, epics::pvAccess::ChannelRequester::shared_pointer const & channelRequester, short priority, std::string const & address); TestProvider(); virtual ~TestProvider(); TestPV::shared_pointer addPV(const std::string& name, const epics::pvData::StructureConstPtr& tdef); void dispatch(); mutable epicsMutex lock; typedef weak_value_map pvs_t; pvs_t pvs; static void testCounts(); }; struct epicsShareClass TestIOC { bool hasInit; TestIOC() : hasInit(false) { testdbPrepare(); } ~TestIOC() { this->shutdown(); testdbCleanup(); } void init() { if(!hasInit) { eltc(0); testIocInitOk(); eltc(1); hasInit = true; } } void shutdown() { if(hasInit) { testIocShutdownOk(); hasInit = false; } } }; #endif // UTILITIES_H