work on RAII and memory leaks

This commit is contained in:
mrkraimer
2016-06-01 10:10:00 -04:00
parent 1eea87efc7
commit e025e542ea
15 changed files with 701 additions and 287 deletions

View File

@ -13,6 +13,8 @@
int testExampleRecord(void);
int testPVCopy(void);
int testPVRecord(void);
int testLocalProvider(void);
int testPVAServer(void);
void pvDatabaseAllTests(void)
{
@ -22,5 +24,7 @@ void pvDatabaseAllTests(void)
runTest(testExampleRecord);
runTest(testPVCopy);
runTest(testPVRecord);
runTest(testLocalProvider);
runTest(testPVAServer);
}

View File

@ -18,4 +18,13 @@ testExampleRecord_SRCS += testExampleRecord.cpp
testHarness_SRCS += testExampleRecord.cpp
TESTS += testExampleRecord
TESTPROD_HOST += testLocalProvider
testLocalProvider_SRCS += testLocalProvider.cpp
testHarness_SRCS += testLocalProvider.cpp
TESTS += testLocalProvider
TESTPROD_HOST += testPVAServer
testPVAServer_SRCS += testPVAServer.cpp
testHarness_SRCS += testPVAServer.cpp
TESTS += testPVAServer

106
test/src/listener.h Normal file
View File

@ -0,0 +1,106 @@
/* listener.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
* @date 2013.04.02
*/
#ifndef LISTENER_H
#define LISTENER_H
#ifdef epicsExportSharedSymbols
# define listenerEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/timeStamp.h>
#include <pv/alarm.h>
#include <pv/pvTimeStamp.h>
#include <pv/pvAlarm.h>
#include <pv/pvDatabase.h>
#ifdef listenerEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef listenerEpicsExportSharedSymbols
#endif
#include <shareLib.h>
//epicsShareFunc epics::pvData::PVStructurePtr createListener();
namespace epics { namespace pvDatabase {
using namespace epics::pvData;
using namespace std;
class Listener;
typedef std::tr1::shared_ptr<Listener> ListenerPtr;
class Listener :
public PVListener,
public std::tr1::enable_shared_from_this<Listener>
{
public:
POINTER_DEFINITIONS(Listener);
static ListenerPtr create(
PVRecordPtr const & pvRecord)
{
ListenerPtr listener(new Listener(pvRecord));
pvRecord->addListener(listener,listener->pvCopy);
return listener;
}
virtual ~Listener(){}
virtual void detach(PVRecordPtr const & pvRecord)
{
}
virtual void dataPut(PVRecordFieldPtr const & pvRecordField)
{
cout << "Listener::dataPut record " << recordName
<< " pvRecordField " << pvRecordField->getPVField()->getFullName()
<< endl;
}
virtual void dataPut(
PVRecordStructurePtr const & requested,
PVRecordFieldPtr const & pvRecordField)
{
cout << "Listener::dataPut record " << recordName
<< " requested " << requested->getPVStructure()->getFullName()
<< " pvRecordField " << pvRecordField->getPVField()->getFullName()
<< endl;
}
virtual void beginGroupPut(PVRecordPtr const & pvRecord)
{
cout << "Listener::beginGroupPut record " << recordName << endl;
}
virtual void endGroupPut(PVRecordPtr const & pvRecord)
{
cout << "Listener::endGroupPut record " << recordName << endl;
}
virtual void unlisten(PVRecordPtr const & pvRecord)
{
cout << "Listener::unlisten record " << recordName << endl;
}
private:
Listener(PVRecordPtr const & pvRecord)
: pvCopy(
PVCopy::create(
getPVDataCreate()->createPVStructure(
pvRecord->getPVRecordStructure()->getPVStructure()),
CreateRequest::create()->createRequest(""),
pvRecord->getRecordName())),
pvStructure(pvCopy->createPVStructure()),
recordName(pvRecord->getRecordName())
{
}
PVCopyPtr pvCopy;
PVStructurePtr pvStructure;
string recordName;
};
}}
#endif /* LISTENER_H */

