diff --git a/src/client/clientMonitor.cpp b/src/client/clientMonitor.cpp index 2a7c321..8b7debd 100644 --- a/src/client/clientMonitor.cpp +++ b/src/client/clientMonitor.cpp @@ -196,16 +196,29 @@ bool Monitor::poll() Guard G(impl->mutex); if(!impl->done && impl->last.next()) { - root = impl->last->pvStructurePtr; + const epics::pvData::PVStructurePtr& ptr = impl->last->pvStructurePtr; changed = *impl->last->changedBitSet; overrun = *impl->last->overrunBitSet; + /* copy the exposed PVStructure for two reasons. + * 1. Prevent accidental use of shared container after release() + * 2. Allows caller to cache results of getSubField() until root.get() changes. + */ + if(!root || (void*)root->getField().get()!=(void*)ptr->getField().get()) { + // initial connection, or new type + root = pvd::getPVDataCreate()->createPVStructure(ptr); // also calls copyUnchecked() + } else { + // same type + const_cast(*root).copyUnchecked(*ptr, changed); + } + + impl->seenEmpty = false; } else { - root.reset(); changed.clear(); overrun.clear(); + impl->seenEmpty = true; } - return impl->seenEmpty = !!root; + return !impl->seenEmpty; } bool Monitor::complete() const diff --git a/src/client/pva/client.h b/src/client/pva/client.h index e9b6897..21f6b3a 100644 --- a/src/client/pva/client.h +++ b/src/client/pva/client.h @@ -104,13 +104,31 @@ struct epicsShareClass Monitor void cancel(); /** updates root, changed, overrun * - * @return true if root!=NULL + * @return true if a new update was extracted from the queue. + * @note This method does not block. * @note MonitorEvent::Data will not be repeated until poll()==false. + * @post root!=NULL (after version 6.0.0) + * @post root!=NULL iff poll()==true (In version 6.0.0) */ bool poll(); //! true if all events received. //! Check after poll()==false bool complete() const; + /** Monitor update data. + * + * After version 6.0.0 + * + * Initially NULL, becomes !NULL the first time poll()==true. + * The PVStructure pointed to be root will presist until + * Monitor reconnect w/ type change. This can be detected + * by comparing `root.get()`. references to root may be cached + * subject to this test. + * + * In version 6.0.0 + * + * NULL except after poll()==true. poll()==false sets root=NULL. + * references to root should not be stored between calls to poll(). + */ epics::pvData::PVStructure::const_shared_pointer root; epics::pvData::BitSet changed, overrun;