more work on monitor queues

This commit is contained in:
Marty Kraimer
2013-11-12 11:09:25 -05:00
parent 006859120e
commit 3039e1cdb0
8 changed files with 2045 additions and 171 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, 04-Sep-2013</h2>
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 12-Nov-2013</h2>
<dl>
<dt>Latest version:</dt>
<dd><a
@ -46,11 +46,11 @@
</dd>
<dt>This version:</dt>
<dd><a
href= "pvDatabaseCPP_20130904.html">pvDatabaseCPP20130904.html</a>
href= "pvDatabaseCPP_20131112.html">pvDatabaseCPP20131112.html</a>
</dd>
<dt>Previous version:</dt>
<dd><a
href= "pvDatabaseCPP_20130828.html">pvDatabaseCPP20130828.html</a>
href= "pvDatabaseCPP_20130904.html">pvDatabaseCPP20130904.html</a>
</dd>
<dt>Editors:</dt>
<dd>Marty Kraimer, BNL</dd>
@ -79,12 +79,27 @@ V4 control system programming environment:<br />
<h2 class="nocount">Status of this Document</h2>
<p>This is the 04-Sep-2013 version of of pvDatabaseCPP.</p>
<p><b>NOTE:</b>
This is built against pvDataCPP-md NOT against pvDataCPP.
To build you must also
checkout pvAccessCPP and build it against pvDataCPP-md.
<p>This is the 12-Nov-2013 version of of pvDatabaseCPP.</p>
</p>
<p><b>Problem</b> When arrayPerformance is run with a small array and queueSize 1 it fails.
For example:
<pre>
mrk&gt; bin/linux-x86_64/arrayPerformanceMain arrayPerformance 50 0.00 local 1 1 0.001
arrayPerformance arrayPerformance 50 0 local 1 1 0
...
first 2245711 last 2245711 sum 112285550 elements/sec 0.0452426million changed {1, 2} overrun {}
first 2246087 last 2246087 sum 112304350 elements/sec 0.0451597million changed {1, 2} overrun {}
arrayPerformance value 2246117 time 1 iterations/sec 336447 elements/sec 16.8223million
first 2246448 last 2246448 sum 112322400 elements/sec 0.0450084million changed {1, 2} overrun {}
first 2246827 last 2246827 sum 112341350 elements/sec 0.0446581million changed {1, 2} overrun {}
...
first 2282180 last 2282180 sum 114109000 elements/sec 0.0447461million changed {1, 2} overrun {}
first 2282540 last 2282540 sum 114127000 elements/sec 0.044695million changed {1, 2} overrun {}
Segmentation fault (core dumped)
</pre>
I do not know why and am stuck about what to do.
Looking at SingleElementQueue I do not see any problem.</p>
<p>All channel methods except channelRPC, which is implemented
by pvAccess, have been implemented.
This project is ready for alpha users.
@ -1597,31 +1612,31 @@ Each has support for <b>-help</b>.</p>
mrk&gt; pwd
/home/hg/pvDatabaseCPP-md
mrk&gt; bin/linux-x86_64/arrayPerformanceMain -help
arrayPerformanceMain recordName size delay providerName nMonitor useQueue
arrayPerformanceMain recordName size delay providerName nMonitor queueSize waitTime
default
arrayPerformance arrayPerformance 50000000 0.001 local 1 false
arrayPerformance arrayPerformance 50000000 0.01 local 1 2 0.0
mrk&gt; bin/linux-x86_64/longArrayMonitorMain -help
longArrayMonitorMain channelName useQueue
longArrayMonitorMain channelName queueSize waitTime
default
longArrayMonitorMain arrayPerformance false
longArrayMonitorMain arrayPerformance 2 0.0
mrk&gt;
</pre>
<h3>Example output</h3>
<pre>
mrk&gt; bin/linux-x86_64/arrayPerformanceMain
arrayPerformance arrayPerformance 50000000 0.01 local 1 false
arrayPerformance arrayPerformance 50000000 0.01 local 1 2 0.0
...
first 0 last 0 sum 0 elements/sec 529.007million changed {1, 2} overrun {}
first 1 last 1 sum 50000000 elements/sec 510.686million changed {1, 2} overrun {}
first 2 last 2 sum 100000000 elements/sec 520.114million changed {1, 2} overrun {}
first 3 last 3 sum 150000000 elements/sec 514.842million changed {1, 2} overrun {}
first 4 last 4 sum 200000000 elements/sec 507.642million changed {1, 2} overrun {}
first 5 last 5 sum 250000000 elements/sec 505.598million changed {1, 2} overrun {}
first 6 last 6 sum 300000000 elements/sec 517.081million changed {1, 2} overrun {}
first 7 last 7 sum 350000000 elements/sec 516.508million changed {1, 2} overrun {}
first 8 last 8 sum 400000000 elements/sec 513.711million changed {1, 2} overrun {}
first 9 last 9 sum 450000000 elements/sec 505.309million changed {1, 2} overrun {}
arrayPerformance value 11 time 1.08257 iterations/sec 10.161 elements/sec 508.049million
first 5 last 5 sum 250000000 elements/sec 51.5164million changed {0} overrun {}
arrayPerformance value 7 time 1.08532 iterations/sec 6.44973 elements/sec 322.487million
first 6 last 6 sum 300000000 elements/sec 493.414million changed {1, 2} overrun {}
first 7 last 7 sum 350000000 elements/sec 172.566million changed {1, 2} overrun {}
first 8 last 8 sum 400000000 elements/sec 515.064million changed {1, 2} overrun {}
first 9 last 9 sum 450000000 elements/sec 515.359million changed {1, 2} overrun {}
arrayPerformance value 11 time 1.10601 iterations/sec 3.6166 elements/sec 180.83million
first 10 last 10 sum 500000000 elements/sec 80.5679million changed {1, 2} overrun {}
first 11 last 11 sum 550000000 elements/sec 499.455million changed {1, 2} overrun {}
first 12 last 12 sum 600000000 elements/sec 504.324million changed {1, 2} overrun {}
first 13 last 13 sum 650000000 elements/sec 101.517million changed {1, 2} overrun {}
...
</pre>
<h3>arrayPerformance</h3>
@ -1677,10 +1692,12 @@ until the record is destroyed executing the following algorithm:</p>
</dd>
<dt>nMonitor</dt>
<dd>The number of longArrayMonitors to create.</dd>
<dt>useQueue</dt>
<dd>Should the longArrayMonitors use a queue?
This must be <b>true</b> or <b>false</b>.
<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.
@ -1690,7 +1707,8 @@ is a report.</p>
<p>The arguments for longArrayMonitorMain are:</p>
<dl>
<dt>channelName</dt>
<dt>useQueue</dt>
<dt>queueSize</dt>
<dt>waitTime</dt>
</dl>
<h3>Some results</h3>
<p>The results were from my laptop.
@ -1713,8 +1731,12 @@ The delay will be a millisecond.
There will be a single monitor and it will connect directly
to the local channelProvider, i. e. it will not use any network
connection.</p>
<p>The report shows that arrayPerformance can perform about 10 iterations per second
and is putting about 500million elements per second.
<p>The report shows that arrayPerformance can perform about 4 iterations per second
and is putting about 200million elements per second.
Since each element is an int64 this means about 1.6gigaBytes per second.
</p>
<p>If queueSize is set to 1 thereport shows that arrayPerformance can perform about 10 iterations
per second and is putting about 500million elements per second.
Since each element is an int64 this means about 4gigaBytes per second.
</p>
<p>When no monitors are requested and a remote longArrayMonitorMain is run:<p>
@ -1727,7 +1749,7 @@ mrk&gt; bin/linux-x86_64/longArrayMonitorMain
In addition the time between reports varies from just over 1 second to 1.3 seconds.
The reason is contention for transfering data between main memory and local caches.
The next section has an example that demonstrates what happens.
Note that if the array size is small enouggh to fix in the local cache then running longArrayMonitor
Note that if the array size is small enough to fix in the local cache then running longArrayMonitor
has almost no effect of arrayPerforance.
</p>
<h2>Vector Performance</h2>

