diff --git a/p2pApp/chancache.cpp b/p2pApp/chancache.cpp index 5a941a8..5d041ba 100644 --- a/p2pApp/chancache.cpp +++ b/p2pApp/chancache.cpp @@ -37,7 +37,18 @@ ChannelCacheEntry::CRequester::getRequesterName() return "GWClient"; } -ChannelCacheEntry::CRequester::~CRequester() {} +size_t ChannelCacheEntry::CRequester::num_instances; + +ChannelCacheEntry::CRequester::CRequester(const ChannelCacheEntry::shared_pointer& p) + :chan(p) +{ + epicsAtomicIncrSizeT(&num_instances); +} + +ChannelCacheEntry::CRequester::~CRequester() +{ + epicsAtomicDecrSizeT(&num_instances); +} void ChannelCacheEntry::CRequester::message(std::string const & message, pvd::MessageType messageType) @@ -142,9 +153,26 @@ ChannelCache::ChannelCache(const pva::ChannelProvider::shared_pointer& prov) ChannelCache::~ChannelCache() { + Guard G(cacheLock); + cleanTimer->destroy(); timerQueue->release(); delete cleaner; + + entries_t E; + E.swap(entries); + + FOREACH(it, end, E) + { + ChannelCacheEntry *ent = it->second.get(); + + if(ent->channel) { + epics::pvAccess::Channel::shared_pointer chan; + chan.swap(ent->channel); + UnGuard U(G); + chan->destroy(); + } + } } ChannelCacheEntry::shared_pointer diff --git a/p2pApp/chancache.h b/p2pApp/chancache.h index 0bbb5c6..e8c3c50 100644 --- a/p2pApp/chancache.h +++ b/p2pApp/chancache.h @@ -128,7 +128,9 @@ struct ChannelCacheEntry // ChannelCacheEntry -> pva::Channel -> CRequester struct CRequester : public epics::pvAccess::ChannelRequester { - CRequester(const ChannelCacheEntry::shared_pointer& p) : chan(p) {} + static size_t num_instances; + + CRequester(const ChannelCacheEntry::shared_pointer& p); virtual ~CRequester(); ChannelCacheEntry::weak_pointer chan; // for Requester diff --git a/p2pApp/channel.cpp b/p2pApp/channel.cpp index 50216e2..4e8e902 100644 --- a/p2pApp/channel.cpp +++ b/p2pApp/channel.cpp @@ -43,6 +43,11 @@ GWChannel::message(std::string const & message, pvd::MessageType messageType) void GWChannel::destroy() { + epics::pvAccess::ChannelRequester::shared_pointer req; + { + Guard G(entry->mutex()); + req.swap(requester); + } } std::tr1::shared_ptr diff --git a/p2pApp/channel.h b/p2pApp/channel.h index 04bfa6f..50e3b83 100644 --- a/p2pApp/channel.h +++ b/p2pApp/channel.h @@ -12,7 +12,7 @@ struct GWChannel : public epics::pvAccess::Channel weak_pointer weakref; const ChannelCacheEntry::shared_pointer entry; - const epics::pvAccess::ChannelRequester::shared_pointer requester; + epics::pvAccess::ChannelRequester::shared_pointer requester; const std::string address; // address of client on GW server side const epics::pvAccess::ChannelProvider::weak_pointer server_provder; diff --git a/p2pApp/moncache.cpp b/p2pApp/moncache.cpp index fe1e618..197f8a0 100644 --- a/p2pApp/moncache.cpp +++ b/p2pApp/moncache.cpp @@ -148,6 +148,8 @@ MonitorCacheEntry::monitorEvent(pvd::MonitorPtr const & monitor) continue; } // we only come out of overflow when downstream release()s an element to us + // empty.empty() does not imply inoverflow, + // however inoverflow does imply empty.empty() assert(!usr->inoverflow); if(usr->filled.empty()) diff --git a/testApp/testmon.cpp b/testApp/testmon.cpp index 0c73ab3..236ede5 100644 --- a/testApp/testmon.cpp +++ b/testApp/testmon.cpp @@ -176,10 +176,12 @@ MAIN(testmon) int ok = 1; size_t temp; #define TESTC(name) temp=epicsAtomicGetSizeT(&name::num_instances); ok &= temp==0; testDiag("num. live " #name " %u", (unsigned)temp) + TESTC(GWChannel); + TESTC(ChannelCacheEntry::CRequester); TESTC(ChannelCacheEntry); TESTC(MonitorCacheEntry); TESTC(MonitorUser); #undef TESTC - testOk(temp, "All instances free'd"); + testOk(ok, "All instances free'd"); return testDone(); }