From fac07c7f3acba58d739813d0a1fd8d91dfca2df4 Mon Sep 17 00:00:00 2001 From: mrkraimer Date: Fri, 24 Jun 2016 15:03:19 -0400 Subject: [PATCH] added stateChangeRequester; improve semantics for unlisten and channelStateChange --- src/pv/pvaClient.h | 39 ++++++++++++++++++++++++++++++++++++++- src/pvaClientChannel.cpp | 13 ++++++++++++- src/pvaClientMonitor.cpp | 11 ++++++++++- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/pv/pvaClient.h b/src/pv/pvaClient.h index 1327462..bc668c6 100644 --- a/src/pv/pvaClient.h +++ b/src/pv/pvaClient.h @@ -53,6 +53,9 @@ class PvaClientPutData; typedef std::tr1::shared_ptr PvaClientPutDataPtr; class PvaClientMonitorData; typedef std::tr1::shared_ptr PvaClientMonitorDataPtr; +class PvaClientChannelStateChangeRequester; +typedef std::tr1::shared_ptr PvaClientChannelStateChangeRequesterPtr; +typedef std::tr1::weak_ptr PvaClientChannelStateChangeRequesterWPtr; class PvaClientChannel; typedef std::tr1::shared_ptr PvaClientChannelPtr; class PvaClientField; @@ -194,13 +197,35 @@ typedef std::tr1::shared_ptr PvaClientPutCachePtr; class ChannelRequesterImpl; typedef std::tr1::shared_ptr ChannelRequesterImplPtr; +/** + * @brief An easy to be notified of a change in connection status. + * + * @author mrk + */ +class epicsShareClass PvaClientChannelStateChangeRequester +{ +public: + POINTER_DEFINITIONS(PvaClientChannelStateChangeRequester); + /** + * Destructor + */ + virtual ~PvaClientChannelStateChangeRequester(){} + /** + * A channel connection state change has occurred. + * @param channel The channel. + * @param isConnected The new connection status. + */ + virtual void channelStateChange(PvaClientChannelPtr const & channel, bool isConnected) = 0; +}; + /** * @brief An easy to use alternative to directly calling the Channel methods of pvAccess. * * @author mrk */ -class epicsShareClass PvaClientChannel +class epicsShareClass PvaClientChannel : + public std::tr1::enable_shared_from_this { public: POINTER_DEFINITIONS(PvaClientChannel); @@ -208,6 +233,7 @@ public: * Destructor */ ~PvaClientChannel(); + void setStateChangeRequester(PvaClientChannelStateChangeRequesterPtr const &stateChangeRequester); /** Get the name of the channel to which PvaClientChannel is connected. * @return The channel name. */ @@ -421,9 +447,11 @@ private: epics::pvData::Mutex mutex; epics::pvData::Event waitForConnect; epics::pvAccess::Channel::shared_pointer channel; + PvaClientChannelStateChangeRequesterWPtr stateChangeRequester; ChannelRequesterImplPtr channelRequester; friend class PvaClient; friend class ChannelRequesterImpl; + }; /** @@ -1312,6 +1340,15 @@ public: * @param monitor The PvaClientMonitor that received the event. */ virtual void event(PvaClientMonitorPtr const & monitor) = 0; + /** + * The data source is no longer available. + */ + + virtual void unlisten() + { + std::cerr << "PvaClientMonitorRequester::unlisten called" + << " but no PvaClientMonitorRequester::unlisten\n"; + } }; diff --git a/src/pvaClientChannel.cpp b/src/pvaClientChannel.cpp index 52c032b..fb2c901 100644 --- a/src/pvaClientChannel.cpp +++ b/src/pvaClientChannel.cpp @@ -213,7 +213,6 @@ PvaClientChannel::~PvaClientChannel() if(PvaClient::getDebug()) showCache(); } - void PvaClientChannel::channelCreated(const Status& status, Channel::shared_pointer const & channel) { if(PvaClient::getDebug()) { @@ -252,6 +251,12 @@ void PvaClientChannel::channelStateChange( << " " << Channel::ConnectionStateNames[connectionState] << endl; } + PvaClientChannelStateChangeRequesterPtr req(stateChangeRequester.lock()); + if(req) { + bool value = (connectionState==Channel::CONNECTED ? true : false); + req->channelStateChange(shared_from_this(),value); + } + Lock xx(mutex); bool waitingForConnect = false; if(connectState==connectActive) waitingForConnect = true; @@ -293,6 +298,12 @@ Channel::shared_pointer PvaClientChannel::getChannel() return channel; } +void PvaClientChannel::setStateChangeRequester( + PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester) +{ + this->stateChangeRequester = stateChangeRequester; +} + void PvaClientChannel::connect(double timeout) { if(PvaClient::getDebug()) { diff --git a/src/pvaClientMonitor.cpp b/src/pvaClientMonitor.cpp index 6b58d5c..5c472f7 100644 --- a/src/pvaClientMonitor.cpp +++ b/src/pvaClientMonitor.cpp @@ -219,9 +219,18 @@ void PvaClientMonitor::monitorEvent(MonitorPtr const & monitor) void PvaClientMonitor::unlisten(MonitorPtr const & monitor) { if(PvaClient::getDebug()) cout << "PvaClientMonitor::unlisten\n"; - throw std::runtime_error("pvaClientMonitor::unlisten called but do not know what to do"); + PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock(); + if(req) { + req->unlisten(); + return; + } + string channelName("disconnected"); + Channel::shared_pointer chan(channel.lock()); + if(chan) channelName = chan->getChannelName(); + cerr << channelName + "pvaClientMonitor::unlisten called but no PvaClientMonitorRequester\n"; } + void PvaClientMonitor::connect() { if(PvaClient::getDebug()) cout << "PvaClientMonitor::connect\n";