File diff suppressed because it is too large Load Diff

View File

@ -44,10 +44,11 @@ int main(int argc,char *argv[])
double delay = .01;
String providerName("local");
size_t nMonitor = 1;
bool useQueue = false;
int queueSize = 2;
double waitTime = 0.0;
if(argc==2 && String(argv[1])==String("-help")) {
cout << "arrayPerformanceMain recordName size";
cout << " delay providerName nMonitor useQueue" << endl;
cout << " delay providerName nMonitor queueSize waitTime" << endl;
cout << "default" << endl;
cout << "arrayPerformance ";
cout << recordName << " ";
@ -55,7 +56,8 @@ int main(int argc,char *argv[])
cout << delay << " ";
cout << providerName << " ";
cout << nMonitor << " ";
cout << (useQueue ? "true" : "false") << endl;
cout << queueSize << " ";
cout << "0.0" << endl;
return 0;
}
if(argc>1) recordName = argv[1];
@ -63,14 +65,16 @@ int main(int argc,char *argv[])
if(argc>3) delay = atof(argv[3]);
if(argc>4) providerName = argv[4];
if(argc>5) nMonitor = strtoul(argv[5],0,0);
if(argc>6) useQueue = (argv[6]==String("true") ? true : false);
if(argc>6) queueSize = strtol(argv[6],0,0);
if(argc>7) waitTime = atof(argv[7]);
cout << "arrayPerformance ";
cout << recordName << " ";
cout << size << " ";
cout << delay << " ";
cout << providerName << " ";
cout << nMonitor << " ";
cout << (useQueue ? "true" : "false") << endl;
cout << queueSize << " ";
cout << waitTime << endl;
ClientFactory::start();
PVDatabasePtr master = PVDatabase::getMaster();
ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();
@ -88,8 +92,9 @@ int main(int argc,char *argv[])
std::vector<LongArrayMonitorPtr> longArrayMonitor(nMonitor);
for(size_t i=0; i<nMonitor; ++i) {
longArrayMonitor[i]
= LongArrayMonitor::create(providerName,recordName,useQueue);
= LongArrayMonitor::create(providerName,recordName,queueSize,waitTime);
}
epicsThreadSleep(1.0);
for(size_t i=0; i<nMonitor; ++i) longArrayMonitor[i]->start();
cout << "arrayPerformance\n";
string str;

