This commit is contained in:
mrkraimer
2017-12-23 06:35:23 -05:00
parent c4fe7150c9
commit d3ce104c33
4 changed files with 94 additions and 23 deletions

View File

@@ -374,7 +374,8 @@ CAChannel::CAChannel(std::string const & _channelName,
channelRequester(_channelRequester),
channelID(0),
channelType(0),
elementCount(0)
elementCount(0),
channelCreated(false)
{
if(DEBUG_LEVEL>0) {
cout<< "CAChannel::CAChannel " << channelName << endl;
@@ -395,6 +396,9 @@ void CAChannel::activate(short priority)
&channelID);
if (result == ECA_NORMAL)
{
channelCreated = true;
CAChannelProviderPtr provider(channelProvider.lock());
if(provider) provider->addChannel(shared_from_this());
req->channelCreated(Status::Ok, shared_from_this());
} else {
Status errorStatus(Status::STATUSTYPE_ERROR, string(ca_message(result)));
@@ -402,6 +406,36 @@ void CAChannel::activate(short priority)
}
}
CAChannel::~CAChannel()
{
if(DEBUG_LEVEL>0) {
cout << "CAChannel::~CAChannel() " << channelName << endl;
}
disconnectChannel();
}
void CAChannel::disconnectChannel()
{
if(DEBUG_LEVEL>0) {
cout << "CAChannel::disconnectChannel() "
<< channelName
<< " channelCreated " << (channelCreated ? "true" : "false")
<< endl;
}
bool disconnect = true;
{
Lock lock(requestsMutex);
if(!channelCreated) disconnect = false;
channelCreated = false;
}
if(!disconnect) return;
/* Clear CA Channel */
threadAttach();
ca_clear_channel(channelID);
}
void CAChannel::addChannelGet(const CAChannelGetPtr & get)
{
if(DEBUG_LEVEL>0) {
@@ -448,17 +482,6 @@ void CAChannel::addChannelMonitor(const CAChannelMonitorPtr & monitor)
monitorList.push_back(monitor);
}
CAChannel::~CAChannel()
{
if(DEBUG_LEVEL>0) {
cout << "CAChannel::~CAChannel() " << channelName << endl;
}
/* Clear CA Channel */
threadAttach();
ca_clear_channel(channelID);
}
chid CAChannel::getChannelID()
{
return channelID;

View File

@@ -22,8 +22,7 @@ namespace epics {
namespace pvAccess {
namespace ca {
class CAChannel;
typedef std::tr1::shared_ptr<CAChannel> CAChannelPtr;
class CAChannelGetField;
typedef std::tr1::shared_ptr<CAChannelGetField> CAChannelGetFieldPtr;
typedef std::tr1::weak_ptr<CAChannelGetField> CAChannelGetFieldWPtr;
@@ -60,7 +59,7 @@ public:
static size_t num_instances;
static shared_pointer create(CAChannelProvider::shared_pointer const & channelProvider,
static CAChannelPtr create(CAChannelProvider::shared_pointer const & channelProvider,
std::string const & channelName,
short priority,
ChannelRequester::shared_pointer const & channelRequester);
@@ -112,6 +111,7 @@ public:
void addChannelGet(const CAChannelGetPtr & get);
void addChannelPut(const CAChannelPutPtr & get);
void addChannelMonitor(const CAChannelMonitorPtr & get);
void disconnectChannel();
private:
@@ -129,6 +129,7 @@ private:
chid channelID;
chtype channelType;
unsigned elementCount;
bool channelCreated;
epics::pvData::Structure::const_shared_pointer structure;
epics::pvData::Mutex requestsMutex;

View File

@@ -52,7 +52,28 @@ CAChannelProvider::CAChannelProvider(const std::tr1::shared_ptr<Configuration>&)
CAChannelProvider::~CAChannelProvider()
{
if(DEBUG_LEVEL>0) std::cout << "CAChannelProvider::~CAChannelProvider()\n";
if(DEBUG_LEVEL>0) {
std::cout << "CAChannelProvider::~CAChannelProvider()"
<< " caChannelList.size() " << caChannelList.size()
<< std::endl;
}
std::queue<CAChannelPtr> channelQ;
{
Lock lock(channelListMutex);
for(size_t i=0; i< caChannelList.size(); ++i) {
CAChannelPtr caChannel(caChannelList[i].lock());
if(caChannel) channelQ.push(caChannel);
}
}
while(!channelQ.empty()) {
if(DEBUG_LEVEL>0) {
std::cout << "disconnectAllChannels calling disconnectChannel "
<< channelQ.front()->getChannelName()
<< std::endl;
}
channelQ.front()->disconnectChannel();
channelQ.pop();
}
}
std::string CAChannelProvider::getProviderName()
@@ -112,6 +133,23 @@ Channel::shared_pointer CAChannelProvider::createChannel(
return CAChannel::create(shared_from_this(), channelName, priority, channelRequester);
}
void CAChannelProvider::addChannel(const CAChannelPtr & channel)
{
if(DEBUG_LEVEL>0) {
std::cout << "CAChannelProvider::addChannel "
<< channel->getChannelName()
<< std::endl;
}
Lock lock(channelListMutex);
for(size_t i=0; i< caChannelList.size(); ++i) {
if(!(caChannelList[i].lock())) {
caChannelList[i] = channel;
return;
}
}
caChannelList.push_back(channel);
}
void CAChannelProvider::configure(epics::pvData::PVStructure::shared_pointer /*configuration*/)
{
}
@@ -136,13 +174,11 @@ void CAChannelProvider::initialize()
/* Create Channel Access */
int result = ca_context_create(ca_enable_preemptive_callback);
if (result != ECA_NORMAL) {
throw std::runtime_error(std::string("CA error %s occurred while trying "
"to start channel access:") + ca_message(result));
throw std::runtime_error(
std::string("CA error %s occurred while trying to start channel access:")
+ ca_message(result));
}
current_context = ca_current_context();
// TODO create a ca_poll thread, if ca_disable_preemptive_callback
}
@@ -154,7 +190,9 @@ void ca_factory_cleanup(void*)
ChannelProviderRegistry::clients()->remove("ca");
ca_context_destroy();
} catch(std::exception& e) {
LOG(logLevelWarn, "Error when unregister \"ca\" factory");
std::string message("Error when unregister \"ca\" factory");
message += e.what();
LOG(logLevelWarn,message.c_str());
}
}
@@ -173,7 +211,7 @@ void CAClientFactory::start()
registerRefCounter("CAChannelPut", &CAChannelPut::num_instances);
registerRefCounter("CAChannelMonitor", &CAChannelMonitor::num_instances);
if(ChannelProviderRegistry::clients()->add<CAChannelProvider>("ca", false))
if(ChannelProviderRegistry::clients()->add<CAChannelProvider>("ca", true))
{
epicsAtExit(&ca_factory_cleanup, NULL);
}

View File

@@ -19,6 +19,10 @@ namespace ca {
#define DEBUG_LEVEL 0
class CAChannel;
typedef std::tr1::shared_ptr<CAChannel> CAChannelPtr;
typedef std::tr1::weak_ptr<CAChannel> CAChannelWPtr;
class CAChannelProvider;
typedef std::tr1::shared_ptr<CAChannelProvider> CAChannelProviderPtr;
typedef std::tr1::weak_ptr<CAChannelProvider> CAChannelProviderWPtr;
@@ -64,13 +68,18 @@ public:
virtual void destroy() EPICS_DEPRECATED {};
void addChannel(const CAChannelPtr & get);
/* ---------------------------------------------------------------- */
void threadAttach();
private:
void initialize();
ca_client_context* current_context;
epics::pvData::Mutex channelListMutex;
std::vector<CAChannelWPtr> caChannelList;
};
}