lock for MonitorCacheEntry
This commit is contained in:
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user