new approach to handle named events efficiently

This commit is contained in:
Dirk Zimoch
2010-10-27 21:56:12 +02:00
parent 0e818f6127
commit 0d8725857b
7 changed files with 136 additions and 89 deletions

View File

@@ -101,14 +101,13 @@ static char *priorityName[NUM_CALLBACK_PRIORITIES] = {
/* EVENT */
typedef struct event_scan_list {
CALLBACK callback;
scan_list scan_list;
struct event_scan_list *next;
typedef struct event_list {
CALLBACK callback[NUM_CALLBACK_PRIORITIES];
scan_list scan_list[NUM_CALLBACK_PRIORITIES];
struct event_list *next;
char event_name[MAX_STRING_SIZE];
} event_scan_list;
static event_scan_list *pevent_list[NUM_CALLBACK_PRIORITIES];
static epicsMutexId event_list_lock[NUM_CALLBACK_PRIORITIES];
} event_list;
static event_list * volatile pevent_list[256];
/* IO_EVENT*/
@@ -206,47 +205,24 @@ void scanAdd(struct dbCommon *precord)
recGblRecordError(-1, (void *)precord,
"scanAdd detected illegal SCAN value");
} else if (scan == menuScanEvent) {
char* evnt;
char* eventname;
int prio;
event_scan_list *pesl;
event_list *pel;
evnt = precord->evnt;
if (*evnt == 0) {
recGblRecordError(S_db_badField, (void *)precord,
"scanAdd: illegal empty EVNT value");
/*precord->scan = menuScanPassive;*/
return;
}
if (strlen(evnt) >= MAX_STRING_SIZE) {
eventname = precord->evnt;
if (strlen(eventname) >= MAX_STRING_SIZE) {
recGblRecordError(S_db_badField, (void *)precord,
"scanAdd: too long EVNT value");
/*precord->scan = menuScanPassive;*/
return;
}
prio = precord->prio;
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
recGblRecordError(-1, (void *)precord,
"scanAdd: illegal prio field");
/*precord->scan = menuScanPassive;*/
return;
}
epicsMutexMustLock(event_list_lock[prio]);
for (pesl = pevent_list[prio]; pesl; pesl=pesl->next) {
if (strcmp(pesl->event_name, evnt) == 0) break;
}
if (pesl == NULL) {
pesl = dbCalloc(1, sizeof(event_scan_list));
strcpy(pesl->event_name, evnt);
pesl->scan_list.lock = epicsMutexMustCreate();
callbackSetCallback(eventCallback, &pesl->callback);
callbackSetPriority(prio, &pesl->callback);
callbackSetUser(pesl, &pesl->callback);
ellInit(&pesl->scan_list.list);
pesl->next=pevent_list[prio];
pevent_list[prio]=pesl;
}
epicsMutexUnlock(event_list_lock[prio]);
addToList(precord, &pesl->scan_list);
pel = eventNameToHandle(eventname);
if (pel) addToList(precord, &pel->scan_list[prio]);
} else if (scan == menuScanI_O_Intr) {
io_scan_list *piosl = NULL;
int prio;
@@ -301,25 +277,25 @@ void scanDelete(struct dbCommon *precord)
recGblRecordError(-1, (void *)precord,
"scanDelete detected illegal SCAN value");
} else if (scan == menuScanEvent) {
char* evnt;
char* eventname;
int prio;
event_scan_list *pesl;
event_list *pel;
scan_list *psl = 0;
evnt = precord->evnt;
eventname = precord->evnt;
prio = precord->prio;
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
recGblRecordError(-1, (void *)precord,
"scanDelete detected illegal PRIO field");
return;
}
epicsMutexMustLock(event_list_lock[prio]);
pesl = pevent_list[prio];
epicsMutexUnlock(event_list_lock[prio]);
for (; pesl; pesl=pesl->next) {
if (strcmp(pesl->event_name, evnt) == 0) break;
do /* multitheading: make sure pel is consistent */
pel = pevent_list[0];
while (pel != pevent_list[0]);
for (; pel; pel=pel->next) {
if (strcmp(pel->event_name, eventname) == 0) break;
}
if (pesl && (psl = &pesl->scan_list))
if (pel && (psl = &pel->scan_list[prio]))
deleteFromList(precord, psl);
} else if (scan == menuScanI_O_Intr) {
io_scan_list *piosl=NULL;
@@ -380,21 +356,21 @@ int scanppl(double period) /* print periodic list */
return 0;
}
int scanpel(char* evnt) /* print event list */
int scanpel(char* eventname) /* print event list */
{
char message[80];
int prio;
event_scan_list *pesl;
event_list *pel;
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
epicsMutexMustLock(event_list_lock[prio]);
pesl = pevent_list[prio];
epicsMutexUnlock(event_list_lock[prio]);
for (; pesl; pesl = pesl->next) {
if (!evnt || strcmp(pesl->event_name, evnt) == 0) {
if (ellCount(&pesl->scan_list.list) == 0) continue;
sprintf(message, "Event \"%s\" Priority %s", pesl->event_name, priorityName[prio]);
printList(&pesl->scan_list, message);
do /* multitheading: make sure pel is consistent */
pel = pevent_list[0];
while (pel != pevent_list[0]);
for (; pel; pel = pel->next) {
if (!eventname || strcmp(pel->event_name, eventname) == 0) {
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
if (ellCount(&pel->scan_list[prio].list) == 0) continue;
sprintf(message, "Event \"%s\" Priority %s", pel->event_name, priorityName[prio]);
printList(&pel->scan_list[prio], message);
}
}
}
@@ -421,48 +397,73 @@ int scanpiol(void) /* print io_event list */
static void eventCallback(CALLBACK *pcallback)
{
event_scan_list *pesl;
scan_list *psl;
callbackGetUser(pesl, pcallback);
scanList(&pesl->scan_list);
callbackGetUser(psl, pcallback);
scanList(psl);
}
static void initEvent(void)
{
int prio;
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
pevent_list[prio] = NULL;
event_list_lock[prio] = epicsMutexMustCreate();
}
}
void post_named_event(char* evnt)
event_list *eventNameToHandle(char *eventname)
{
int prio;
event_scan_list *pesl;
event_list *pel;
static epicsMutexId lock = NULL;
if (scanCtl != ctlRun) return;
if (!evnt || *evnt == 0) return;
for (prio=0; prio<NUM_CALLBACK_PRIORITIES; prio++) {
epicsMutexMustLock(event_list_lock[prio]);
pesl = pevent_list[prio];
epicsMutexUnlock(event_list_lock[prio]);
for (; pesl; pesl=pesl->next) {
if (strcmp(pesl->event_name, evnt) == 0) {
if (ellCount(&pesl->scan_list.list) >0)
callbackRequest((void *)pesl);
}
if (!lock) lock = epicsMutexMustCreate();
if (!eventname || eventname[0] == 0) return NULL;
epicsMutexMustLock(lock);
for (pel = pevent_list[0]; pel; pel=pel->next) {
if (strcmp(pel->event_name, eventname) == 0) break;
}
if (pel == NULL) {
pel = dbCalloc(1, sizeof(event_list));
strcpy(pel->event_name, eventname);
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
callbackSetUser(&pel->scan_list[prio], &pel->callback[prio]);
callbackSetPriority(prio, &pel->callback[prio]);
callbackSetCallback(eventCallback, &pel->callback[prio]);
pel->scan_list[prio].lock = epicsMutexMustCreate();
ellInit(&pel->scan_list[prio].list);
}
pel->next=pevent_list[0];
pevent_list[0]=pel;
{ /* backward compatibility */
char* p;
long e = strtol(eventname, &p, 0);
if (*p == 0 && e > 0 && e <= 255)
pevent_list[e]=pel;
}
}
epicsMutexUnlock(lock);
return pel;
}
void postEvent(event_list *pel)
{
int prio;
if (scanCtl != ctlRun) return;
if (!pel) return;
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
if (ellCount(&pel->scan_list[prio].list) >0)
callbackRequest(&pel->callback[prio]);
}
}
/* backward compatibility */
void post_event(int event)
{
char event_name[10];
event_list* pel;
sprintf(event_name, "%i", event);
post_named_event(event_name);
if (event <= 0 || event > 255) return;
do { /* multitheading: make sure pel is consistent */
pel = pevent_list[event];
} while (pel != pevent_list[event]);
postEvent(pel);
}
void scanIoInit(IOSCANPVT *ppioscanpvt)

View File

@@ -37,6 +37,7 @@ extern "C" {
struct io_scan_list;
typedef struct io_scan_list *IOSCANPVT;
typedef struct event_list *EVENTPVT;
struct dbCommon;
@@ -44,8 +45,9 @@ epicsShareFunc long scanInit(void);
epicsShareFunc void scanRun(void);
epicsShareFunc void scanPause(void);
epicsShareFunc EVENTPVT eventNameToHandle(char* event);
epicsShareFunc void postEvent(EVENTPVT epvt);
epicsShareFunc void post_event(int event) EPICS_DEPRECATED;
epicsShareFunc void post_named_event(char* event);
epicsShareFunc void scanAdd(struct dbCommon *);
epicsShareFunc void scanDelete(struct dbCommon *);
epicsShareFunc double scanPeriod(int scan);

View File

@@ -69,9 +69,15 @@ static long init_record(eventRecord *prec)
static long read_event(eventRecord *prec)
{
long status;
char newEvent[MAX_STRING_SIZE];
status = dbGetLink(&prec->inp, DBR_STRING, prec->val, 0, 0);
if (prec->inp.type == CONSTANT) return 0;
status = dbGetLinkValue(&prec->inp, DBR_STRING, newEvent, 0, 0);
if (!status) {
if (strcmp(newEvent, prec->val) != 0) {
strcpy(prec->val, newEvent);
prec->epvt = eventNameToHandle(prec->val);
}
prec->udf = FALSE;
if (prec->tsel.type == CONSTANT &&
prec->tse == epicsTimeEventDeviceTime)

View File

@@ -197,6 +197,8 @@ static long init_record(calcoutRecord *prec, int pass)
callbackSetUser(prec, &prpvt->checkLinkCb);
prpvt->cbScheduled = 0;
prec->epvt = eventNameToHandle(prec->oevt);
if (pcalcoutDSET->init_record) pcalcoutDSET->init_record(prec);
prec->pval = prec->val;
prec->mlst = prec->val;
@@ -357,6 +359,9 @@ static long special(DBADDR *paddr, int after)
}
db_post_events(prec, plinkValid, DBE_VALUE);
return 0;
case(calcoutRecordOEVT):
prec->epvt = eventNameToHandle(prec->oevt);
return 0;
default:
recGblDbaddrError(S_db_badChoice, paddr, "calc: special");
return(S_db_badChoice);
@@ -540,12 +545,12 @@ static void execOutput(calcoutRecord *prec)
/* Output the value */
status = writeValue(prec);
/* post output event if set */
post_named_event(prec->oevt);
if (prec->epvt) postEvent(prec->epvt);
} else switch (prec->ivoa) {
case menuIvoaContinue_normally:
status = writeValue(prec);
/* post output event if set */
post_named_event(prec->oevt);
if (prec->epvt) postEvent(prec->epvt);
break;
case menuIvoaDon_t_drive_outputs:
break;
@@ -553,7 +558,7 @@ static void execOutput(calcoutRecord *prec)
prec->oval = prec->ivov;
status = writeValue(prec);
/* post output event if set */
post_named_event(prec->oevt);
if (prec->epvt) postEvent(prec->epvt);
break;
default:
status = -1;

View File

@@ -258,9 +258,17 @@ recordtype(calcout) {
field(OEVT,DBF_STRING) {
prompt("Event To Issue")
promptgroup(GUI_CLOCK)
special(SPC_MOD)
asl(ASL0)
size(40)
}
%#include "dbScan.h"
field(EPVT, DBF_NOACCESS) {
prompt("Event private")
special(SPC_NOMOD)
interest(4)
extra("EVENTPVT epvt")
}
field(IVOA,DBF_MENU) {
prompt("INVALID output action")
promptgroup(GUI_OUTPUT)

View File

@@ -32,6 +32,7 @@
#include "errMdef.h"
#include "recSup.h"
#include "recGbl.h"
#include "special.h"
#include "menuYesNo.h"
#define GEN_SIZE_OFFSET
#include "eventRecord.h"
@@ -43,7 +44,7 @@
#define initialize NULL
static long init_record(eventRecord *, int);
static long process(eventRecord *);
#define special NULL
static long special(DBADDR *, int);
static long get_value(eventRecord *, struct valueDes *);
#define cvt_dbaddr NULL
#define get_array_info NULL
@@ -106,6 +107,8 @@ static long init_record(eventRecord *prec, int pass)
recGblInitConstantLink(&prec->siol,DBF_STRING,&prec->sval);
}
prec->epvt = eventNameToHandle(prec->val);
if( (pdset=(struct eventdset *)(prec->dset)) && (pdset->init_record) )
status=(*pdset->init_record)(prec);
return(status);
@@ -123,7 +126,7 @@ static long process(eventRecord *prec)
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
post_named_event(prec->val);
postEvent(prec->epvt);
recGblGetTimeStamp(prec);
@@ -137,7 +140,18 @@ static long process(eventRecord *prec)
return(status);
}
static long special(DBADDR *paddr, int after)
{
eventRecord *prec = (eventRecord *)paddr->precord;
if (!after) return 0;
if (dbGetFieldIndex(paddr) == eventRecordVAL) {
prec->epvt = eventNameToHandle(prec->val);
}
}
static long get_value(eventRecord *prec, struct valueDes *pvdes)
{
pvdes->field_type = DBF_STRING;
@@ -180,7 +194,10 @@ static long readValue(eventRecord *prec)
status=dbGetLink(&(prec->siol),DBR_STRING,
&(prec->sval),0,0);
if (status==0) {
strcpy(prec->val, prec->sval);
if (strcmp(prec->sval, prec->val) != 0) {
strcpy(prec->val, prec->sval);
prec->epvt = eventNameToHandle(prec->val);
}
prec->udf=FALSE;
}
} else {

View File

@@ -12,9 +12,17 @@ recordtype(event) {
field(VAL,DBF_STRING) {
prompt("Event Name To Post")
promptgroup(GUI_INPUTS)
special(SPC_MOD)
asl(ASL0)
size(40)
}
%#include "dbScan.h"
field(EPVT, DBF_NOACCESS) {
prompt("Event private")
special(SPC_NOMOD)
interest(4)
extra("EVENTPVT epvt")
}
field(INP,DBF_INLINK) {
prompt("Input Specification")
promptgroup(GUI_INPUTS)