72
test/src/recordClient.h Normal file
View File

@ -0,0 +1,72 @@
/* recordClient.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
* @date 2013.04.02
*/
#ifndef RECORDCLIENT_H
#define RECORDCLIENT_H
#ifdef epicsExportSharedSymbols
# define pvRecordClientEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/timeStamp.h>
#include <pv/alarm.h>
#include <pv/pvTimeStamp.h>
#include <pv/pvAlarm.h>
#include <pv/pvDatabase.h>
#ifdef pvRecordClientEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef pvRecordClientEpicsExportSharedSymbols
#endif
#include <shareLib.h>
namespace epics { namespace pvDatabase {
class RecordClient;
typedef std::tr1::shared_ptr<RecordClient> RecordClientPtr;
class RecordClient :
public PVRecordClient,
public std::tr1::enable_shared_from_this<RecordClient>
{
public:
POINTER_DEFINITIONS(RecordClient);
static RecordClientPtr create(
PVRecordPtr const & pvRecord)
{
RecordClientPtr pvRecordClient(new RecordClient(pvRecord));
pvRecord->addPVRecordClient(pvRecordClient);
return pvRecordClient;
}
virtual ~RecordClient()
{
std::string recordName("pvRecord was destroyed");
if(pvRecord) recordName = pvRecord->getRecordName();
std::cout << "RecordClient::~RecordClient " << recordName << std::endl;
}
virtual void detach(PVRecordPtr const & pvRecord)
{
std::cout << "RecordClient::detach record " << pvRecord->getRecordName() << std::endl;
this->pvRecord.reset();
}
private:
RecordClient(PVRecordPtr const & pvRecord)
: pvRecord(pvRecord)
{}
PVRecordPtr pvRecord;
};
}}
#endif /* RECORDCLIENT_H */

View File

@ -32,6 +32,8 @@
#include <pv/pvAccess.h>
#define epicsExportSharedSymbols
#include "powerSupply.h"
#include "recordClient.h"
#include "listener.h"
#include <epicsExport.h>
@ -42,6 +44,7 @@ using namespace epics::pvAccess;
using namespace epics::pvDatabase;
static bool debug = false;
static int traceLevel = 0;
void test()
@ -55,26 +58,29 @@ void test()
recordName = "exampleDouble";
PVStructurePtr pvStructure;
pvStructure = standardPVField->scalar(scalarType,properties);
PVRecordPtr pvRecord = PVRecord::create(recordName,pvStructure);
PVRecordPtr exampleRecord = PVRecord::create(recordName,pvStructure);
exampleRecord->setTraceLevel(traceLevel);
RecordClientPtr exampleRecordClient(RecordClient::create(exampleRecord));
ListenerPtr exampleListener(Listener::create(exampleRecord));
{
pvRecord->lock();
pvRecord->process();
pvRecord->unlock();
exampleRecord->lock();
exampleRecord->process();
exampleRecord->unlock();
}
if(debug) {cout << "processed exampleDouble " << endl; }
pvRecord->destroy();
pvRecord.reset();
exampleRecord->destroy();
recordName = "powerSupplyExample";
pvStructure.reset();
PowerSupplyPtr psr;
pvStructure = createPowerSupply();
psr = PowerSupply::create("powerSupply",pvStructure);
psr->setTraceLevel(traceLevel);
RecordClientPtr psrRecordClient(RecordClient::create(psr));
ListenerPtr psrListener(Listener::create(psr));
testOk1(psr.get()!=0);
if(!psr) {
if(debug) {cout << "PowerSupplyRecordTest::create failed" << endl;}
return;
}
pvStructure.reset();
double voltage,power,current;
{
psr->lock();
@ -121,10 +127,7 @@ void test()
testOk1(psr->getVoltage()==1.0);
testOk1(psr->getPower()==1.0);
testOk1(psr->getCurrent()==1.0);
PVDatabasePtr pvDatabase = PVDatabase::getMaster();
pvDatabase->addRecord(psr);
psr.reset();
pvDatabase->destroy();
psr->destroy();
}
MAIN(testExampleRecord)

