caProvider: Convert caChannelList into a tsDLList

This should provide a significant performance boost when creating
many thousands of CA channels. The only time it is necessary to
traverse the list is in the CAChannelProvider's destructor; when
individual channels are added or destroyed they can insert or
remove themselves from the list without having to do a search.
This commit is contained in:
Andrew Johnson
2021-10-20 20:06:28 -05:00
parent 284de4fb6b
commit ace1a82c12
4 changed files with 26 additions and 33 deletions

View File

@ -132,7 +132,7 @@ void CAChannel::activate(short priority)
channelCreated = true;
CAChannelProviderPtr provider(channelProvider.lock());
if (provider)
provider->addChannel(shared_from_this());
provider->addChannel(*this);
EXCEPTION_GUARD(req->channelCreated(Status::Ok, shared_from_this()));
}
else {
@ -167,10 +167,14 @@ void CAChannel::disconnectChannel()
/* Clear CA Channel */
Attach to(ca_context);
int result = ca_clear_channel(channelID);
if (result == ECA_NORMAL) return;
string mess("CAChannel::disconnectChannel() ");
mess += ca_message(result);
cerr << mess << endl;
if (result != ECA_NORMAL) {
string mess("CAChannel::disconnectChannel() ");
mess += ca_message(result);
cerr << mess << endl;
}
CAChannelProviderPtr provider(channelProvider.lock());
if (provider)
provider->delChannel(*this);
}
chid CAChannel::getChannelID()

View File

@ -18,6 +18,7 @@
#include <epicsMutex.h>
#include <epicsEvent.h>
#include <cadef.h>
#include <tsDLList.h>
#include <pv/pvAccess.h>
@ -66,6 +67,7 @@ private:
class CAChannel :
public Channel,
public tsDLNode<CAChannel>,
public NotifierClient,
public std::tr1::enable_shared_from_this<CAChannel>
{

View File

@ -31,22 +31,9 @@ CAChannelProvider::CAChannelProvider(const std::tr1::shared_ptr<Configuration> &
CAChannelProvider::~CAChannelProvider()
{
std::queue<CAChannelPtr> channelQ;
{
std::vector<CAChannelWPtr>::iterator it;
epicsGuard<epicsMutex> G(channelListMutex);
for (it = caChannelList.begin(); it != caChannelList.end(); ++it)
{
CAChannelPtr caChannel(it->lock());
if (caChannel)
channelQ.push(caChannel);
}
caChannelList.clear();
}
while (!channelQ.empty())
{
channelQ.front()->disconnectChannel();
channelQ.pop();
epicsGuard<epicsMutex> G(channelListMutex);
while (CAChannel *ch = caChannelList.first()) {
ch->disconnectChannel(); // Removes itself from the list
}
}
@ -106,18 +93,16 @@ Channel::shared_pointer CAChannelProvider::createChannel(
return CAChannel::create(shared_from_this(), channelName, priority, channelRequester);
}
void CAChannelProvider::addChannel(const CAChannelPtr &channel)
void CAChannelProvider::addChannel(CAChannel &channel)
{
std::vector<CAChannelWPtr>::iterator it;
epicsGuard<epicsMutex> G(channelListMutex);
for (it = caChannelList.begin(); it != caChannelList.end(); ++it)
{
if (it->expired()) {
*it = channel;
return;
}
}
caChannelList.push_back(channel);
caChannelList.add(channel);
}
void CAChannelProvider::delChannel(CAChannel &channel)
{
epicsGuard<epicsMutex> G(channelListMutex);
caChannelList.remove(channel);
}
void CAChannelProvider::configure(epics::pvData::PVStructure::shared_pointer /*configuration*/)

View File

@ -14,6 +14,7 @@
#include <cadef.h>
#include <epicsMutex.h>
#include <tsDLList.h>
#include <pv/logger.h>
#include <pv/pvAccess.h>
@ -80,7 +81,8 @@ public:
virtual void flush();
virtual void poll();
void addChannel(const CAChannelPtr & channel);
void addChannel(CAChannel &channel);
void delChannel(CAChannel &channel);
CAContextPtr caContext() {
return ca_context;
@ -94,7 +96,7 @@ public:
private:
CAContextPtr ca_context;
epicsMutex channelListMutex;
std::vector<CAChannelWPtr> caChannelList;
tsDLList<CAChannel> caChannelList;
NotifierConveyor connectNotifier;
NotifierConveyor resultNotifier;