View File

@ -38,21 +38,25 @@ using namespace epics::pvDatabase;
int main(int argc,char *argv[])
{
String channelName("arrayPerformance");
bool useQueue = false;
int queueSize = 2;
double waitTime = 0.0;
if(argc==2 && String(argv[1])==String("-help")) {
cout << "longArrayMonitorMain channelName useQueue" << endl;
cout << "longArrayMonitorMain channelName queueSize waitTime" << endl;
cout << "default" << endl;
cout << "longArrayMonitorMain " << channelName << " ";
cout << (useQueue ? "true" : "false") << endl;
cout << queueSize << " ";
cout << "0.0" << endl;
return 0;
}
ClientFactory::start();
if(argc>1) channelName = argv[1];
if(argc>2) useQueue = (String(argv[2])==String("true") ? true : false);
if(argc>2) queueSize = strtol(argv[2],0,0);
if(argc>3) waitTime = atof(argv[3]);
cout << "longArrayMonitorMain " << channelName << " ";
cout << (useQueue ? "true" : "false") << endl;
cout << queueSize << " ";
cout << waitTime << endl;
LongArrayMonitorPtr longArrayMonitor
= LongArrayMonitor::create("pvAccess",channelName,useQueue);
= LongArrayMonitor::create("pvAccess",channelName,queueSize,waitTime);
longArrayMonitor->start();
cout << "longArrayMonitor\n";
string str;

View File

@ -67,8 +67,9 @@ class LAMMonitorRequester :
public epicsThreadRunable
{
public:
LAMMonitorRequester(LongArrayMonitorPtr const &longArrayMonitor)
LAMMonitorRequester(LongArrayMonitorPtr const &longArrayMonitor,double waitTime)
: longArrayMonitor(longArrayMonitor),
waitTime(waitTime),
isDestroyed(false),
runReturned(false),
threadName("longArrayMonitor")
@ -87,6 +88,7 @@ public:
private:
void handleMonitor();
LongArrayMonitorPtr longArrayMonitor;
double waitTime;
bool isDestroyed;
bool runReturned;
epics::pvData::String threadName;
@ -173,6 +175,7 @@ void LAMMonitorRequester::run()
if(monitorElement!=NULL) pvStructure = monitorElement->pvStructurePtr;
}
if(monitorElement==NULL) break;
if(waitTime>0.0) epicsThreadSleep(waitTime);
pvTimeStamp.attach(pvStructure->getSubField("timeStamp"));
pvTimeStamp.get(timeStamp);
pvValue = dynamic_pointer_cast<PVLongArray>(pvStructure->getSubField("value"));
@ -219,10 +222,11 @@ void LAMMonitorRequester::unlisten(MonitorPtr const & monitor)
LongArrayMonitorPtr LongArrayMonitor::create(
String const &providerName,
String const & channelName,
bool useQueue)
int queueSize,
double waitTime)
{
LongArrayMonitorPtr longArrayMonitor(new LongArrayMonitor());
if(!longArrayMonitor->init(providerName,channelName,useQueue)) longArrayMonitor.reset();
if(!longArrayMonitor->init(providerName,channelName,queueSize,waitTime)) longArrayMonitor.reset();
return longArrayMonitor;
}
@ -233,10 +237,11 @@ LongArrayMonitor::~LongArrayMonitor() {}
bool LongArrayMonitor::init(
String const &providerName,
String const &channelName,
bool useQueue)
int queueSize,
double waitTime)
{
channelRequester = LAMChannelRequesterPtr(new LAMChannelRequester(getPtrSelf()));
monitorRequester = LAMMonitorRequesterPtr(new LAMMonitorRequester(getPtrSelf()));
monitorRequester = LAMMonitorRequesterPtr(new LAMMonitorRequester(getPtrSelf(),waitTime));
monitorRequester->init();
ChannelProvider::shared_pointer channelProvider = getChannelAccess()->getProvider(providerName);
if(channelProvider==NULL) {
@ -246,10 +251,10 @@ bool LongArrayMonitor::init(
channel = channelProvider->createChannel(channelName,channelRequester,0);
event.wait();
if(!status.isOK()) return false;
String queueSize("0");
if(useQueue) queueSize="2";
String request("record[queueSize=");
request += queueSize;
char buff[20];
sprintf(buff,"%d",queueSize);
request += buff;
request += "]field(value,timeStamp,alarm)";
CreateRequest::shared_pointer createRequest = CreateRequest::create();
PVStructurePtr pvRequest = createRequest->createRequest(request);

View File

@ -38,7 +38,8 @@ public:
static LongArrayMonitorPtr create(
epics::pvData::String const & providerName,
epics::pvData::String const & channelName,
bool useQueue = false);
int queueSize = 1,
double waitTime = 0.0);
~LongArrayMonitor();
void start();
void stop();
@ -48,7 +49,8 @@ private:
bool init(
epics::pvData::String const & providerName,
epics::pvData::String const & channelName,
bool useQueue);
int queueSize,
double waitTime);
LongArrayMonitorPtr getPtrSelf()
{
return shared_from_this();

View File

@ -18,8 +18,8 @@ INC += pvCopy.h
INC += monitorAlgorithm.h
LIBSRCS += channelProviderLocal.cpp
LIBSRCS += pvCopy.cpp
LIBSRCS += channelLocal.cpp
LIBSRCS += monitorFactory.cpp
LIBSRCS += channelLocal.cpp
SRC_DIRS += $(DATABASE)/V3IOC
DBD += PVAServerRegister.dbd

View File

@ -35,12 +35,12 @@ static ConvertPtr convert = getConvert();
//class MonitorFieldNode;
//typedef std::tr1::shared_ptr<MonitorFieldNode> MonitorFieldNodePtr;
class MonitorQueue;
typedef std::tr1::shared_ptr<MonitorQueue> MonitorQueuePtr;
class NOQueue;
typedef std::tr1::shared_ptr<NOQueue> NOQueuePtr;
class RealQueue;
typedef std::tr1::shared_ptr<RealQueue> RealQueuePtr;
class ElementQueue;
typedef std::tr1::shared_ptr<ElementQueue> ElementQueuePtr;
class SingleElementQueue;
typedef std::tr1::shared_ptr<SingleElementQueue> SingleElementQueuePtr;
class MultipleElementQueue;
typedef std::tr1::shared_ptr<MultipleElementQueue> MultipleElementQueuePtr;
//class MonitorFieldNode
//{
@ -49,36 +49,34 @@ typedef std::tr1::shared_ptr<RealQueue> RealQueuePtr;
// size_t bitOffset; // pv pvCopy
//};
class MonitorQueue :
public std::tr1::enable_shared_from_this<MonitorQueue>
class ElementQueue :
public Monitor,
public std::tr1::enable_shared_from_this<ElementQueue>
{
public:
POINTER_DEFINITIONS(MonitorQueue);
virtual ~MonitorQueue(){}
virtual Status start() = 0;
virtual void stop() = 0;
virtual bool dataChanged() = 0;
virtual MonitorElementPtr poll() = 0;
virtual void release(MonitorElementPtr const &monitorElement) = 0;
POINTER_DEFINITIONS(ElementQueue);
virtual ~ElementQueue(){}
virtual bool dataChanged(bool firstMonitor) = 0;
protected:
MonitorQueuePtr getPtrSelf()
ElementQueuePtr getPtrSelf()
{
return shared_from_this();
}
};
class NOQueue :
public MonitorQueue
class SingleElementQueue :
public ElementQueue
{
public:
POINTER_DEFINITIONS(NOQueue);
virtual ~NOQueue(){}
NOQueue(
POINTER_DEFINITIONS(SingleElementQueue);
virtual ~SingleElementQueue(){}
SingleElementQueue(
MonitorLocalPtr const &monitorLocal);
virtual void destroy(){}
virtual Status start();
virtual void stop();
virtual bool dataChanged();
virtual Status stop();
virtual bool dataChanged(bool firstMonitor);
virtual MonitorElementPtr poll();
virtual void release(MonitorElementPtr const &monitorElement);
private:
@ -88,26 +86,32 @@ private:
bool gotMonitor;
BitSetPtr changedBitSet;
BitSetPtr overrunBitSet;
BitSetPtr dataChangedBitSet;
BitSetPtr dataOverrunBitSet;
};
class RealQueue :
public MonitorQueue
typedef Queue<MonitorElement> MonitorElementQueue;
typedef std::tr1::shared_ptr<MonitorElementQueue> MonitorElementQueuePtr;
class MultipleElementQueue :
public ElementQueue
{
public:
POINTER_DEFINITIONS(RealQueue);
virtual ~RealQueue(){}
RealQueue(
POINTER_DEFINITIONS(MultipleElementQueue);
virtual ~MultipleElementQueue(){}
MultipleElementQueue(
MonitorLocalPtr const &monitorLocal,
std::vector<MonitorElementPtr> &monitorElementArray,
MonitorElementQueuePtr const &queue,
size_t nfields);
virtual void destroy(){}
virtual Status start();
virtual void stop();
virtual bool dataChanged();
virtual Status stop();
virtual bool dataChanged(bool firstMonitor);
virtual MonitorElementPtr poll();
virtual void release(MonitorElementPtr const &monitorElement);
private:
std::tr1::weak_ptr<MonitorLocal> monitorLocal;
Queue<MonitorElement> queue;
MonitorElementQueuePtr queue;
BitSetPtr changedBitSet;
BitSetPtr overrunBitSet;
MonitorElementPtr latestMonitorElement;
@ -146,7 +150,7 @@ private:
bool isDestroyed;
bool firstMonitor;
PVCopyPtr pvCopy;
MonitorQueuePtr queue;
ElementQueuePtr queue;
PVCopyMonitorPtr pvCopyMonitor;
Mutex mutex;
};
@ -205,55 +209,41 @@ Status MonitorLocal::start()
Status MonitorLocal::stop()
{
if(pvRecord->getTraceLevel()>0)
{
cout << "MonitorLocal::stop() " << endl;
}
pvCopyMonitor->stopMonitoring();
queue->stop();
{
Lock xx(mutex);
if(pvRecord->getTraceLevel()>0){
cout << "MonitorLocal::stop() " << endl;
}
if(!isDestroyed) queue->stop();
}
return Status::Ok;
}
MonitorElementPtr MonitorLocal::poll()
{
pvRecord->lock();
try {
Lock xx(mutex);
if(pvRecord->getTraceLevel()>1)
{
cout << "MonitorLocal::poll() " << endl;
}
if(isDestroyed) {
pvRecord->unlock();
return NULLMonitorElement;
}
MonitorElementPtr element = queue->poll();
pvRecord->unlock();
return element;
} catch(...) {
pvRecord->unlock();
throw;
Lock xx(mutex);
if(pvRecord->getTraceLevel()>1)
{
cout << "MonitorLocal::poll() " << endl;
}
if(isDestroyed) {
return NULLMonitorElement;
}
return queue->poll();
}
void MonitorLocal::release(MonitorElementPtr const & monitorElement)
{
pvRecord->lock();
try {
Lock xx(mutex);
if(pvRecord->getTraceLevel()>1)
{
cout << "MonitorLocal::release() " << endl;
}
if(isDestroyed) {
return;
}
queue->release(monitorElement);
pvRecord->unlock();
} catch(...) {
pvRecord->unlock();
throw;
Lock xx(mutex);
if(pvRecord->getTraceLevel()>1)
{
cout << "MonitorLocal::release() " << endl;
}
if(isDestroyed) {
return;
}
queue->release(monitorElement);
}
void MonitorLocal::dataChanged()
@ -262,17 +252,14 @@ void MonitorLocal::dataChanged()
{
cout << "MonitorLocal::dataChanged() " "firstMonitor " << firstMonitor << endl;
}
Lock xx(mutex);
if(isDestroyed) return;
if(firstMonitor) {
queue->dataChanged();
firstMonitor = false;
monitorRequester->monitorEvent(getPtrSelf());
return;
}
if(queue->dataChanged()) {
monitorRequester->monitorEvent(getPtrSelf());
bool getMonitorEvent = false;
{
Lock xx(mutex);
if(isDestroyed) return;
getMonitorEvent = queue->dataChanged(firstMonitor);
firstMonitor = false;
}
if(getMonitorEvent) monitorRequester->monitorEvent(getPtrSelf());
}
void MonitorLocal::unlisten()
@ -326,18 +313,23 @@ bool MonitorLocal::init(PVStructurePtr const & pvRequest)
pvCopyMonitor = pvCopy->createPVCopyMonitor(getPtrSelf());
// MARTY MUST IMPLEMENT periodic
if(queueSize<2) {
queue = NOQueuePtr(new NOQueue(getPtrSelf()));
queue = SingleElementQueuePtr(new SingleElementQueue(getPtrSelf()));
} else {
std::vector<MonitorElementPtr> monitorElementArray;
monitorElementArray.reserve(queueSize);
size_t nfields = 0;
for(size_t i=0; i<queueSize; i++) {
PVStructurePtr pvStructure = pvCopy->createPVStructure();
if(nfields==0) nfields = pvStructure->getNumberFields();
MonitorElementPtr monitorElement(
new MonitorElement(pvStructure));
monitorElementArray.push_back(monitorElement);
}
size_t nfields = monitorElementArray[0]->pvStructurePtr->getNumberFields();
queue = RealQueuePtr(new RealQueue(getPtrSelf(),monitorElementArray,nfields));
MonitorElementQueuePtr elementQueue(new MonitorElementQueue(monitorElementArray));
queue = MultipleElementQueuePtr(new MultipleElementQueue(
getPtrSelf(),
elementQueue,
nfields));
}
// MARTY MUST IMPLEMENT algorithm
monitorRequester->monitorConnect(
@ -410,22 +402,26 @@ MonitorAlgorithmCreatePtr MonitorFactory::getMonitorAlgorithmCreate(
return nullMonitorAlgorithmCreate;
}
NOQueue::NOQueue(
SingleElementQueue::SingleElementQueue(
MonitorLocalPtr const &monitorLocal)
: monitorLocal(monitorLocal),
pvCopyStructure(monitorLocal->getPVCopy()->createPVStructure()),
monitorElement(new MonitorElement(pvCopyStructure)),
gotMonitor(false),
changedBitSet(new BitSet(pvCopyStructure->getNumberFields())),
overrunBitSet(new BitSet(pvCopyStructure->getNumberFields()))
overrunBitSet(new BitSet(pvCopyStructure->getNumberFields())),
dataChangedBitSet(new BitSet(pvCopyStructure->getNumberFields())),
dataOverrunBitSet(new BitSet(pvCopyStructure->getNumberFields()))
{
}
Status NOQueue::start()
Status SingleElementQueue::start()
{
gotMonitor = true;
changedBitSet->clear();
overrunBitSet->clear();
dataChangedBitSet->clear();
dataOverrunBitSet->clear();
MonitorLocalPtr ml = monitorLocal.lock();
if(ml==NULL) return wasDestroyedStatus;
ml->getPVCopyMonitor()->startMonitoring(
@ -434,54 +430,61 @@ Status NOQueue::start()
return Status::Ok;
}
void NOQueue::stop()
Status SingleElementQueue::stop()
{
return Status::Ok;
}
bool NOQueue::dataChanged()
bool SingleElementQueue::dataChanged(bool firstMonitor)
{
MonitorLocalPtr ml = monitorLocal.lock();
if(ml==NULL) return false;
if(firstMonitor) changedBitSet->set(0);
ml->getPVCopy()->updateCopyFromBitSet(pvCopyStructure,changedBitSet);
(*dataChangedBitSet) |= (*changedBitSet);
(*dataOverrunBitSet) |= (*overrunBitSet);
changedBitSet->clear();
overrunBitSet->clear();
gotMonitor = true;
return true;
}
MonitorElementPtr NOQueue::poll()
MonitorElementPtr SingleElementQueue::poll()
{
if(!gotMonitor) return NULLMonitorElement;
MonitorLocalPtr ml = monitorLocal.lock();
if(ml==NULL) return NULLMonitorElement;
ml->getPVCopy()->updateCopyFromBitSet(
pvCopyStructure, changedBitSet);
BitSetUtil::compress(changedBitSet,pvCopyStructure);
BitSetUtil::compress(overrunBitSet,pvCopyStructure);
monitorElement->changedBitSet->clear();
monitorElement->overrunBitSet->clear();
(*monitorElement->changedBitSet) |= (*changedBitSet);
(*monitorElement->overrunBitSet) |= (*overrunBitSet);
changedBitSet->clear();
overrunBitSet->clear();
if(!gotMonitor) return NULLMonitorElement;
gotMonitor = false;
convert->copyStructure(pvCopyStructure,monitorElement->pvStructurePtr);
BitSetUtil::compress(dataChangedBitSet,pvCopyStructure);
BitSetUtil::compress(dataOverrunBitSet,pvCopyStructure);
(*monitorElement->changedBitSet) = (*dataChangedBitSet);
(*monitorElement->overrunBitSet) = (*dataOverrunBitSet);
dataChangedBitSet->clear();
dataOverrunBitSet->clear();
return monitorElement;
}
void NOQueue::release(MonitorElementPtr const &monitorElement)
void SingleElementQueue::release(MonitorElementPtr const &monitorElement)
{
gotMonitor = false;
}
RealQueue::RealQueue(
MultipleElementQueue::MultipleElementQueue(
MonitorLocalPtr const &monitorLocal,
std::vector<MonitorElementPtr> &monitorElementArray,
MonitorElementQueuePtr const &queue,
size_t nfields)
: monitorLocal(monitorLocal),
queue(monitorElementArray),
queue(queue),
changedBitSet(new BitSet(nfields)),
overrunBitSet(new BitSet(nfields)),
queueIsFull(false)
{
}
Status RealQueue::start()
Status MultipleElementQueue::start()
{
queue.clear();
queue->clear();
queueIsFull = false;
changedBitSet->clear();
overrunBitSet->clear();
MonitorLocalPtr ml = monitorLocal.lock();
@ -490,11 +493,12 @@ Status RealQueue::start()
return Status::Ok;
}
void RealQueue::stop()
Status MultipleElementQueue::stop()
{
return Status::Ok;
}
bool RealQueue::dataChanged()
bool MultipleElementQueue::dataChanged(bool firstMonitor)
{
MonitorLocalPtr ml = monitorLocal.lock();
if(ml==NULL) return false;
@ -508,14 +512,15 @@ bool RealQueue::dataChanged()
overrunBitSet->clear();
return false;
}
MonitorElementPtr monitorElement = queue.getFree();
MonitorElementPtr monitorElement = queue->getFree();
if(monitorElement==NULL) {
throw std::logic_error(String("RealQueue::dataChanged() logic error"));
throw std::logic_error(String("MultipleElementQueue::dataChanged() logic error"));
}
if(queue.getNumberFree()==0){
if(queue->getNumberFree()==0){
queueIsFull = true;
latestMonitorElement = monitorElement;
}
if(firstMonitor) changedBitSet->set(0);
PVStructurePtr pvStructure = monitorElement->pvStructurePtr;
ml->getPVCopy()->updateCopyFromBitSet(
pvStructure,changedBitSet);
@ -527,16 +532,16 @@ bool RealQueue::dataChanged()
(*monitorElement->overrunBitSet)|=(*overrunBitSet);
changedBitSet->clear();
overrunBitSet->clear();
queue.setUsed(monitorElement);
queue->setUsed(monitorElement);
return true;
}
MonitorElementPtr RealQueue::poll()
MonitorElementPtr MultipleElementQueue::poll()
{
return queue.getUsed();
return queue->getUsed();
}
void RealQueue::release(MonitorElementPtr const &currentElement)
void MultipleElementQueue::release(MonitorElementPtr const &currentElement)
{
if(queueIsFull) {
MonitorElementPtr monitorElement = latestMonitorElement;
@ -546,7 +551,7 @@ void RealQueue::release(MonitorElementPtr const &currentElement)
queueIsFull = false;
latestMonitorElement.reset();
}
queue.releaseUsed(currentElement);
queue->releaseUsed(currentElement);
}
MonitorFactoryPtr getMonitorFactory()