lock for MonitorCacheEntry

This commit is contained in:
Michael Davidsaver
2015-12-08 17:29:46 -05:00
parent 247caaf161
commit 810377aa34
4 changed files with 38 additions and 28 deletions

View File

@ -24,10 +24,13 @@ struct MonitorCacheEntry : public epics::pvData::MonitorRequester
POINTER_DEFINITIONS(MonitorCacheEntry);
static size_t num_instances;
typedef std::vector<epicsUInt8> pvrequest_t;
pvrequest_t key;
ChannelCacheEntry * const chan;
// to avoid yet another mutex borrow interested.mutex() for our members
inline epicsMutex& mutex() const { return interested.mutex(); }
typedef std::vector<epicsUInt8> pvrequest_t;
bool done;
size_t nwakeups; // # of upstream monitorEvent() calls
size_t nevents; // # of upstream events poll()'d

View File

@ -150,41 +150,44 @@ GWChannel::createMonitor(
// serialize request struct to string using host byte order (only used for local comparison)
pvd::serializeToVector(pvRequest.get(), EPICS_BYTE_ORDER, ser);
MonitorCacheEntry::shared_pointer ent;
MonitorCacheEntry::shared_pointer ment;
MonitorUser::shared_pointer mon;
pvd::Status startresult;
pvd::StructureConstPtr typedesc;
try {
Guard G(entry->cache->cacheLock);
{
Guard G(entry->cache->cacheLock);
ent = entry->mon_entries.find(ser);
if(!ent) {
ent.reset(new MonitorCacheEntry(entry.get()));
entry->mon_entries[ser] = ent;
ment = entry->mon_entries.find(ser);
if(!ment) {
ment.reset(new MonitorCacheEntry(entry.get()));
entry->mon_entries[ser] = 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(ent.get(), noclean());
// 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());
ent->mon = entry->channel->createMonitor(fakereal, pvRequest);
ment->mon = entry->channel->createMonitor(fakereal, pvRequest);
ent->key.swap(ser); // no copy
std::cout<<"Monitor cache "<<entry->channelName<<" Miss\n";
} else {
std::cout<<"Monitor cache "<<entry->channelName<<" Hit\n";
std::cout<<"Monitor cache "<<entry->channelName<<" Miss\n";
} else {
std::cout<<"Monitor cache "<<entry->channelName<<" Hit\n";
}
}
mon.reset(new MonitorUser(ent));
ent->interested.insert(mon);
Guard G(ment->mutex());
mon.reset(new MonitorUser(ment));
ment->interested.insert(mon);
mon->weakref = mon;
mon->req = monitorRequester;
typedesc = ent->typedesc;
startresult = ent->startresult;
typedesc = ment->typedesc;
startresult = ment->startresult;
} catch(std::exception& e) {
mon.reset();

View File

@ -39,7 +39,7 @@ MonitorCacheEntry::monitorConnect(pvd::Status const & status,
interested_t::vector_type tonotify;
{
Guard G(chan->cache->cacheLock);
Guard G(mutex());
typedesc = structure;
if(status.isSuccess()) {
@ -56,6 +56,8 @@ MonitorCacheEntry::monitorConnect(pvd::Status const & status,
if(!startresult.isSuccess())
std::cout<<"upstream monitor start() fails\n";
//TODO: hold a shared_ptr to 'this' incase all MonitorUsers are destroy()d in a callback
for(interested_t::vector_type::const_iterator it = tonotify.begin(),
end = tonotify.end(); it!=end; ++it)
{
@ -90,6 +92,8 @@ MonitorCacheEntry::monitorEvent(pvd::MonitorPtr const & monitor)
pvd::MonitorElementPtr update;
//TODO: hold a shared_ptr to 'this' incase all MonitorUsers are destroy()d in a callback
while((update=monitor->poll()))
{
cntpoll++;
@ -179,7 +183,7 @@ void
MonitorUser::destroy()
{
{
Guard G(entry->chan->cache->cacheLock);
Guard G(queueLock);
running = false;
}
}
@ -195,7 +199,7 @@ MonitorUser::start()
pvd::PVStructurePtr lval;
pvd::StructureConstPtr typedesc;
{
Guard G(entry->chan->cache->cacheLock);
Guard G(entry->mutex());
if(!entry->startresult.isSuccess())
return entry->startresult;

View File

@ -343,7 +343,7 @@ void statusServer(int lvl, const char *chanexpr)
size_t nsrvmon;
bool hastype, hasdata, isdone;
{
Guard G(scp->cache.cacheLock);
Guard G(ME.mutex());
nsrvmon = ME.interested.size();
hastype = !!ME.typedesc;