added longArrayGet and longArrayPut; much more testing

This commit is contained in:
Marty Kraimer
2013-11-20 10:41:29 -05:00
parent 3e1a405d01
commit ce116eefb8
14 changed files with 3280 additions and 85 deletions

View File

@ -38,7 +38,7 @@
<h1>pvDatabaseCPP</h1>
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 13-Nov-2013</h2>
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 20-Nov-2013</h2>
<dl>
<dt>Latest version:</dt>
<dd><a
@ -46,7 +46,7 @@
</dd>
<dt>This version:</dt>
<dd><a
href= "pvDatabaseCPP_20131113.html">pvDatabaseCPP20131113.html</a>
href= "pvDatabaseCPP_20131120.html">pvDatabaseCPP20131120.html</a>
</dd>
<dt>Previous version:</dt>
<dd><a
@ -79,17 +79,27 @@ V4 control system programming environment:<br />
<h2 class="nocount">Status of this Document</h2>
<p>This is the 13-Nov-2013 version of of pvDatabaseCPP.</p>
<p>This is the 20-Nov-2013 version of of pvDatabaseCPP.</p>
</p>
<p>The previous version reported a problem with a queueSize of 1.
Further thought showed that queueSize must be &gt;= 2.
This ensures that the locking between poll and dataChanged ensures that these two
methods always use separate instances of pvStructure, changeBitSet, and overrunBitSet.</p>
<p>All channel methods except channelRPC, which is implemented
by pvAccess, have been implemented.
This project is ready for alpha users.
</p>
<p>Since the last version the longArrayGet and longArrayPut examples were added.
More testing for monitor queues and memory leaks was done.
Everything looks good!!
But there are still two unresolved problems:
<dl>
<dt>memory leak</dt>
<dd>arrayPerformanceMain shows a slight memory leak at termination.</dd>
<dt>channel destroy and recreate</dt>
<dd>longArrayGet and longArrayPut fail if the channel is destroyed and
immediately recreated.
</dd>
</dl>
</p>
<p>Future enhancements in priority order:</p>
<dl>
<dt>Separate example that also has pvaSrv</dt>
@ -1582,10 +1592,28 @@ where
<dd>This creates the example using the remote channel provider.</dd>
</dl>
<h2>Array Performance</h2>
<p>Two main programs are available for testing the performance of large
arrays: arrayPerformanceMain and longArrayMonitorMain.
Each has support for <b>-help</b>.</p>
<h2>Array Performance and Memory Example</h2>
<p>This section describes main programs that demonstrate performance
of large arrays and can also be used to check for memory leaks.
Checking for memory leaks can be accomplished by running the programs with valgrind
or some other memory check program.
</p>
<h3>Brief Summary</h3>
<p>The programs are:</p>
<dl>
<dt>arrayPerformanceMain</dt>
<dd>This is server and also a configurable number of longArrayMonitor clients.
The clients can use either the local or
remote providers. The moitor code is the same code that is used by longArrayMonitorMain.
</dd>
<dt>longArrayMonitorMain</dt>
<dd>Remote client that monitors the array served by arrayPerformanceMain.</dd>
<dt>longArrayGetMain</dt>
<dd>Remote client that uses channelGet to access the array served by arrayPerformanceMain.</dd>
<dt>longArrayPutMain</dt>
<dd>Remote client that uses channelPut to access the array served by arrayPerformanceMain.</dd>
<dl>
<p>Each has support for <b>-help</b>.</p>
<pre>
mrk&gt; pwd
/home/hg/pvDatabaseCPP-md
@ -1593,33 +1621,97 @@ mrk&gt; bin/linux-x86_64/arrayPerformanceMain -help
arrayPerformanceMain recordName size delay providerName nMonitor queueSize waitTime
default
arrayPerformance arrayPerformance 10000000 0.0001 local 1 2 0.0
mrk&gt; bin/linux-x86_64/longArrayMonitorMain -help
longArrayMonitorMain channelName queueSize waitTime
default
longArrayMonitorMain arrayPerformance 2 0.0
mrk&gt; bin/linux-x86_64/longArrayGetMain -help
longArrayGetMain channelName iterBetweenCreateChannel iterBetweenCreateChannelGet delayTime
default
longArrayGetMain arrayPerformance 0 0 1
mrk&gt; bin/linux-x86_64/longArrayPutMain -help
longArrayPutMain channelName arraySize iterBetweenCreateChannel iterBetweenCreateChannelPut delayTime
default
longArrayPutMain arrayPerformance 10 0 0 1
mrk&gt;
</pre>
<h3>Example output</h3>
<p><b>Note:</b> These may fail if run on a platform that does not have sufficent memory,</p>
<p>To see an example just execute the following commands in four different terminal windows:</p>
<pre>
bin/linux/&lt;arch&gt;/arrayPerformanceMain
bin/linux/&lt;arch&gt;/longArrayMonitorMain
bin/linux/&lt;arch&gt;/longArrayGetMain
bin/linux/&lt;arch&gt;/longArrayPutMain
</pre>
<p>Each program generates a report every second when it has somthing to report.
Examples are:
<pre>
mrk&gt; bin/linux-x86_64/arrayPerformanceMain
arrayPerformance arrayPerformance 10000000 0.0001 local 1 2 0.0
arrayPerformance arrayPerformance 10000000 0.0001 local 1 2 0
...
first 526 last 526 sum 5260000000 elements/sec 499.337million changed {1, 2} overrun {}
first 527 last 527 sum 5270000000 elements/sec 568.729million changed {1, 2} overrun {}
first 528 last 528 sum 5280000000 elements/sec 505.281million changed {1, 2} overrun {}
first 529 last 529 sum 5290000000 elements/sec 506.33million changed {1, 2} overrun {}
first 530 last 530 sum 5300000000 elements/sec 574.022million changed {1, 2} overrun {}
arrayPerformance value 532 time 1.00839 iterations/sec 51.5672 elements/sec 515.672million
first 531 last 531 sum 5310000000 elements/sec 484.185million changed {1, 2} overrun {}
first 532 last 532 sum 5320000000 elements/sec 531.4million changed {1, 2} overrun {}
first 533 last 533 sum 5330000000 elements/sec 428.229million changed {1, 2} overrun {}
first 534 last 534 sum 5340000000 elements/sec 427.387million changed {1, 2} overrun {}
first 535 last 535 sum 5350000000 elements/sec 443.669million changed {1, 2} overrun {}
monitors/sec 66 first 131 last 131 changed {1, 2} overrun {} megaElements/sec 656.999
arrayPerformance value 132 time 1.00486 Iterations/sec 65.681 megaElements/sec 656.81
monitors/sec 66 first 197 last 197 changed {1, 2} overrun {} megaElements/sec 656.304
arrayPerformance value 198 time 1.00563 Iterations/sec 65.6307 megaElements/sec 656.307
monitors/sec 66 first 263 last 263 changed {1, 2} overrun {} megaElements/sec 654.824
...
</pre>
<pre>
mrk&gt; bin/linux-x86_64/longArrayMonitorMain
longArrayMonitorMain arrayPerformance 2 0
...
monitors/sec 6 first 2357 last 2357 changed {1, 2} overrun {} megaElements/sec 68.6406
monitors/sec 13 first 2385 last 2385 changed {1, 2} overrun {} megaElements/sec 118.72
monitors/sec 9 first 2418 last 2418 changed {1, 2} overrun {1, 2} megaElements/sec 85.0984
...
</pre>
<pre>
mrk&gt; bin/linux-x86_64/longArrayPutMain
longArrayPutMain arrayPerformance 10 0 0 1
...
put numChannelPut 0 time 1.00148 Elements/sec 79.8819
put numChannelPut 1 time 1.00176 Elements/sec 79.8598
...
</pre>
<pre>
mrk&gt; bin/linux-x86_64/longArrayGetMain
longArrayGetMain arrayPerformance 0 0 1
...
get kiloElements/sec 7384.61
get kiloElements/sec 8726.34
...
</pre>
<h3>arrayPerformance</h3>
<p>The arguments for arrayPerforamanceMain are:</p>
<dl>
<dt>recordName</dt>
<dd>The name for the arrayPerform record.</dd>
<dt>size</dt>
<dd>The size for the long array of the value field.</dd>
<dt>delay</dt>
<dd>The time in seconds to sleep after each iteration.</dd>
<dt>providerName</dt>
<dd>The name of the channel provider for the longArrayMonitors
created by the main program. This must be either <b>local</b>
or <b>pvAccess</b>.
</dd>
<dt>nMonitor</dt>
<dd>The number of longArrayMonitors to create.</dd>
<dt>queueSize</dt>
<dd>The queueSize for the element queue.
A value less than 1 will become 1.
</dd>
<dt>waitTime</dt>
<dd>The time that longArrayMonitor will sleep after poll returns a monitorElement.</dd>
</dl>
<p>
This creates a PVRecord that has the structure:.
arrayPerformance creates a PVRecord that has the structure:.
<pre>
recordName
long[] value
@ -1631,7 +1723,7 @@ Thus it holds an array of 64 bit integers.</p>
until the record is destroyed executing the following algorithm:</p>
<dl>
<dt>report</dt>
<dd>At least once a second it produces a report.
<dd>Once a second it produces a report.
In the above example output each line starting with
<b>ArrayPerformance</b> is an arrayPerformance report.
</dd>
@ -1655,40 +1747,66 @@ until the record is destroyed executing the following algorithm:</p>
<dt>delay</dt>
<dd>If delay is greater than zero epicsThreadSleep is called.</dd>
</dl>
<p>The arguments for arrayPerforamanceMain are:</p>
<dl>
<dt>recordName</dt>
<dd>The name for the arrayPerform record.</dd>
<dt>size</dt>
<dd>The size for the long array of the value field.</dd>
<dt>delay</dt>
<dd>The time in seconds to sleep after each iteration.</dd>
<dt>providerName</dt>
<dd>The name of the channel provider for the longArrayMonitors
created by the main program. This must be either <b>local</b>
or <b>pvAccess</b>.
</dd>
<dt>nMonitor</dt>
<dd>The number of longArrayMonitors to create.</dd>
<dt>queueSize</dt>
<dd>The queueSize for the element queue.
A value less than 1 will become 1.
</dd>
<dt>waitTime</dt>
<dd>The time that longArrayMonitor will sleep after poll returns a monitorElement.</dd>
</dl>
<h3>longArrayMonitor</h3>
<p>This is a pvAccess client that monitors an arrayPerformance record.
It generates a report for each monitor event.
In the example output shown above each line starting with <b>first</b>
is a report.</p>
It generates a report every second showing how many elements has received.
For every monitor it also checks that the number of alements is &gt;0 and the
the first element equals the last element. It reports an error if either
of these conditions is not true.</p>
<p>The arguments for longArrayMonitorMain are:</p>
<dl>
<dt>channelName</dt>
<dd>The name for the arrayPerform record.</dd>
<dt>queueSize</dt>
<dd>The queueSize. Note that any size &lt;2 is made 2.</dd>
<dt>waitTime</dt>
<dd>The time to wait after a poll request returns a monitorElement.
This can be used to force an overrun of the client even if there is no
overrun on the server.</dd>
</dl>
<h3>longArrayGet</h3>
<p>This is a pvAccess client that uses channelGet to access an arrayPerformance record.
Every second it produces a report.</p>
<p>The arguments for longArrayGetMain are:</p>
<dl>
<dt>channelName</dt>
<dd>The name for the arrayPerform record.</dd>
<dt>iterBetweenCreateChannel</dt>
<dd>The number of iterations between destroying and recreating the channel.
A value of 0 means never destroy and recreate.
</dd>
<dt>iterBetweenCreateChannelGet</dt>
<dd>The number of iterations between destroying and recreating the channelGet.
A value of 0 means never destroy and recreate.
</dd>
<dt>delayTime</dt>
<dd>The time to dalay between gets.</dd>
</dl>
<h3>longArrayPut</h3>
<p>This is a pvAccess client that uses channelPut to access an arrayPerformance record.
Every second it produces a report.</p>
<p>The arguments for longArrayPutMain are:</p>
<dl>
<dt>channelName</dt>
<dd>The name for the arrayPerform record.</dd>
<dt>arraySize</dt>
<dd>The capacity and length of the array to put to the server.</dd>
<dt>iterBetweenCreateChannel</dt>
<dd>The number of iterations between destroying and recreating the channel.
A value of 0 means never destroy and recreate.
</dd>
<dt>iterBetweenCreateChannelPut</dt>
<dd>The number of iterations between destroying and recreating the channelPut.
A value of 0 means never destroy and recreate.
</dd>
<dt>delayTime</dt>
<dd>The time to dalay between gets.</dd>
</dl>
<h3>Some results</h3>
<h4>array performance</h4>
<p>The results were from my laptop.
It has a 2.2Ghz intel core i7 with 4Gbytes of memory.
The operating system is linux fedora 16.</p>
@ -1724,6 +1842,21 @@ The next section has an example that demonstrates what happens.
Note that if the array size is small enough to fit in the local cache then running longArrayMonitor
has almost no effect of arrayPerforance.
</p>
<h4>memory leaks</h4>
<p>Running longArrayMonitorMain, longArrayPutMain, and longArrayGetMain
under valgrind shows no memory leaks.</p>
<p>arrayPerformanceMain shows the following:</p>
<pre>
==9125== LEAK SUMMARY:
==9125== definitely lost: 0 bytes in 0 blocks
==9125== indirectly lost: 0 bytes in 0 blocks
==9125== possibly lost: 576 bytes in 2 blocks
</pre>
<p>The possibly leaked is either 1 or 2 blocks.
It seems to be the same if clients are connected.
</p>
<h4>iterBetweenCreateChannel</h4>
<p>If this is not zero then the attempt to destroy and recreate the channel fails.</p>
<h2>Vector Performance</h2>
<p>This example demonstrates how array size effects performance.
The example is run as:</p>

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,16 @@ longArrayMonitorMain_SRCS += longArrayMonitorMain.cpp
longArrayMonitorMain_LIBS += pvDatabase pvAccess pvData Com
longArrayMonitorMain_LIBS += pvDatabaseExample
PROD_HOST += longArrayGetMain
longArrayGetMain_SRCS += longArrayGetMain.cpp
longArrayGetMain_LIBS += pvDatabase pvAccess pvData Com
longArrayGetMain_LIBS += pvDatabaseExample
PROD_HOST += longArrayPutMain
longArrayPutMain_SRCS += longArrayPutMain.cpp
longArrayPutMain_LIBS += pvDatabase pvAccess pvData Com
longArrayPutMain_LIBS += pvDatabaseExample
PROD_HOST += vectorPerformanceMain
vectorPerformanceMain_SRCS += vectorPerformanceMain.cpp
vectorPerformanceMain_LIBS += pvDatabase pvAccess pvData Com

