Collect ca_client_context operations
Each instance of the caContext class represents a separate CA context, so each CAChannelProvider creates one and keeps a shared_ptr to it, making that available to its channels and channel operations. These also take their own shared_ptr to it as well so the context cannot be destroyed while it might be needed. A related caContext Attach object is intended to be short-lived, and to be allocated on the stack. When created it saves the current CA context for the thread, replacing it from the caContext given to its constructor. CA operations will now use the attached context. When the Attach destructor runs it detaches the thread from the current context (checking still has the expected value) and re-attaches the thread to any context that was saved by the constructor.
This commit is contained in:
committed by
mdavidsaver
parent
25dde0f4ba
commit
f9c40e96cf
65
src/ca/caContext.cpp
Normal file
65
src/ca/caContext.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvAccessCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#include <cadef.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "caContext.h"
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
namespace ca {
|
||||
|
||||
CAContext::CAContext()
|
||||
{
|
||||
int result = ca_context_create(ca_enable_preemptive_callback);
|
||||
if (result != ECA_NORMAL)
|
||||
throw std::runtime_error("Can't create CA context");
|
||||
|
||||
ca_context = ca_current_context();
|
||||
}
|
||||
|
||||
ca_client_context* CAContext::attach()
|
||||
{
|
||||
ca_client_context *thread_context = ca_current_context();
|
||||
if (thread_context != ca_context) {
|
||||
if (thread_context)
|
||||
ca_detach_context();
|
||||
|
||||
int result = ca_attach_context(ca_context);
|
||||
if (result != ECA_NORMAL)
|
||||
throw std::runtime_error("Can't attach to CA context");
|
||||
}
|
||||
return thread_context;
|
||||
}
|
||||
|
||||
void CAContext::detach(ca_client_context* restore) \
|
||||
{
|
||||
ca_client_context *thread_context = ca_current_context();
|
||||
if (thread_context != ca_context)
|
||||
std::cerr << "CA context was changed!" << std::endl;
|
||||
|
||||
ca_detach_context();
|
||||
|
||||
if (restore) {
|
||||
int result = ca_attach_context(restore);
|
||||
if (result != ECA_NORMAL)
|
||||
std::cerr << "Can't re-attach to CA context" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
CAContext::~CAContext()
|
||||
{
|
||||
ca_client_context *thread_context = attach();
|
||||
ca_context_destroy();
|
||||
if (thread_context != ca_context) {
|
||||
int result = ca_attach_context(ca_context);
|
||||
if (result != ECA_NORMAL)
|
||||
std::cerr << "Can't re-attach to CA context" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
}}}
|
||||
Reference in New Issue
Block a user