From 7c2a093338b5167b2d315f1ddf1715d631d0ce46 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 25 May 2017 18:01:41 -0400 Subject: [PATCH] add ChannelBaseRequester::channelDisconnect() per-operation notification of channel disconnect/destroy. --- src/client/Makefile | 1 + src/client/pv/monitor.h | 61 +++++++-------------- src/client/pv/pvAccess.h | 75 ++++++++++++++++++++------ src/client/pvAccess.cpp | 2 +- src/remote/pv/remote.h | 2 +- src/remoteClient/clientContextImpl.cpp | 32 ++++++++--- 6 files changed, 109 insertions(+), 64 deletions(-) diff --git a/src/client/Makefile b/src/client/Makefile index a89c26d..358aae1 100644 --- a/src/client/Makefile +++ b/src/client/Makefile @@ -2,6 +2,7 @@ SRC_DIRS += $(PVACCESS_SRC)/client +INC += pv/monitor.h INC += pv/pvAccess.h LIBSRCS += pvAccess.cpp diff --git a/src/client/pv/monitor.h b/src/client/pv/monitor.h index 54ac1d1..39b16dd 100644 --- a/src/client/pv/monitor.h +++ b/src/client/pv/monitor.h @@ -18,7 +18,7 @@ #include -namespace epics { namespace pvData { +namespace epics { namespace pvAccess { class MonitorElement; typedef std::tr1::shared_ptr MonitorElementPtr; @@ -38,14 +38,14 @@ class epicsShareClass MonitorElement { public: POINTER_DEFINITIONS(MonitorElement); MonitorElement(){} - MonitorElement(PVStructurePtr const & pvStructurePtr) + MonitorElement(epics::pvData::PVStructurePtr const & pvStructurePtr) : pvStructurePtr(pvStructurePtr), - changedBitSet(BitSet::create(static_cast(pvStructurePtr->getNumberFields()))), - overrunBitSet(BitSet::create(static_cast(pvStructurePtr->getNumberFields()))) + changedBitSet(epics::pvData::BitSet::create(static_cast(pvStructurePtr->getNumberFields()))), + overrunBitSet(epics::pvData::BitSet::create(static_cast(pvStructurePtr->getNumberFields()))) {} - PVStructurePtr pvStructurePtr; - BitSet::shared_pointer changedBitSet; - BitSet::shared_pointer overrunBitSet; + epics::pvData::PVStructurePtr pvStructurePtr; + epics::pvData::BitSet::shared_pointer changedBitSet; + epics::pvData::BitSet::shared_pointer overrunBitSet; }; /** @@ -54,7 +54,7 @@ class epicsShareClass MonitorElement { * This is used by pvAccess to implement monitors. * @author mrk */ -class epicsShareClass Monitor : public Destroyable{ +class epicsShareClass Monitor : public epics::pvData::Destroyable{ public: POINTER_DEFINITIONS(Monitor); virtual ~Monitor(){} @@ -62,12 +62,12 @@ class epicsShareClass Monitor : public Destroyable{ * Start monitoring. * @return completion status. */ - virtual Status start() = 0; + virtual epics::pvData::Status start() = 0; /** * Stop Monitoring. * @return completion status. */ - virtual Status stop() = 0; + virtual epics::pvData::Status stop() = 0; /** * If monitor has occurred return data. * @return monitorElement for modified data. @@ -93,36 +93,15 @@ class epicsShareClass Monitor : public Destroyable{ }; -/** - * @brief Callback implemented by monitor clients. - * - * Requester for ChannelMonitor. - * @author mrk - */ -class epicsShareClass MonitorRequester : public virtual Requester { - public: - POINTER_DEFINITIONS(MonitorRequester); - virtual ~MonitorRequester(){} - /** - * The client and server have both completed the createMonitor request. - * @param status Completion status. - * @param monitor The monitor - * @param structure The structure defining the data. - */ - virtual void monitorConnect(Status const & status, - MonitorPtr const & monitor, StructureConstPtr const & structure) = 0; - /** - * A monitor event has occurred. - * The requester must call Monitor.poll to get data. - * @param monitor The monitor. - */ - virtual void monitorEvent(MonitorPtr const & monitor) = 0; - /** - * The data source is no longer available. - * @param monitor The monitor. - */ - virtual void unlisten(MonitorPtr const & monitor) = 0; -}; - }} + +namespace epics { namespace pvData { + +using epics::pvAccess::MonitorElement; +using epics::pvAccess::MonitorElementPtr; +using epics::pvAccess::MonitorElementPtrArray; +using epics::pvAccess::Monitor; +using epics::pvAccess::MonitorPtr; +}} + #endif /* MONITOR_H */ diff --git a/src/client/pv/pvAccess.h b/src/client/pv/pvAccess.h index 088ebc6..e208845 100644 --- a/src/client/pv/pvAccess.h +++ b/src/client/pv/pvAccess.h @@ -39,12 +39,6 @@ using epics::pvData::RequesterPtr; using epics::pvData::MessageType; using epics::pvData::getMessageTypeName; -using epics::pvData::MonitorElement; -using epics::pvData::MonitorElementPtr; -using epics::pvData::MonitorElementPtrArray; -using epics::pvData::Monitor; -using epics::pvData::MonitorRequester; - // TODO add write-only? // change names enum AccessRights { @@ -116,7 +110,6 @@ private: bool locked; }; - class Channel; class ChannelProvider; class ChannelArrayRequester; @@ -127,8 +120,23 @@ class ChannelPutRequester; class ChannelPutGetRequester; class ChannelRPCRequester; +struct epicsShareClass ChannelBaseRequester : virtual public epics::pvData::Requester +{ + POINTER_DEFINITIONS(ChannelBaseRequester); + + virtual ~ChannelBaseRequester() {} + + /** Notification when underlying Channel becomes DISCONNECTED or DESTORYED + * + * (re)connection is notified through a sub-class *Connect() method. + * + * @param destroy true for final disconnect (shutdown). + */ + virtual void channelDisconnect(bool destroy) {} +}; + /** - * Base interface for all channel requests. + * Base interface for all channel requests (aka. Operations). */ class epicsShareClass ChannelRequest : public epics::pvData::Destroyable, public Lockable, private epics::pvData::NoDefaultMethods { public: @@ -159,6 +167,37 @@ public: virtual void lastRequest() = 0; }; +/** + * @brief Callback implemented by monitor clients. + * + * Requester for ChannelMonitor. + * @author mrk + */ +class epicsShareClass MonitorRequester : public ChannelBaseRequester { + public: + POINTER_DEFINITIONS(MonitorRequester); + virtual ~MonitorRequester(){} + /** + * The client and server have both completed the createMonitor request. + * @param status Completion status. + * @param monitor The monitor + * @param structure The structure defining the data. + */ + virtual void monitorConnect(epics::pvData::Status const & status, + MonitorPtr const & monitor, epics::pvData::StructureConstPtr const & structure) = 0; + /** + * A monitor event has occurred. + * The requester must call Monitor.poll to get data. + * @param monitor The monitor. + */ + virtual void monitorEvent(MonitorPtr const & monitor) = 0; + /** + * The data source is no longer available. + * @param monitor The monitor. + */ + virtual void unlisten(MonitorPtr const & monitor) = 0; +}; + /** * Request to put and get Array Data. * The data is either taken from or put in the PVArray returned by ChannelArrayRequester.channelArrayConnect. @@ -204,7 +243,7 @@ public: /** * The Requester for a ChannelArray. */ -class epicsShareClass ChannelArrayRequester : virtual public Requester { +class epicsShareClass ChannelArrayRequester : public ChannelBaseRequester { public: POINTER_DEFINITIONS(ChannelArrayRequester); typedef ChannelArray operation_type; @@ -338,7 +377,7 @@ public: /** * Requester for channelGet. */ -class epicsShareClass ChannelGetRequester : virtual public Requester { +class epicsShareClass ChannelGetRequester : public ChannelBaseRequester { public: POINTER_DEFINITIONS(ChannelGetRequester); typedef ChannelGet operation_type; @@ -392,7 +431,7 @@ public: /** * Requester for channelProcess. */ -class epicsShareClass ChannelProcessRequester : virtual public Requester { +class epicsShareClass ChannelProcessRequester : public ChannelBaseRequester { public: POINTER_DEFINITIONS(ChannelProcessRequester); typedef ChannelProcess operation_type; @@ -450,7 +489,7 @@ public: /** * Requester for ChannelPut. */ -class epicsShareClass ChannelPutRequester : virtual public Requester { +class epicsShareClass ChannelPutRequester : public ChannelBaseRequester { public: POINTER_DEFINITIONS(ChannelPutRequester); typedef ChannelPut operation_type; @@ -530,7 +569,7 @@ public: /** * Requester for ChannelPutGet. */ -class epicsShareClass ChannelPutGetRequester : virtual public Requester +class epicsShareClass ChannelPutGetRequester : public ChannelBaseRequester { public: POINTER_DEFINITIONS(ChannelPutGetRequester); @@ -625,7 +664,7 @@ public: * * No locks may be held while calling these methods. */ -class epicsShareClass ChannelRPCRequester : virtual public Requester { +class epicsShareClass ChannelRPCRequester : public ChannelBaseRequester { public: POINTER_DEFINITIONS(ChannelRPCRequester); typedef ChannelRPC operation_type; @@ -665,7 +704,7 @@ public: /** * Completion notification for Channel::getField() */ -class epicsShareClass GetFieldRequester : virtual public Requester { +class epicsShareClass GetFieldRequester : public ChannelBaseRequester { public: POINTER_DEFINITIONS(GetFieldRequester); @@ -1249,6 +1288,12 @@ public: } } +// compatibility +namespace epics { namespace pvData { +using epics::pvAccess::MonitorRequester; +}} + + #endif /* PVACCESS_H */ /** @page Overview Documentation diff --git a/src/client/pvAccess.cpp b/src/client/pvAccess.cpp index c932f9f..b51e839 100644 --- a/src/client/pvAccess.cpp +++ b/src/client/pvAccess.cpp @@ -81,7 +81,7 @@ ChannelRPC::shared_pointer Channel::createChannelRPC( } pvd::Monitor::shared_pointer Channel::createMonitor( - epics::pvData::MonitorRequester::shared_pointer const & requester, + epics::pvAccess::MonitorRequester::shared_pointer const & requester, epics::pvData::PVStructure::shared_pointer const & pvRequest) { pvd::Monitor::shared_pointer ret; diff --git a/src/remote/pv/remote.h b/src/remote/pv/remote.h index 94dd1fa..1b66f2b 100644 --- a/src/remote/pv/remote.h +++ b/src/remote/pv/remote.h @@ -572,7 +572,7 @@ public: * Get request requester. * @return request requester. */ - virtual std::tr1::shared_ptr getRequester() = 0; + virtual std::tr1::shared_ptr getRequester() = 0; }; /** diff --git a/src/remoteClient/clientContextImpl.cpp b/src/remoteClient/clientContextImpl.cpp index 5e5661a..1542067 100644 --- a/src/remoteClient/clientContextImpl.cpp +++ b/src/remoteClient/clientContextImpl.cpp @@ -145,7 +145,7 @@ protected: ChannelImpl::shared_pointer m_channel; - Requester::shared_pointer m_requester; + ChannelBaseRequester::shared_pointer m_requester; /* negative... */ static const int NULL_REQUEST = -1; @@ -170,7 +170,7 @@ protected: virtual ~BaseRequestImpl() {}; - BaseRequestImpl(ChannelImpl::shared_pointer const & channel, Requester::shared_pointer const & requester) : + BaseRequestImpl(ChannelImpl::shared_pointer const & channel, ChannelBaseRequester::shared_pointer const & requester) : m_channel(channel), m_requester(requester), m_ioid(INVALID_IOID), @@ -213,7 +213,7 @@ protected: public: // used to send message to this request - Requester::shared_pointer getRequester() { + ChannelBaseRequester::shared_pointer getRequester() { return m_requester; } @@ -1969,7 +1969,7 @@ public: PVACCESS_REFCOUNT_MONITOR_DESTRUCT(channelGetField); } - Requester::shared_pointer getRequester() { + ChannelBaseRequester::shared_pointer getRequester() { return m_callback; } @@ -4043,10 +4043,11 @@ private: void reportChannelStateChange() { - Channel::shared_pointer thisPointer = shared_from_this(); + Channel::shared_pointer self(shared_from_this()); while (true) { + std::vector ops; ConnectionState connectionState; { Lock guard(m_channelMutex); @@ -4054,9 +4055,28 @@ private: break; connectionState = channelStateChangeQueue.front(); channelStateChangeQueue.pop(); + + if(connectionState==Channel::DISCONNECTED || connectionState==Channel::DESTROYED) { + Lock guard(m_responseRequestsMutex); + ops.reserve(m_responseRequests.size()); + for(IOIDResponseRequestMap::const_iterator it = m_responseRequests.begin(), + end = m_responseRequests.end(); + it!=end; ++it) + { + ops.push_back(it->second); + } + } } - EXCEPTION_GUARD(m_requester->channelStateChange(thisPointer, connectionState)); + EXCEPTION_GUARD(m_requester->channelStateChange(self, connectionState)); + + if(connectionState==Channel::DISCONNECTED || connectionState==Channel::DESTROYED) { + for(size_t i=0, N=ops.size(); igetRequester()->channelDisconnect(connectionState==Channel::DESTROYED);) + } + } }