View File

@ -0,0 +1,86 @@
/*longArrayGetMain.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
* @date 2013.08.10
*/
/* Author: Marty Kraimer */
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstdio>
#include <memory>
#include <iostream>
#include <vector>
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/arrayPerformance.h>
#include <pv/longArrayGet.h>
#include <pv/traceRecord.h>
#include <pv/channelProviderLocal.h>
#include <pv/serverContext.h>
#include <pv/clientFactory.h>
using namespace std;
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvDatabase;
int main(int argc,char *argv[])
{
String channelName("arrayPerformance");
int iterBetweenCreateChannel = 0;
int iterBetweenCreateChannelGet = 0;
double delayTime = 1.0;
if(argc==2 && String(argv[1])==String("-help")) {
cout << "longArrayGetMain channelName ";
cout << "iterBetweenCreateChannel iterBetweenCreateChannelGet delayTime" << endl;
cout << "default" << endl;
cout << "longArrayGetMain " << channelName << " ";
cout << iterBetweenCreateChannel << " ";
cout << iterBetweenCreateChannelGet << " ";
cout << delayTime << endl;
return 0;
}
ClientFactory::start();
if(argc>1) channelName = argv[1];
if(argc>2) iterBetweenCreateChannel = strtol(argv[2],0,0);
if(argc>3) iterBetweenCreateChannelGet = strtol(argv[3],0,0);
if(argc>4) delayTime = atof(argv[4]);
cout << "longArrayGetMain " << channelName << " ";
cout << iterBetweenCreateChannel << " ";
cout << iterBetweenCreateChannelGet << " ";
cout << delayTime << endl;
LongArrayGetPtr longArrayGet
= LongArrayGet::create(
"pvAccess",
channelName,
iterBetweenCreateChannel,
iterBetweenCreateChannelGet,
delayTime);
cout << "longArrayGet\n";
string str;
while(true) {
cout << "Type exit to stop: \n";
getline(cin,str);
if(str.compare("exit")==0) break;
}
longArrayGet->destroy();
longArrayGet.reset();
double xxx = 1.0;
if(xxx<delayTime) xxx = delayTime;
ClientFactory::stop();
epicsThreadSleep(xxx);
return 0;
}