View File

@ -0,0 +1,82 @@
/*testExampleServerMain.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
/* Author: Marty Kraimer */
#include <epicsUnitTest.h>
#include <testMain.h>
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstdio>
#include <memory>
#include <iostream>
#include <epicsStdio.h>
#include <epicsMutex.h>
#include <epicsEvent.h>
#include <epicsThread.h>
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/pvData.h>
#include <pv/pvAccess.h>
#include <pv/channelProviderLocal.h>
#include <pv/serverContext.h>
#include "recordClient.h"
#include "listener.h"
using namespace std;
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvDatabase;
static bool debug = false;
void test()
{
PVDatabasePtr master = PVDatabase::getMaster();
testOk1(master.get()!=0);
ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();
testOk1(channelProvider.get()!=0);
StandardPVFieldPtr standardPVField = getStandardPVField();
string properties;
ScalarType scalarType;
string recordName;
properties = "alarm,timeStamp";
scalarType = pvDouble;
recordName = "exampleDouble";
PVStructurePtr pvStructure(standardPVField->scalar(scalarType,properties));
PVRecordPtr pvRecord(PVRecord::create(recordName,pvStructure));
RecordClientPtr exampleRecordClient(RecordClient::create(pvRecord));
ListenerPtr exampleListener(Listener::create(pvRecord));
master->addRecord(pvRecord);
pvRecord = master->findRecord("exampleDouble");
testOk1(pvRecord.get()!=0);
{
pvRecord->lock();
pvRecord->process();
pvRecord->unlock();
}
if(debug) {cout << "processed exampleDouble " << endl; }
channelProvider->destroy();
}
MAIN(testExampleServer)
{
testPlan(3);
test();
return 0;
}

View File

@ -0,0 +1,79 @@
/*testExampleServerMain.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
/* Author: Marty Kraimer */
#include <epicsUnitTest.h>
#include <testMain.h>
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstdio>
#include <memory>
#include <iostream>
#include <epicsStdio.h>
#include <epicsMutex.h>
#include <epicsEvent.h>
#include <epicsThread.h>
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/pvData.h>
#include <pv/pvAccess.h>
#include <pv/channelProviderLocal.h>
#include <pv/serverContext.h>
using namespace std;
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvDatabase;
static bool debug = false;
void test()
{
PVDatabasePtr master = PVDatabase::getMaster();
ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();
StandardPVFieldPtr standardPVField = getStandardPVField();
string properties;
ScalarType scalarType;
string recordName;
properties = "alarm,timeStamp";
scalarType = pvDouble;
recordName = "exampleDouble";
PVStructurePtr pvStructure;
pvStructure = standardPVField->scalar(scalarType,properties);
PVRecordPtr pvRecord = PVRecord::create(recordName,pvStructure);
master->addRecord(pvRecord);
pvRecord = master->findRecord("exampleDouble");
{
pvRecord->lock();
pvRecord->process();
pvRecord->unlock();
}
if(debug) {cout << "processed exampleDouble " << endl; }
ServerContext::shared_pointer ctx =
startPVAServer("local",0,true,true);
testOk1(ctx.get()!=0);
ctx->destroy();
}
MAIN(testExampleServer)
{
testPlan(1);
test();
return 0;
}

View File

@ -48,7 +48,6 @@ static PVRecordPtr createScalar(
{
PVStructurePtr pvStructure = getStandardPVField()->scalar(scalarType,properties);
PVRecordPtr pvRecord = PVRecord::create(recordName,pvStructure);
pvStructure.reset();
return pvRecord;
}