client: (shallow) copy into Monitor::root

Avoid exposing refs. from monitor queue
which might then be used after release().
Also allows users the possibility of caching
getSubField() until root.get() actually changes.
This commit is contained in:
Michael Davidsaver
2018-02-21 11:19:21 -08:00
parent 79ada524fa
commit b5bf6a4ccd
2 changed files with 35 additions and 4 deletions

View File

@@ -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<pvd::PVStructure&>(*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