more work on monitor queues
This commit is contained in:
@ -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> 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> pwd
|
||||
/home/hg/pvDatabaseCPP-md
|
||||
mrk> 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> bin/linux-x86_64/longArrayMonitorMain -help
|
||||
longArrayMonitorMain channelName useQueue
|
||||
longArrayMonitorMain channelName queueSize waitTime
|
||||
default
|
||||
longArrayMonitorMain arrayPerformance false
|
||||
longArrayMonitorMain arrayPerformance 2 0.0
|
||||
mrk>
|
||||
</pre>
|
||||
<h3>Example output</h3>
|
||||
<pre>
|
||||
mrk> 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> 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>
|
||||
|
1831
documentation/pvDatabaseCPP_20131112.html
Normal file
1831
documentation/pvDatabaseCPP_20131112.html
Normal file
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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 ¤tElement)
|
||||
void MultipleElementQueue::release(MonitorElementPtr const ¤tElement)
|
||||
{
|
||||
if(queueIsFull) {
|
||||
MonitorElementPtr monitorElement = latestMonitorElement;
|
||||
@ -546,7 +551,7 @@ void RealQueue::release(MonitorElementPtr const ¤tElement)
|
||||
queueIsFull = false;
|
||||
latestMonitorElement.reset();
|
||||
}
|
||||
queue.releaseUsed(currentElement);
|
||||
queue->releaseUsed(currentElement);
|
||||
}
|
||||
|
||||
MonitorFactoryPtr getMonitorFactory()
|
||||
|
Reference in New Issue
Block a user