View File

@ -66,10 +66,10 @@ int main(int argc,char *argv[])
if(str.compare("exit")==0) break;
}
ClientFactory::stop();
epicsThreadSleep(.1);
longArrayMonitor->destroy();
longArrayMonitor.reset();
ClientFactory::stop();
epicsThreadSleep(1.0);
return 0;
}

View File

@ -0,0 +1,92 @@
/*longArrayPutMain.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
* @date 2013.08.10
*/
/* Author: Marty Kraimer */
#include <cstddef>
#include <cstdlib>
#include <cstddef>
#include <string>
#include <cstdio>
#include <memory>
#include <iostream>
#include <vector>
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/arrayPerformance.h>
#include <pv/longArrayPut.h>
#include <pv/traceRecord.h>
#include <pv/channelProviderLocal.h>
#include <pv/serverContext.h>
#include <pv/clientFactory.h>
using namespace std;
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvDatabase;
int main(int argc,char *argv[])
{
String channelName("arrayPerformance");
size_t arraySize = 10;
int iterBetweenCreateChannel = 0;
int iterBetweenCreateChannelPut = 0;
double delayTime = 1.0;
if(argc==2 && String(argv[1])==String("-help")) {
cout << "longArrayPutMain channelName arraySize ";
cout << "iterBetweenCreateChannel iterBetweenCreateChannelPut delayTime" << endl;
cout << "default" << endl;
cout << "longArrayPutMain " << channelName << " ";
cout << arraySize << " ";
cout << iterBetweenCreateChannel << " ";
cout << iterBetweenCreateChannelPut << " ";
cout << delayTime << endl;
return 0;
}
ClientFactory::start();
if(argc>1) channelName = argv[1];
if(argc>2) arraySize = strtoul(argv[2],0,0);
if(argc>3) iterBetweenCreateChannel = strtol(argv[3],0,0);
if(argc>4) iterBetweenCreateChannelPut = strtol(argv[4],0,0);
if(argc>5) delayTime = atof(argv[5]);
cout << "longArrayPutMain " << channelName << " ";
cout << arraySize << " ";
cout << iterBetweenCreateChannel << " ";
cout << iterBetweenCreateChannelPut << " ";
cout << delayTime << endl;
LongArrayPutPtr longArrayPut
= LongArrayPut::create(
"pvAccess",
channelName,
arraySize,
iterBetweenCreateChannel,
iterBetweenCreateChannelPut,
delayTime);
cout << "longArrayPut\n";
string str;
while(true) {
cout << "Type exit to stop: \n";
getline(cin,str);
if(str.compare("exit")==0) break;
}
longArrayPut->destroy();
longArrayPut.reset();
double xxx = 1.0;
if(xxx<delayTime) xxx = delayTime;
epicsThreadSleep(xxx);
ClientFactory::stop();
epicsThreadSleep(1.0);
return 0;
}

