diff --git a/src/db/dbNotify.c b/src/db/dbNotify.c index adc90ba43..fd787f887 100644 --- a/src/db/dbNotify.c +++ b/src/db/dbNotify.c @@ -156,7 +156,14 @@ STATIC void putNotifyPvt(putNotify *ppn,dbCommon *precord) dbScanUnlock(precord); (*ppn->userCallback)(ppn); epicsMutexMustLock(notifyLock); - if(ppn->requestCancel) epicsEventSignal(*ppn->pcancelEvent); + if(ppn->cancelWait) { + ppn->cancelWait = 0; + epicsEventSignal(ppn->cancelEvent); + } + if(ppn->userCallbackWait) { + ppn->userCallbackWait = 0; + epicsEventSignal(ppn->userCallbackEvent); + } ppn->state = putNotifyNotActive; epicsMutexUnlock(notifyLock); return; @@ -175,16 +182,16 @@ STATIC void notifyCallback(CALLBACK *pcallback) assert(ppn->state==putNotifyRestartCallbackRequested || ppn->state==putNotifyUserCallbackRequested); assert(ellCount(&ppn->waitList)==0); - if(ppn->requestCancel) { + if(ppn->cancelWait) { ppn->status = putNotifyCanceled; if(ppn->state==putNotifyRestartCallbackRequested) { restartCheck(precord->ppnr); } ppn->state = putNotifyNotActive; + ppn->cancelWait = 0; epicsMutexUnlock(notifyLock); dbScanUnlock(precord); - assert(ppn->pcancelEvent); - epicsEventSignal(*ppn->pcancelEvent); + epicsEventSignal(ppn->cancelEvent); return; } if(ppn->state==putNotifyRestartCallbackRequested) { @@ -198,11 +205,40 @@ STATIC void notifyCallback(CALLBACK *pcallback) dbScanUnlock(precord); (*ppn->userCallback)(ppn); epicsMutexMustLock(notifyLock); - if(ppn->requestCancel) epicsEventSignal(*ppn->pcancelEvent); + if(ppn->cancelWait) { + ppn->cancelWait = 0; + epicsEventSignal(ppn->cancelEvent); + } + if(ppn->userCallbackWait) { + ppn->userCallbackWait = 0; + epicsEventSignal(ppn->userCallbackEvent); + } ppn->state = putNotifyNotActive; epicsMutexUnlock(notifyLock); } +void epicsShareAPI dbPutNotifyInit(void) +{ + notifyLock = epicsMutexMustCreate(); +} + +void epicsShareAPI putNotifyInit(putNotify *ppn) +{ + memset(ppn,0,sizeof(putNotify)); + callbackSetCallback(notifyCallback,&ppn->callback); + callbackSetUser(ppn,&ppn->callback); + callbackSetPriority(priorityLow,&ppn->callback); + ellInit(&ppn->waitList); + ppn->cancelEvent = epicsEventCreate(epicsEventEmpty); + ppn->userCallbackEvent = epicsEventCreate(epicsEventEmpty); +} + +void epicsShareAPI putNotifyCleanup(putNotify *ppn) +{ + epicsEventDestroy(ppn->cancelEvent); + epicsEventDestroy(ppn->userCallbackEvent); +} + void epicsShareAPI dbPutNotify(putNotify *ppn) { dbCommon *precord = ppn->paddr->precord; @@ -232,11 +268,7 @@ void epicsShareAPI dbPutNotify(putNotify *ppn) epicsMutexMustLock(notifyLock); ppn->status = 0; ppn->state = putNotifyNotActive; - ppn->requestCancel = 0; - callbackSetCallback(notifyCallback,&ppn->callback); - callbackSetUser(ppn,&ppn->callback); - callbackSetPriority(priorityLow,&ppn->callback); - ellInit(&ppn->waitList); + ppn->cancelWait = ppn->userCallbackWait = 0; if(!precord->ppnr) {/* make sure record has a putNotifyRecord*/ precord->ppnr = dbCalloc(1,sizeof(putNotifyRecord)); precord->ppnr->precord = precord; @@ -245,11 +277,6 @@ void epicsShareAPI dbPutNotify(putNotify *ppn) putNotifyPvt(ppn,precord); } -void epicsShareAPI dbPutNotifyInit(void) -{ - notifyLock = epicsMutexMustCreate(); -} - void epicsShareAPI dbNotifyCancel(putNotify *ppn) { dbCommon *precord = ppn->paddr->precord; @@ -264,17 +291,12 @@ void epicsShareAPI dbNotifyCancel(putNotify *ppn) if(state==putNotifyUserCallbackRequested || state==putNotifyRestartCallbackRequested || state==putNotifyUserCallbackActive) { - epicsEventId eventId; - eventId = epicsEventCreate(epicsEventEmpty); - ppn->pcancelEvent = &eventId; - ppn->requestCancel = 1; + ppn->cancelWait = 1; epicsMutexUnlock(notifyLock); dbScanUnlock(precord); - epicsEventWait(eventId); + epicsEventWait(ppn->cancelEvent); epicsMutexMustLock(notifyLock); - ppn->pcancelEvent = 0; - ppn->requestCancel = 0; - epicsEventDestroy(eventId); + ppn->cancelWait = 0; epicsMutexUnlock(notifyLock); return; } @@ -406,6 +428,7 @@ long epicsShareAPI dbtpn(char *pname,char *pvalue) return(-1); } ppn = dbCalloc(1,sizeof(putNotify)); + putNotifyInit(ppn); ppn->paddr = pdbaddr; ppn->pbuffer = psavevalue; ppn->nRequest = 1; diff --git a/src/db/dbNotify.h b/src/db/dbNotify.h index a14faed8e..79b431635 100644 --- a/src/db/dbNotify.h +++ b/src/db/dbNotify.h @@ -49,14 +49,18 @@ typedef struct putNotify{ putNotifyStatus status; /*The following are private to dbNotify */ short state; - short requestCancel; CALLBACK callback; ELLLIST waitList; /*list of records for current putNotify*/ - epicsEventId *pcancelEvent; + short cancelWait; + short userCallbackWait; + epicsEventId cancelEvent; + epicsEventId userCallbackEvent; }putNotify; /* dbPutNotify and dbNotifyCancel are the routines called by user*/ /* The user is normally channel access client or server */ +epicsShareFunc void epicsShareAPI putNotifyInit(putNotify *pputNotify); +epicsShareFunc void epicsShareAPI putNotifyCleanup(putNotify *pputNotify); epicsShareFunc void epicsShareAPI dbPutNotify(putNotify *pputNotify); epicsShareFunc void epicsShareAPI dbNotifyCancel(putNotify *pputNotify); diff --git a/src/db/dbPutNotifyBlocker.cpp b/src/db/dbPutNotifyBlocker.cpp index c6fe4101d..014a0ef20 100644 --- a/src/db/dbPutNotifyBlocker.cpp +++ b/src/db/dbPutNotifyBlocker.cpp @@ -49,13 +49,14 @@ dbPutNotifyBlocker::dbPutNotifyBlocker ( epicsMutex & mutexIn ) : mutex ( mutexIn ), pNotify ( 0 ), maxValueSize ( sizeof ( this->dbrScalarValue ) ) { - memset ( & this->pn, '\0', sizeof ( this->pn ) ); + ::putNotifyInit(& this->pn); memset ( & this->dbrScalarValue, '\0', sizeof ( this->dbrScalarValue ) ); this->pn.pbuffer = & this->dbrScalarValue; } dbPutNotifyBlocker::~dbPutNotifyBlocker () { + ::putNotifyCleanup(& this->pn); } void dbPutNotifyBlocker::destructor ( epicsGuard < epicsMutex > & guard )