3 #include <epicsAtomic.h>
6 #include <epicsMutex.h>
7 #include <epicsTimer.h>
9 #include <pv/epicsException.h>
10 #include <pv/serverContext.h>
11 #include <pv/pvAccess.h>
13 #define epicsExportSharedSymbols
16 #include "chancache.h"
19 namespace pvd = epics::pvData;
20 namespace pva = epics::pvAccess;
22 size_t ChannelCacheEntry::num_instances;
24 ChannelCacheEntry::ChannelCacheEntry(
ChannelCache* c,
const std::string& n)
25 :channelName(n), cache(c), dropPoke(true)
27 epicsAtomicIncrSizeT(&num_instances);
30 ChannelCacheEntry::~ChannelCacheEntry()
35 epicsAtomicDecrSizeT(&num_instances);
39 ChannelCacheEntry::CRequester::getRequesterName()
44 size_t ChannelCacheEntry::CRequester::num_instances;
46 ChannelCacheEntry::CRequester::CRequester(
const ChannelCacheEntry::shared_pointer& p)
49 epicsAtomicIncrSizeT(&num_instances);
52 ChannelCacheEntry::CRequester::~CRequester()
54 epicsAtomicDecrSizeT(&num_instances);
59 ChannelCacheEntry::CRequester::channelCreated(
const pvd::Status& status,
60 pva::Channel::shared_pointer
const & channel)
64 ChannelCacheEntry::CRequester::channelStateChange(pva::Channel::shared_pointer
const & channel,
65 pva::Channel::ConnectionState connectionState)
67 ChannelCacheEntry::shared_pointer chan(this->chan.lock());
72 Guard G(chan->cache->cacheLock);
74 assert(chan->channel.get()==channel.get());
76 switch(connectionState)
78 case pva::Channel::DISCONNECTED:
79 case pva::Channel::DESTROYED:
81 chan->cache->entries.erase(chan->channelName);
90 ChannelCacheEntry::interested_t::vector_type interested(chan->interested.lock_vector());
92 FOREACH(ChannelCacheEntry::interested_t::vector_type::const_iterator, it, end, interested)
95 pva::ChannelRequester::shared_pointer req(chan->requester.lock());
97 req->channelStateChange(*it, connectionState);
106 epicsTimerNotify::expireStatus expire(
const epicsTime ¤tTime)
110 std::set<ChannelCacheEntry::shared_pointer> cleaned;
113 Guard G(cache->cacheLock);
114 cache->cleanerRuns++;
116 ChannelCache::entries_t::iterator cur=cache->entries.begin(), next, end=cache->entries.end();
121 if(!cur->second->dropPoke && cur->second->interested.empty()) {
122 cleaned.insert(cur->second);
123 cache->entries.erase(cur);
124 cache->cleanerDust++;
126 cur->second->dropPoke =
false;
132 return epicsTimerNotify::expireStatus(epicsTimerNotify::restart, 30.0);
136 ChannelCache::ChannelCache(
const pva::ChannelProvider::shared_pointer& prov)
138 ,timerQueue(&epicsTimerQueueActive::allocate(1, epicsThreadPriorityCAServerLow-2))
144 throw std::logic_error(
"Missing 'pva' provider");
146 cleanTimer = &timerQueue->createTimer();
147 cleanTimer->start(*cleaner, 30.0);
150 ChannelCache::~ChannelCache()
156 cleanTimer->destroy();
157 timerQueue->release();
165 ChannelCacheEntry::shared_pointer
166 ChannelCache::lookup(
const std::string& newName)
168 ChannelCacheEntry::shared_pointer ret;
172 entries_t::const_iterator it = entries.find(newName);
174 if(it==entries.end()) {
181 entries[newName] = ent;
183 pva::Channel::shared_pointer M;
186 epicsGuardRelease<epicsMutex> U(G);
188 M = provider->createChannel(newName, ent->requester);
190 THROW_EXCEPTION2(std::runtime_error,
"Failed to createChannel");
197 }
else if(it->second->channel && it->second->channel->isConnected()) {
201 it->second->dropPoke =
true;
205 it->second->dropPoke =
true;