less locking during monitor setup

This commit is contained in:
Michael Davidsaver
2015-12-08 18:10:06 -05:00
parent 5e9ed37613
commit 3223c5da19
2 changed files with 26 additions and 16 deletions

View File

@ -157,6 +157,7 @@ GWChannel::createMonitor(
pvd::StructureConstPtr typedesc;
try {
bool create = false;
{
Guard G(entry->cache->cacheLock);
@ -165,14 +166,11 @@ GWChannel::createMonitor(
ment.reset(new MonitorCacheEntry(entry.get()));
entry->mon_entries[ser] = ment; // ref. wrapped
ment->weakref = ment;
// Create upstream monitor
// This would create a strong ref. loop between ent and ent->mon.
// Instead we get clever and pass a "fake" strong ref.
// and ensure that ~MonitorCacheEntry destroy()s the client Monitor
MonitorCacheEntry::shared_pointer fakereal(ment.get(), noclean());
ment->mon = entry->channel->createMonitor(fakereal, pvRequest);
create = true;
// We've added an incomplete entry (no Monitor)
// so MonitorUser must check validity before de-ref.
// in this case we use !!typedesc as this also indicates
// that the upstream monitor is connected
std::cout<<"Monitor cache "<<entry->channelName<<" Miss\n";
} else {
@ -180,8 +178,24 @@ GWChannel::createMonitor(
}
}
pvd::MonitorPtr M;
if(create) {
// Note: no lock held
// Create upstream monitor
// This would create a strong ref. loop between ent and ent->mon.
// Instead we get clever and pass a "fake" strong ref.
// and ensure that ~MonitorCacheEntry destroy()s the client Monitor
MonitorCacheEntry::shared_pointer fakereal(ment.get(), noclean());
M = entry->channel->createMonitor(fakereal, pvRequest);
}
Guard G(ment->mutex());
if(create)
ment->mon = M;
mon.reset(new MonitorUser(ment));
ment->interested.insert(mon);
mon->weakref = mon;
@ -194,18 +208,14 @@ GWChannel::createMonitor(
mon.reset();
std::cerr<<"Exception in "<<__PRETTY_FUNCTION__<<"\n"
"is "<<e.what()<<"\n";
pvd::Status oops(pvd::Status::STATUSTYPE_FATAL, "Error during GWChannel setup");
startresult = oops;
monitorRequester->monitorConnect(oops, mon, typedesc);
return mon;
startresult = pvd::Status(pvd::Status::STATUSTYPE_FATAL, "Error during GWChannel setup");
}
// unlock for callback
if(typedesc || !startresult.isSuccess()) {
// upstream monitor already connected, or never will be,
// so connect immeidately
monitorRequester->monitorConnect(pvd::Status::Ok, mon, typedesc);
// upstream monitor already connected, or never will be.
monitorRequester->monitorConnect(startresult, mon, typedesc);
}
return mon;

View File

@ -109,7 +109,7 @@ MonitorCacheEntry::monitorEvent(pvd::MonitorPtr const & monitor)
bool notify = false;
{
Guard G(usr->queueLock); // TODO: more granular lock
Guard G(usr->queueLock);
if(!usr->running || usr->empty.empty()) {
epicsAtomicIncrSizeT(&usr->ndropped);
continue;