dbScan: add scanOnce3() w/ completion callback

This commit is contained in:
Michael Davidsaver
2015-01-05 16:26:47 -05:00
parent 7d50f62aed
commit 2ba2b90b06
2 changed files with 44 additions and 19 deletions
+39 -16
View File
@@ -26,10 +26,9 @@
#include "ellLib.h"
#include "epicsEvent.h"
#include "epicsExit.h"
#include "epicsInterrupt.h"
#include "epicsMutex.h"
#include "epicsPrint.h"
#include "epicsRingPointer.h"
#include "epicsRingBytes.h"
#include "epicsStdio.h"
#include "epicsStdlib.h"
#include "epicsString.h"
@@ -64,7 +63,7 @@ static volatile enum ctl scanCtl;
static int onceQueueSize = 1000;
static epicsEventId onceSem;
static epicsRingPointerId onceQ;
static epicsRingBytesId onceQ;
static epicsThreadId onceTaskId;
static void *exitOnce;
@@ -172,7 +171,7 @@ void scanShutdown(void)
deletePeriodic();
ioscanDestroy();
epicsRingPointerDelete(onceQ);
epicsRingBytesDelete(onceQ);
epicsEventDestroy(startStopEvent);
epicsEventDestroy(onceSem);
@@ -609,15 +608,27 @@ void scanIoSetComplete(IOSCANPVT piosh, io_scan_complete cb, void *arg)
piosh->arg = arg;
}
void scanOnce(struct dbCommon *precord)
int scanOnce(struct dbCommon *precord) {
return scanOnce3(precord, NULL, NULL);
}
typedef struct {
struct dbCommon *prec;
once_complete cb;
void *usr;
} onceEntry;
int scanOnce3(struct dbCommon *precord, once_complete cb, void *usr)
{
static int newOverflow = TRUE;
int lockKey;
onceEntry ent;
int pushOK;
lockKey = epicsInterruptLock();
pushOK = epicsRingPointerPush(onceQ, precord);
epicsInterruptUnlock(lockKey);
ent.prec = precord;
ent.cb = cb;
ent.usr = usr;
pushOK = epicsRingBytesPut(onceQ, (void*)&ent, sizeof(ent));
if (!pushOK) {
if (newOverflow) errlogPrintf("scanOnce: Ring buffer overflow\n");
@@ -626,6 +637,8 @@ void scanOnce(struct dbCommon *precord)
newOverflow = TRUE;
}
epicsEventSignal(onceSem);
return !pushOK;
}
static void onceTask(void *arg)
@@ -634,14 +647,24 @@ static void onceTask(void *arg)
epicsEventSignal(startStopEvent);
while (TRUE) {
void *precord;
epicsEventMustWait(onceSem);
while ((precord = epicsRingPointerPop(onceQ))) {
if (precord == &exitOnce) goto shutdown;
dbScanLock(precord);
dbProcess(precord);
dbScanUnlock(precord);
while(1) {
onceEntry ent;
int bytes = epicsRingBytesGet(onceQ, (void*)&ent, sizeof(ent));
if(bytes==0)
break;
if(bytes!=sizeof(ent)) {
errlogPrintf("onceTask: received incomplete %d of %u\n",
bytes, (unsigned)sizeof(ent));
continue; /* what to do? */
} else if (ent.prec == (void*)&exitOnce) goto shutdown;
dbScanLock(ent.prec);
dbProcess(ent.prec);
dbScanUnlock(ent.prec);
if(ent.cb)
ent.cb(ent.usr, ent.prec);
}
}
@@ -658,7 +681,7 @@ int scanOnceSetQueueSize(int size)
static void initOnce(void)
{
if ((onceQ = epicsRingPointerCreate(onceQueueSize)) == NULL) {
if ((onceQ = epicsRingBytesLockedCreate(sizeof(onceEntry)*onceQueueSize)) == NULL) {
cantProceed("initOnce: Ring buffer create failed\n");
}
onceSem = epicsEventMustCreate(epicsEventEmpty);
+5 -3
View File
@@ -39,10 +39,11 @@ struct ioscan_head;
typedef struct ioscan_head *IOSCANPVT;
typedef struct event_list *EVENTPVT;
typedef void (*io_scan_complete)(void *usr, IOSCANPVT, int prio);
struct dbCommon;
typedef void (*io_scan_complete)(void *usr, IOSCANPVT, int prio);
typedef void (*once_complete)(void *usr, struct dbCommon*);
epicsShareFunc long scanInit(void);
epicsShareFunc void scanRun(void);
epicsShareFunc void scanPause(void);
@@ -54,7 +55,8 @@ epicsShareFunc void post_event(int event) EPICS_DEPRECATED;
epicsShareFunc void scanAdd(struct dbCommon *);
epicsShareFunc void scanDelete(struct dbCommon *);
epicsShareFunc double scanPeriod(int scan);
epicsShareFunc void scanOnce(struct dbCommon *);
epicsShareFunc int scanOnce(struct dbCommon *);
epicsShareFunc int scanOnce3(struct dbCommon *, once_complete cb, void *usr);
epicsShareFunc int scanOnceSetQueueSize(int size);
/*print periodic lists*/