Replaced 4 notification threads with 2 notifierConveyors
Channel connection notifications are now handled by connectNotifier, getDone, putDone and monitor events handled by resultNotifier. A notifierConveyor is generic, and contains a queue and a thread. You pass a Notification pointing to a NotifierClient to a Conveyor's notifyClient() method, and the thread will call the client's notifyClient() method once it reaches the front of the queue. The conveyor threads stop when the caProvider is destroyed. The queue stores weak pointers, so queued notifications won't prevent client objects from being destroyed.
This commit is contained in:
committed by
mdavidsaver
parent
2729903a10
commit
06c2fb579f
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvAccessCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#include "notifierConveyor.h"
|
||||
|
||||
using epics::pvData::Lock;
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
namespace ca {
|
||||
|
||||
NotifierConveyor::~NotifierConveyor()
|
||||
{
|
||||
if (thread) {
|
||||
{
|
||||
Lock the(mutex);
|
||||
halt = true;
|
||||
}
|
||||
workToDo.signal();
|
||||
thread->exitWait();
|
||||
}
|
||||
}
|
||||
|
||||
void NotifierConveyor::start()
|
||||
{
|
||||
if (thread) return;
|
||||
thread = std::tr1::shared_ptr<epicsThread>(new epicsThread(*this,
|
||||
"caProvider::clientNotifier",
|
||||
epicsThreadGetStackSize(epicsThreadStackBig),
|
||||
epicsThreadPriorityLow));
|
||||
thread->start();
|
||||
}
|
||||
|
||||
void NotifierConveyor::notifyClient(
|
||||
NotificationPtr const ¬ificationPtr)
|
||||
{
|
||||
{
|
||||
Lock the(mutex);
|
||||
if (halt || notificationPtr->queued) return;
|
||||
notificationPtr->queued = true;
|
||||
workQueue.push(notificationPtr);
|
||||
}
|
||||
workToDo.signal();
|
||||
}
|
||||
|
||||
void NotifierConveyor::run()
|
||||
{
|
||||
bool stopping;
|
||||
do {
|
||||
workToDo.wait();
|
||||
Lock the(mutex);
|
||||
stopping = halt;
|
||||
bool work = !workQueue.empty();
|
||||
while (work)
|
||||
{
|
||||
NotificationWPtr notificationWPtr(workQueue.front());
|
||||
workQueue.pop();
|
||||
work = !workQueue.empty();
|
||||
NotificationPtr notification(notificationWPtr.lock());
|
||||
if (notification) {
|
||||
notification->queued = false;
|
||||
NotifierClientPtr client(notification->client.lock());
|
||||
if (client) {
|
||||
the.unlock();
|
||||
client->notifyClient();
|
||||
if (work) {
|
||||
the.lock();
|
||||
stopping = halt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (!stopping);
|
||||
}
|
||||
|
||||
}}}
|
||||
Reference in New Issue
Block a user