From 527cb3fe62481c6bd153fc3f3ba599daa99dad0e Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Wed, 18 Jul 2018 10:50:08 -0700 Subject: [PATCH] MonitorFIFO use PVRequestMapper MonitorFIFO add config option dropEmptyUpdates really distinct from ignoreRequestMask --- src/client/monitor.cpp | 63 ++++++++++++++++------------------------- src/client/pv/monitor.h | 9 +++--- 2 files changed, 30 insertions(+), 42 deletions(-) diff --git a/src/client/monitor.cpp b/src/client/monitor.cpp index 1514955..eaa8784 100644 --- a/src/client/monitor.cpp +++ b/src/client/monitor.cpp @@ -26,7 +26,8 @@ MonitorFIFO::Config::Config() :maxCount(4) ,defCount(4) ,actualCount(0) // readback - ,ignoreRequestMask(false) + ,dropEmptyUpdates(true) + ,mapperMode(pvd::PVRequestMapper::Mask) {} size_t MonitorFIFO::num_instances; @@ -129,7 +130,7 @@ void MonitorFIFO::setFreeHighMark(double level) void MonitorFIFO::open(const pvd::StructureConstPtr& type) { - bool emptyselect; + std::string message; { Guard G(mutex); @@ -148,34 +149,27 @@ void MonitorFIFO::open(const pvd::StructureConstPtr& type) // fill up empty. pvd::PVDataCreatePtr create(pvd::getPVDataCreate()); + + mapper.compute(*create->createPVStructure(type), *pvRequest, conf.mapperMode); + message = mapper.warnings(); + while(empty.size() < conf.actualCount+1) { - MonitorElementPtr elem(new MonitorElement(create->createPVStructure(type))); + MonitorElementPtr elem(new MonitorElement(mapper.buildRequested())); empty.push_back(elem); } opened = true; needConnected = true; - this->type = type; - - if(conf.ignoreRequestMask) { - selectMask.clear(); - for(size_t i=0, N=empty.back()->pvStructurePtr->getNextFieldOffset(); ipvStructurePtr, - pvRequest->getSubField("field")); - } - emptyselect = selectMask.isEmpty(); assert(inuse.empty()); assert(empty.size()>=2); assert(returned.empty()); assert(conf.actualCount>=1); } - if(!emptyselect) return; + if(message.empty()) return; requester_type::shared_pointer req(requester.lock()); if(req) { - req->message("pvRequest with empty field mask", warningMessage); + req->message(message, warningMessage); } } @@ -187,8 +181,6 @@ void MonitorFIFO::close() opened = false; needClosed = true; - selectMask.clear(); - type.reset(); } void MonitorFIFO::finish() @@ -214,14 +206,10 @@ bool MonitorFIFO::tryPost(const pvData::PVStructure& value, assert(opened && !finished); assert(!empty.empty() || !inuse.empty()); - // compute effective changed mask for this subscription - scratch = changed; - scratch &= selectMask; - const bool havefree = _freeCount()>0u; MonitorElementPtr elem; - if(!conf.ignoreRequestMask && scratch.isEmpty()) { + if(conf.dropEmptyUpdates && !changed.logical_and(mapper.requestedMask())) { // drop empty update } else if(havefree) { // take an empty element @@ -229,16 +217,16 @@ bool MonitorFIFO::tryPost(const pvData::PVStructure& value, empty.pop_front(); } else if(force) { // allocate an extra element - elem.reset(new MonitorElement(pvd::getPVDataCreate()->createPVStructure(type))); + elem.reset(new MonitorElement(mapper.buildRequested())); } if(elem) { try { - assert(value.getStructure() == elem->pvStructurePtr->getStructure()); - elem->pvStructurePtr->copyUnchecked(value, scratch); - *elem->changedBitSet = scratch; - *elem->overrunBitSet = overrun; - *elem->overrunBitSet &= selectMask; + elem->changedBitSet->clear(); + mapper.copyBaseToRequested(value, changed, + *elem->pvStructurePtr, *elem->changedBitSet); + elem->overrunBitSet->clear(); + mapper.maskBaseToRequested(overrun, *elem->overrunBitSet); if(inuse.empty() && running) needEvent = true; @@ -284,19 +272,16 @@ void MonitorFIFO::post(const pvData::PVStructure& value, elem = inuse.back(); } - scratch = changed; - scratch &= selectMask; - - if(!conf.ignoreRequestMask && scratch.isEmpty()) + if(conf.dropEmptyUpdates && !changed.logical_and(mapper.requestedMask())) return; // drop empty update - assert(value.getStructure() == elem->pvStructurePtr->getStructure()); - elem->pvStructurePtr->copyUnchecked(value, scratch); + scratch.clear(); + mapper.copyBaseToRequested(value, changed, *elem->pvStructurePtr, scratch); if(use_empty) { *elem->changedBitSet = scratch; - *elem->overrunBitSet = overrun; - *elem->overrunBitSet &= selectMask; + elem->overrunBitSet->clear(); + mapper.maskBaseToRequested(overrun, *elem->overrunBitSet); if(inuse.empty() && running) needEvent = true; @@ -311,7 +296,9 @@ void MonitorFIFO::post(const pvData::PVStructure& value, // squash elem->overrunBitSet->or_and(*elem->changedBitSet, scratch); *elem->changedBitSet |= scratch; - elem->overrunBitSet->or_and(overrun, selectMask); + oscratch.clear(); + mapper.maskBaseToRequested(overrun, oscratch); + elem->overrunBitSet->or_and(oscratch, scratch); // leave as inuse.back() } diff --git a/src/client/pv/monitor.h b/src/client/pv/monitor.h index 14df362..5a9ef2f 100644 --- a/src/client/pv/monitor.h +++ b/src/client/pv/monitor.h @@ -22,6 +22,7 @@ #include #include #include +#include #ifdef monitorEpicsExportSharedSymbols # define epicsExportSharedSymbols @@ -274,7 +275,8 @@ public: size_t maxCount, //!< upper limit on requested FIFO size defCount, //!< FIFO size when client makes no request actualCount; //!< filled in with actual FIFO size - bool ignoreRequestMask; + bool dropEmptyUpdates; //!< default true. Drop updates which don't include an field values. + epics::pvData::PVRequestMapper::mode_t mapperMode; //!< default Mask. @see epics::pvData::PVRequestMapper::mode_t Config(); }; @@ -377,8 +379,7 @@ private: bool opened; // open() vs. close() bool running; // start() vs. stop() bool finished; // finish() called - epics::pvData::BitSet selectMask, // set during open() - scratch; // using during post to avoid re-alloc + epics::pvData::BitSet scratch, oscratch; // using during post to avoid re-alloc bool needConnected; bool needEvent; @@ -388,7 +389,7 @@ private: size_t freeHighLevel; epicsInt32 flowCount; - epics::pvData::StructureConstPtr type; // NULL if not opened + epics::pvData::PVRequestMapper mapper; typedef std::list buffer_t; // we allocate one extra buffer element to hold data when post()