View File

@ -23,6 +23,10 @@ INC+= arrayPerformance.h
LIBSRCS += arrayPerformance.cpp
INC+= longArrayMonitor.h
LIBSRCS += longArrayMonitor.cpp
INC+= longArrayGet.h
LIBSRCS += longArrayGet.cpp
INC+= longArrayPut.h
LIBSRCS += longArrayPut.cpp
include $(TOP)/configure/RULES

View File

@ -143,15 +143,36 @@ void ArrayPerformanceThread::run()
if(diff>=1.0) {
ostringstream out;
out << "arrayPerformance value " << value;
out << " time " << diff;
out << " time " << diff ;
double iterations = nSinceLastReport;
iterations /= diff;
out << " iterations/sec " << iterations;
if(iterations>10.0e9) {
iterations /= 1e9;
out << " gigaIterations/sec " << iterations;
} else if(iterations>10.0e6) {
iterations /= 1e6;
out << " megaIterations/sec " << iterations;
} else if(iterations>10.0e3) {
iterations /= 1e3;
out << " kiloIterations/sec " << iterations;
} else {
out << " Iterations/sec " << iterations;
}
double elementSize = arrayPerformance->size;
double elementsPerSecond = elementSize*nSinceLastReport;
elementsPerSecond /= diff;
elementsPerSecond /= 1e6;
out << " elements/sec " << elementsPerSecond << "million";
if(elementsPerSecond>10.0e9) {
elementsPerSecond /= 1e9;
out << " gigaElements/sec " << elementsPerSecond;
} else if(elementsPerSecond>10.0e6) {
elementsPerSecond /= 1e6;
out << " megaElements/sec " << elementsPerSecond;
} else if(elementsPerSecond>10.0e3) {
elementsPerSecond /= 1e3;
out << " kiloElements/sec " << elementsPerSecond;
} else {
out << " Elements/sec " << elementsPerSecond;
}
cout << out.str() << endl;
timeStampLast = timeStamp;
nSinceLastReport = 0;

View File

@ -0,0 +1,381 @@
/* longArrayGet.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
* @date 2013.08.09
*/
#include <epicsThread.h>
#include <pv/longArrayGet.h>
#include <pv/caProvider.h>
namespace epics { namespace pvDatabase {
using namespace epics::pvData;
using namespace epics::pvAccess;
using std::tr1::static_pointer_cast;
using std::tr1::dynamic_pointer_cast;
using std::cout;
using std::endl;
using std::ostringstream;
static String requesterName("longArrayGet");
static String request("value,timeStamp,alarm");
static epics::pvData::Mutex printMutex;
class LongArrayChannelGet :
virtual public ChannelRequester,
virtual public ChannelGetRequester,
public std::tr1::enable_shared_from_this<LongArrayChannelGet>,
public epicsThreadRunable
{
public:
LongArrayChannelGet(
String providerName,
String channelName,
int iterBetweenCreateChannel,
int iterBetweenCreateChannelGet,
double delayTime)
: providerName(providerName),
channelName(channelName),
iterBetweenCreateChannel(iterBetweenCreateChannel),
iterBetweenCreateChannelGet(iterBetweenCreateChannelGet),
delayTime(delayTime),
isDestroyed(false),
runReturned(false),
threadName("longArrayGet")
{}
virtual ~LongArrayChannelGet(){}
bool init();
virtual void destroy();
virtual void run();
virtual String getRequesterName() { return requesterName;}
virtual void message(String const & message, MessageType messageType)
{
Lock guard(printMutex);
cout << requesterName << " message " << message << endl;
}
virtual void channelCreated(
const Status& status,
Channel::shared_pointer const & channel);
virtual void channelStateChange(
Channel::shared_pointer const & channel,
Channel::ConnectionState connectionState);
virtual void channelGetConnect(
Status const & status,
ChannelGet::shared_pointer const & channelGet,
PVStructurePtr const &pvStructure,
BitSetPtr const &bitSet);
virtual void getDone(Status const & status);
private:
LongArrayChannelGetPtr getPtrSelf()
{
return shared_from_this();
}
size_t checkResult();
String providerName;
String channelName;
int iterBetweenCreateChannel;
int iterBetweenCreateChannelGet;
double delayTime;
bool isDestroyed;
bool runReturned;
epics::pvData::String threadName;
Status status;
Event event;
Mutex mutex;
std::auto_ptr<epicsThread> thread;
Channel::shared_pointer channel;
ChannelGet::shared_pointer channelGet;
PVStructurePtr pvStructure;
BitSetPtr bitSet;
};
bool LongArrayChannelGet::init()
{
ChannelProvider::shared_pointer channelProvider =
getChannelAccess()->getProvider(providerName);
if(channelProvider==NULL) {
cout << "provider " << providerName << " not found" << endl;
return false;
}
channel = channelProvider->createChannel(channelName,getPtrSelf(),0);
event.wait();
channelProvider.reset();
if(!status.isOK()) return false;
CreateRequest::shared_pointer createRequest = CreateRequest::create();
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(pvRequest==NULL) {
cout << "request logic error " << createRequest->getMessage() << endl;
return false;
}
channelGet = channel->createChannelGet(getPtrSelf(),pvRequest);
event.wait();
if(!status.isOK()) return false;
thread = std::auto_ptr<epicsThread>(new epicsThread(
*this,
threadName.c_str(),
epicsThreadGetStackSize(epicsThreadStackSmall),
epicsThreadPriorityLow));
thread->start();
event.signal();
return true;
}
void LongArrayChannelGet::destroy()
{
if(isDestroyed) return;
isDestroyed = true;
event.signal();
while(true) {
if(runReturned) break;
epicsThreadSleep(.01);
}
thread->exitWait();
channel->destroy();
channelGet.reset();
channel.reset();
}
void LongArrayChannelGet::channelCreated(
const Status& status,
Channel::shared_pointer const & channel)
{
if(!status.isOK()) message(status.getMessage(),errorMessage);
this->status = status;
this->channel = channel;
event.signal();
}
void LongArrayChannelGet::channelStateChange(
Channel::shared_pointer const & channel,
Channel::ConnectionState connectionState)
{
MessageType messageType =
(connectionState==Channel::CONNECTED ? infoMessage : errorMessage);
message("channelStateChange",messageType);
}
void LongArrayChannelGet::channelGetConnect(
Status const & status,
ChannelGet::shared_pointer const & channelGet,
PVStructurePtr const &pvStructure,
BitSetPtr const &bitSet)
{
this->status = status;
if(!status.isOK()) {
message(status.getMessage(),errorMessage);
event.signal();
return;
}
this->channelGet = channelGet;
this->pvStructure = pvStructure;
this->bitSet = bitSet;
bool structureOK(true);
PVFieldPtr pvField = pvStructure->getSubField("timeStamp");
if(pvField==NULL) structureOK = false;
pvField = pvStructure->getSubField("value");
if(pvField==NULL) {
structureOK = false;
} else {
FieldConstPtr field = pvField->getField();
if(field->getType()!=scalarArray) {
structureOK = false;
} else {
ScalarArrayConstPtr scalarArray = dynamic_pointer_cast<const ScalarArray>(field);
if(scalarArray->getElementType()!=pvLong) structureOK = false;
}
}
if(!structureOK) {
String mess("channelGetConnect: illegal structure");
message(mess,errorMessage);
this->status = Status(Status::STATUSTYPE_ERROR,mess);
}
event.signal();
}
void LongArrayChannelGet::run()
{
while(true) {
event.wait();
if(isDestroyed) {
runReturned = true;
return;
}
TimeStamp timeStamp;
TimeStamp timeStampLast;
timeStampLast.getCurrent();
int numChannelGet = 0;
int numChannelCreate = 0;
size_t nElements = 0;
while(true) {
channelGet->get(false);
event.wait();
if(isDestroyed) {
runReturned = true;
return;
}
size_t latestSize = checkResult();
nElements += latestSize;
timeStamp.getCurrent();
double diff = TimeStamp::diff(timeStamp,timeStampLast);
if(diff>=1.0) {
ostringstream out;
out << "get";
double elementsPerSec = nElements;
elementsPerSec /= diff;
if(elementsPerSec>10.0e9) {
elementsPerSec /= 1e9;
out << " gigaElements/sec " << elementsPerSec;
} else if(elementsPerSec>10.0e6) {
elementsPerSec /= 1e6;
out << " megaElements/sec " << elementsPerSec;
} else if(elementsPerSec>10.0e3) {
elementsPerSec /= 1e3;
out << " kiloElements/sec " << elementsPerSec;
} else {
out << " Elements/sec " << elementsPerSec;
}
cout << out.str() << endl;
timeStampLast = timeStamp;
nElements = 0;
}
if(delayTime>0.0) epicsThreadSleep(delayTime);
if(isDestroyed) {
runReturned = true;
return;
}
++numChannelCreate;
bool createGet = false;
if(iterBetweenCreateChannel!=0) {
if(numChannelCreate>=iterBetweenCreateChannel) {
channel->destroy();
ChannelProvider::shared_pointer channelProvider =
getChannelAccess()->getProvider(providerName);
channel = channelProvider->createChannel(
channelName,getPtrSelf(),0);
event.wait();
channelProvider.reset();
if(!status.isOK()) {
message(status.getMessage(),errorMessage);
return;
}
cout<< "createChannel success" << endl;
createGet = true;
numChannelCreate = 0;
numChannelGet = 0;
}
}
++numChannelGet;
if(iterBetweenCreateChannelGet!=0) {
if(numChannelGet>=iterBetweenCreateChannelGet) createGet = true;
}
if(createGet) {
numChannelGet = 0;
channelGet->destroy();
CreateRequest::shared_pointer createRequest = CreateRequest::create();
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(pvRequest==NULL) {
cout << "request logic error " << createRequest->getMessage() << endl;
return ;
}
channelGet = channel->createChannelGet(getPtrSelf(),pvRequest);
event.wait();
if(!status.isOK()) {
message(status.getMessage(),errorMessage);
return;
}
cout<< "createChannelGet success" << endl;
}
}
}
}
void LongArrayChannelGet::getDone(Status const & status)
{
event.signal();
}
size_t LongArrayChannelGet::checkResult()
{
PVLongArrayPtr pvValue;
if(!status.isOK()) {
message(status.getMessage(),errorMessage);
return 0;
}
pvValue = dynamic_pointer_cast<PVLongArray>(pvStructure->getSubField("value"));
if(!bitSet->get(pvValue->getFieldOffset())) {
return 0;
}
bitSet->clear();
shared_vector<const int64> data = pvValue->view();
if(data.size()>0) {
int64 first = data[0];
int64 last = data[data.size()-1];
if(first!=last) {
cout << "error first=" << first << " last=" << last << endl;
}
}
return data.size();
}
LongArrayGetPtr LongArrayGet::create(
String const &providerName,
String const & channelName,
int iterBetweenCreateChannel,
int iterBetweenCreateChannelGet,
double delayTime)
{
LongArrayGetPtr longArrayGet(
new LongArrayGet(
providerName,
channelName,
iterBetweenCreateChannel,
iterBetweenCreateChannelGet,
delayTime));
if(!longArrayGet->init()) longArrayGet.reset();
return longArrayGet;
}
LongArrayGet::LongArrayGet(
String const &providerName,
String const & channelName,
int iterBetweenCreateChannel,
int iterBetweenCreateChannelGet,
double delayTime)
: providerName(providerName),
channelName(channelName),
iterBetweenCreateChannel(iterBetweenCreateChannel),
iterBetweenCreateChannelGet(iterBetweenCreateChannelGet),
delayTime(delayTime)
{}
LongArrayGet::~LongArrayGet() {}
bool LongArrayGet::init()
{
longArrayChannelGet = LongArrayChannelGetPtr(new LongArrayChannelGet(
providerName,
channelName,
iterBetweenCreateChannel,
iterBetweenCreateChannelGet,
delayTime));
return longArrayChannelGet->init();
}
void LongArrayGet::destroy()
{
longArrayChannelGet->destroy();
longArrayChannelGet.reset();
}
}}

View File

@ -0,0 +1,68 @@
/* longArrayGet.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.08.09
*/
#ifndef LONGARRAYGET_H
#define LONGARRAYGET_H
#include <pv/event.h>
#include <pv/lock.h>
#include <pv/standardPVField.h>
#include <pv/timeStamp.h>
#include <pv/pvTimeStamp.h>
#include <pv/pvAccess.h>
namespace epics { namespace pvDatabase {
class LongArrayGet;
typedef std::tr1::shared_ptr<LongArrayGet> LongArrayGetPtr;
class LongArrayChannelGet;
typedef std::tr1::shared_ptr<LongArrayChannelGet> LongArrayChannelGetPtr;
class LongArrayGet :
public std::tr1::enable_shared_from_this<LongArrayGet>
{
public:
POINTER_DEFINITIONS(LongArrayGet);
static LongArrayGetPtr create(
epics::pvData::String const & providerName,
epics::pvData::String const & channelName,
int iterBetweenCreateChannel = 0,
int iterBetweenCreateChannelGet = 0,
double delayTime = 0.0);
~LongArrayGet();
void destroy();
private:
LongArrayGetPtr getPtrSelf()
{
return shared_from_this();
}
LongArrayGet(
epics::pvData::String const & providerName,
epics::pvData::String const & channelName,
int iterBetweenCreateChannel = 0,
int iterBetweenCreateChannelGet = 0,
double delayTime = 0.0);
bool init();
epics::pvData::String providerName;
epics::pvData::String channelName;
int iterBetweenCreateChannel;
int iterBetweenCreateChannelGet;
double delayTime;
LongArrayChannelGetPtr longArrayChannelGet;
};
}}
#endif /* LONGARRAYGET_H */

View File

@ -21,6 +21,7 @@ using std::tr1::static_pointer_cast;
using std::tr1::dynamic_pointer_cast;
using std::cout;
using std::endl;
using std::ostringstream;
static String requesterName("longArrayMonitor");
@ -86,7 +87,6 @@ public:
virtual void monitorEvent(MonitorPtr const & monitor);
virtual void unlisten(MonitorPtr const & monitor);
private:
void handleMonitor();
LongArrayMonitorPtr longArrayMonitor;
double waitTime;
bool isDestroyed;
@ -160,6 +160,8 @@ void LAMMonitorRequester::run()
TimeStamp timeStamp;
TimeStamp timeStampLast;
timeStampLast.getCurrent();
size_t nElements = 0;
int nSinceLastReport = 0;
while(true) {
event.wait();
if(isDestroyed) {
@ -181,25 +183,45 @@ void LAMMonitorRequester::run()
pvValue = dynamic_pointer_cast<PVLongArray>(pvStructure->getSubField("value"));
shared_vector<const int64> data = pvValue->view();
if(data.size()>0) {
nElements += data.size();
int64 first = data[0];
int64 last = data[data.size()-1];
int64 sum = 0;
for(size_t i=0; i<data.size(); ++i) sum += data[i];
if(first!=last) {
cout << "error first=" << first << " last=" << last << endl;
}
double diff = TimeStamp::diff(timeStamp,timeStampLast);
double elementsPerSecond = data.size();
elementsPerSecond = 1e-6*elementsPerSecond/diff;
cout << "first " << first << " last " << last << " sum " << sum;
cout << " elements/sec " << elementsPerSecond << "million";
BitSetPtr changed = monitorElement->changedBitSet;
BitSetPtr overrun = monitorElement->overrunBitSet;
String buffer;
changed->toString(&buffer);
cout << " changed " << buffer;
buffer.clear();
overrun->toString(&buffer);
cout << " overrun " << buffer;
cout << endl;
timeStampLast = timeStamp;
if(diff>=1.0) {
ostringstream out;
out << " monitors/sec " << nSinceLastReport << " ";
out << "first " << first << " last " << last ;
BitSetPtr changed = monitorElement->changedBitSet;
BitSetPtr overrun = monitorElement->overrunBitSet;
String buffer;
changed->toString(&buffer);
out << " changed " << buffer;
buffer.clear();
overrun->toString(&buffer);
out << " overrun " << buffer;
double elementsPerSec = nElements;
elementsPerSec /= diff;
if(elementsPerSec>10.0e9) {
elementsPerSec /= 1e9;
out << " gigaElements/sec " << elementsPerSec;
} else if(elementsPerSec>10.0e6) {
elementsPerSec /= 1e6;
out << " megaElements/sec " << elementsPerSec;
} else if(elementsPerSec>10.0e3) {
elementsPerSec /= 1e3;
out << " kiloElements/sec " << elementsPerSec;
} else {
out << " Elements/sec " << elementsPerSec;
}
cout << out.str() << endl;
timeStampLast = timeStamp;
nSinceLastReport = 0;
nElements = 0;
}
++nSinceLastReport;
} else {
cout << "size = 0" << endl;
}

View File

@ -0,0 +1,374 @@
/* longArrayPut.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
* @date 2013.08.09
*/
#include <epicsThread.h>
#include <pv/longArrayPut.h>
#include <pv/caProvider.h>
namespace epics { namespace pvDatabase {
using namespace epics::pvData;
using namespace epics::pvAccess;
using std::tr1::static_pointer_cast;
using std::tr1::dynamic_pointer_cast;
using std::cout;
using std::endl;
using std::ostringstream;
static String requesterName("longArrayPut");
static String request("value");
static epics::pvData::Mutex printMutex;
class LongArrayChannelPut :
virtual public ChannelRequester,
virtual public ChannelPutRequester,
public std::tr1::enable_shared_from_this<LongArrayChannelPut>,
public epicsThreadRunable
{
public:
LongArrayChannelPut(
String providerName,
String channelName,
size_t arraySize,
int iterBetweenCreateChannel,
int iterBetweenCreateChannelPut,
double delayTime)
: providerName(providerName),
channelName(channelName),
arraySize(arraySize),
iterBetweenCreateChannel(iterBetweenCreateChannel),
iterBetweenCreateChannelPut(iterBetweenCreateChannelPut),
delayTime(delayTime),
isDestroyed(false),
runReturned(false),
threadName("longArrayPut")
{}
virtual ~LongArrayChannelPut(){}
bool init();
virtual void destroy();
virtual void run();
virtual String getRequesterName() { return requesterName;}
virtual void message(String const & message, MessageType messageType)
{
Lock guard(printMutex);
cout << requesterName << " message " << message << endl;
}
virtual void channelCreated(
const Status& status,
Channel::shared_pointer const & channel);
virtual void channelStateChange(
Channel::shared_pointer const & channel,
Channel::ConnectionState connectionState);
virtual void channelPutConnect(
Status const & status,
ChannelPut::shared_pointer const & channelPut,
PVStructurePtr const &pvStructure,
BitSetPtr const &bitSet);
virtual void putDone(Status const & status);
virtual void getDone(Status const & status){}
private:
LongArrayChannelPutPtr getPtrSelf()
{
return shared_from_this();
}
String providerName;
String channelName;
size_t arraySize;
int iterBetweenCreateChannel;
int iterBetweenCreateChannelPut;
double delayTime;
bool isDestroyed;
bool runReturned;
epics::pvData::String threadName;
Status status;
Event event;
Mutex mutex;
std::auto_ptr<epicsThread> thread;
Channel::shared_pointer channel;
ChannelPut::shared_pointer channelPut;
PVStructurePtr pvStructure;
PVLongArrayPtr pvLongArray;
BitSetPtr bitSet;
};
bool LongArrayChannelPut::init()
{
ChannelProvider::shared_pointer channelProvider = getChannelAccess()->getProvider(providerName);
if(channelProvider==NULL) {
cout << "provider " << providerName << " not found" << endl;
return false;
}
channel = channelProvider->createChannel(channelName,getPtrSelf(),0);
event.wait();
if(!status.isOK()) return false;
CreateRequest::shared_pointer createRequest = CreateRequest::create();
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(pvRequest==NULL) {
cout << "request logic error " << createRequest->getMessage() << endl;
return false;
}
channelPut = channel->createChannelPut(getPtrSelf(),pvRequest);
event.wait();
if(!status.isOK()) return false;
thread = std::auto_ptr<epicsThread>(new epicsThread(
*this,
threadName.c_str(),
epicsThreadGetStackSize(epicsThreadStackSmall),
epicsThreadPriorityLow));
thread->start();
event.signal();
return true;
}
void LongArrayChannelPut::destroy()
{
if(isDestroyed) return;
isDestroyed = true;
event.signal();
while(true) {
if(runReturned) break;
epicsThreadSleep(.01);
}
thread->exitWait();
channel->destroy();
channelPut.reset();
channel.reset();
}
void LongArrayChannelPut::channelCreated(
const Status& status,
Channel::shared_pointer const & channel)
{
if(!status.isOK()) message(status.getMessage(),errorMessage);
this->status = status;
this->channel = channel;
event.signal();
}
void LongArrayChannelPut::channelStateChange(
Channel::shared_pointer const & channel,
Channel::ConnectionState connectionState)
{
MessageType messageType =
(connectionState==Channel::CONNECTED ? infoMessage : errorMessage);
message("channelStateChange",messageType);
}
void LongArrayChannelPut::channelPutConnect(
Status const & status,
ChannelPut::shared_pointer const & channelPut,
PVStructurePtr const &pvStructure,
BitSetPtr const &bitSet)
{
this->status = status;
if(!status.isOK()) {
message(status.getMessage(),errorMessage);
event.signal();
return;
}
this->channelPut = channelPut;
this->pvStructure = pvStructure;
this->bitSet = bitSet;
bool structureOK(true);
PVFieldPtr pvField = pvStructure->getSubField("value");
if(pvField==NULL) {
structureOK = false;
} else {
FieldConstPtr field = pvField->getField();
if(field->getType()!=scalarArray) {
structureOK = false;
} else {
ScalarArrayConstPtr scalarArray = dynamic_pointer_cast<const ScalarArray>(field);
if(scalarArray->getElementType()!=pvLong) structureOK = false;
}
}
if(!structureOK) {
String mess("channelPutConnect: illegal structure");
message(mess,errorMessage);
this->status = Status(Status::STATUSTYPE_ERROR,mess);
}
pvLongArray = static_pointer_cast<PVLongArray>(pvField);
event.signal();
}
void LongArrayChannelPut::run()
{
while(true) {
event.wait();
if(isDestroyed) {
runReturned = true;
return;
}
TimeStamp timeStamp;
TimeStamp timeStampLast;
timeStampLast.getCurrent();
int numChannelPut = 0;
int numChannelCreate = 0;
size_t nElements = 0;
while(true) {
nElements += sizeof(int64) * arraySize;
shared_vector<int64> xxx(arraySize,numChannelPut);
shared_vector<const int64> data(freeze(xxx));
pvLongArray->replace(data);
bitSet->set(pvLongArray->getFieldOffset());
channelPut->put(false);
event.wait();
if(isDestroyed) {
runReturned = true;
return;
}
if(delayTime>0.0) epicsThreadSleep(delayTime);
if(isDestroyed) {
runReturned = true;
return;
}
timeStamp.getCurrent();
double diff = TimeStamp::diff(timeStamp,timeStampLast);
if(diff>=1.0) {
ostringstream out;
out << "put numChannelPut " << numChannelPut;
out << " time " << diff ;
double elementsPerSec = nElements;
elementsPerSec /= diff;
if(elementsPerSec>10.0e9) {
elementsPerSec /= 1e9;
out << " gigaElements/sec " << elementsPerSec;
} else if(elementsPerSec>10.0e6) {
elementsPerSec /= 1e6;
out << " megaElements/sec " << elementsPerSec;
} else if(elementsPerSec>10.0e3) {
elementsPerSec /= 1e3;
out << " kiloElements/sec " << elementsPerSec;
} else {
out << " Elements/sec " << elementsPerSec;
}
cout << out.str() << endl;
timeStampLast = timeStamp;
nElements = 0;
}
++numChannelCreate;
bool createPut = false;
if(iterBetweenCreateChannel!=0) {
if(numChannelCreate>=iterBetweenCreateChannel) {
channel->destroy();
ChannelProvider::shared_pointer channelProvider =
getChannelAccess()->getProvider(providerName);
channel = channelProvider->createChannel(channelName,getPtrSelf(),0);
event.wait();
if(isDestroyed) {
runReturned = true;
return;
}
if(!status.isOK()) {
message(status.getMessage(),errorMessage);
return;
}
cout<< "createChannel success" << endl;
createPut = true;
numChannelCreate = 0;
numChannelPut = 0;
}
}
++numChannelPut;
if(iterBetweenCreateChannelPut!=0) {
if(numChannelPut>=iterBetweenCreateChannelPut) createPut = true;
}
if(createPut) {
numChannelPut = 0;
channelPut->destroy();
CreateRequest::shared_pointer createRequest = CreateRequest::create();
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(pvRequest==NULL) {
cout << "request logic error " << createRequest->getMessage() << endl;
return ;
}
channelPut = channel->createChannelPut(getPtrSelf(),pvRequest);
event.wait();
if(isDestroyed) {
runReturned = true;
return;
}
if(!status.isOK()) {
message(status.getMessage(),errorMessage);
return;
}
cout<< "createChannelPut success" << endl;
}
}
}
}
void LongArrayChannelPut::putDone(Status const & status)
{
event.signal();
}
LongArrayPutPtr LongArrayPut::create(
String const &providerName,
String const & channelName,
size_t arraySize,
int iterBetweenCreateChannel,
int iterBetweenCreateChannelPut,
double delayTime)
{
LongArrayPutPtr longArrayPut(
new LongArrayPut(
providerName,
channelName,
arraySize,
iterBetweenCreateChannel,
iterBetweenCreateChannelPut,
delayTime));
if(!longArrayPut->init()) longArrayPut.reset();
return longArrayPut;
}
LongArrayPut::LongArrayPut(
String const &providerName,
String const & channelName,
size_t arraySize,
int iterBetweenCreateChannel,
int iterBetweenCreateChannelPut,
double delayTime)
: providerName(providerName),
channelName(channelName),
arraySize(arraySize),
iterBetweenCreateChannel(iterBetweenCreateChannel),
iterBetweenCreateChannelPut(iterBetweenCreateChannelPut),
delayTime(delayTime)
{}
LongArrayPut::~LongArrayPut() {}
bool LongArrayPut::init()
{
longArrayChannelPut = LongArrayChannelPutPtr(new LongArrayChannelPut(
providerName,
channelName,
arraySize,
iterBetweenCreateChannel,
iterBetweenCreateChannelPut,
delayTime));
return longArrayChannelPut->init();
}
void LongArrayPut::destroy()
{
longArrayChannelPut->destroy();
longArrayChannelPut.reset();
}
}}

View File

@ -0,0 +1,71 @@
/* longArrayPut.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.08.09
*/
#ifndef LONGARRAYPUT_H
#define LONGARRAYPUT_H
#include <pv/event.h>
#include <pv/lock.h>
#include <pv/standardPVField.h>
#include <pv/timeStamp.h>
#include <pv/pvTimeStamp.h>
#include <pv/pvAccess.h>
namespace epics { namespace pvDatabase {
class LongArrayPut;
typedef std::tr1::shared_ptr<LongArrayPut> LongArrayPutPtr;
class LongArrayChannelPut;
typedef std::tr1::shared_ptr<LongArrayChannelPut> LongArrayChannelPutPtr;
class LongArrayPut :
public std::tr1::enable_shared_from_this<LongArrayPut>
{
public:
POINTER_DEFINITIONS(LongArrayPut);
static LongArrayPutPtr create(
epics::pvData::String const & providerName,
epics::pvData::String const & channelName,
size_t arraySize = 100,
int iterBetweenCreateChannel = 0,
int iterBetweenCreateChannelPut = 0,
double delayTime = 0.0);
~LongArrayPut();
void destroy();
private:
LongArrayPutPtr getPtrSelf()
{
return shared_from_this();
}
LongArrayPut(
epics::pvData::String const & providerName,
epics::pvData::String const & channelName,
size_t arraySize,
int iterBetweenCreateChannel,
int iterBetweenCreateChannelPut,
double delayTime);
bool init();
epics::pvData::String providerName;
epics::pvData::String channelName;
size_t arraySize;
int iterBetweenCreateChannel;
int iterBetweenCreateChannelPut;
double delayTime;
LongArrayChannelPutPtr longArrayChannelPut;
};
}}
#endif /* LONGARRAYPUT_H */

View File

@ -54,7 +54,7 @@ class ElementQueue :
public:
POINTER_DEFINITIONS(ElementQueue);
virtual ~ElementQueue(){}
virtual bool dataChanged(bool firstMonitor) = 0;
virtual bool dataChanged() = 0;
protected:
ElementQueuePtr getPtrSelf()
{
@ -79,7 +79,7 @@ public:
virtual void destroy(){}
virtual Status start();
virtual Status stop();
virtual bool dataChanged(bool firstMonitor);
virtual bool dataChanged();
virtual MonitorElementPtr poll();
virtual void release(MonitorElementPtr const &monitorElement);
private:
@ -168,15 +168,13 @@ void MonitorLocal::destroy()
Status MonitorLocal::start()
{
Lock xx(mutex);
if(pvRecord->getTraceLevel()>0)
{
Lock xx(mutex);
if(pvRecord->getTraceLevel()>0)
{
cout << "MonitorLocal::start() " << endl;
}
if(isDestroyed) return wasDestroyedStatus;
firstMonitor = true;
cout << "MonitorLocal::start() " << endl;
}
if(isDestroyed) return wasDestroyedStatus;
firstMonitor = true;
return queue->start();
}
@ -229,7 +227,7 @@ void MonitorLocal::dataChanged()
{
Lock xx(mutex);
if(isDestroyed) return;
getMonitorEvent = queue->dataChanged(firstMonitor);
getMonitorEvent = queue->dataChanged();
firstMonitor = false;
}
if(getMonitorEvent) monitorRequester->monitorEvent(getPtrSelf());
@ -401,7 +399,7 @@ Status MultipleElementQueue::stop()
return Status::Ok;
}
bool MultipleElementQueue::dataChanged(bool firstMonitor)
bool MultipleElementQueue::dataChanged()
{
MonitorLocalPtr ml = monitorLocal.lock();
if(ml==NULL) return false;
@ -423,7 +421,6 @@ bool MultipleElementQueue::dataChanged(bool firstMonitor)
queueIsFull = true;
latestMonitorElement = monitorElement;
}
if(firstMonitor) changedBitSet->set(0);
PVStructurePtr pvStructure = monitorElement->pvStructurePtr;
ml->getPVCopy()->updateCopyFromBitSet(
pvStructure,changedBitSet);