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:
Andrew Johnson
2021-01-05 11:01:02 -08:00
committed by mdavidsaver
parent 2729903a10
commit 06c2fb579f
16 changed files with 213 additions and 833 deletions
+79
View File
@@ -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 &notificationPtr)
{
{
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);
}
}}}