Files
pvAccess/pvAccessApp/pva/clientFactory.cpp
2013-11-20 16:14:42 +01:00

102 lines
2.8 KiB
C++

/**
* 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 <pv/lock.h>
#include <pv/logger.h>
#include <epicsSignal.h>
#define epicsExportSharedSymbols
#include <pv/clientFactory.h>
#include <pv/clientContextImpl.h>
using namespace epics::pvData;
using namespace epics::pvAccess;
// TODO global static variable (de/initialization order not guaranteed)
static Mutex mutex;
static ClientContextImpl::shared_pointer context;
class ChannelProviderFactoryImpl : public ChannelProviderFactory
{
public:
POINTER_DEFINITIONS(ChannelProviderFactoryImpl);
virtual epics::pvData::String getFactoryName()
{
return ClientContextImpl::PROVIDER_NAME;
}
virtual ChannelProvider::shared_pointer sharedInstance()
{
Lock guard(mutex);
if (!context.get())
{
try {
ClientContextImpl::shared_pointer lcontext = createClientContextImpl();
lcontext->initialize();
context = lcontext;
} catch (std::exception &e) {
LOG(logLevelError, "Unhandled exception caught at %s:%d: %s", __FILE__, __LINE__, e.what());
} catch (...) {
LOG(logLevelError, "Unhandled exception caught at %s:%d.", __FILE__, __LINE__);
}
}
return context->getProvider();
}
virtual ChannelProvider::shared_pointer newInstance()
{
Lock guard(mutex);
try {
ClientContextImpl::shared_pointer lcontext = createClientContextImpl();
lcontext->initialize();
return lcontext->getProvider();
} catch (std::exception &e) {
LOG(logLevelError, "Unhandled exception caught at %s:%d: %s", __FILE__, __LINE__, e.what());
return ChannelProvider::shared_pointer();
} catch (...) {
LOG(logLevelError, "Unhandled exception caught at %s:%d.", __FILE__, __LINE__);
return ChannelProvider::shared_pointer();
}
}
void destroySharedInstance()
{
Lock guard(mutex);
if (context.get())
{
context->dispose();
context.reset();
}
}
};
static ChannelProviderFactoryImpl::shared_pointer factory;
void ClientFactory::start()
{
epicsSignalInstallSigAlarmIgnore();
epicsSignalInstallSigPipeIgnore();
Lock guard(mutex);
if (!factory.get())
factory.reset(new ChannelProviderFactoryImpl());
registerChannelProviderFactory(factory);
}
void ClientFactory::stop()
{
Lock guard(mutex);
if (factory.get())
{
unregisterChannelProviderFactory(factory);
factory->destroySharedInstance();
}
}