support async processing
This commit is contained in:
@ -216,6 +216,7 @@ static long process_record(dbCommon *prec)
|
||||
{
|
||||
pyDevice *priv = prec->dpvt;
|
||||
PyGILState_STATE pystate;
|
||||
long pact = prec->pact;
|
||||
|
||||
if(!priv || !priv->support)
|
||||
return 0;
|
||||
@ -227,6 +228,10 @@ static long process_record(dbCommon *prec)
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
/* always clear PACT if it was initially set */
|
||||
if(pact)
|
||||
prec->pact = 0;
|
||||
|
||||
PyGILState_Release(pystate);
|
||||
return 0;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <dbCommon.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbStaticLib.h>
|
||||
#include <recSup.h>
|
||||
#include <dbScan.h>
|
||||
|
||||
#include "pydevsup.h"
|
||||
@ -132,21 +133,81 @@ static PyObject* pyRecord_scan(pyRecord *self, PyObject *args, PyObject *kws)
|
||||
|
||||
if(!PyObject_IsTrue(sync)) {
|
||||
scanOnce(prec);
|
||||
Py_RETURN_NONE;
|
||||
|
||||
} else {
|
||||
long ret;
|
||||
setCausePyRecord(prec, reason);
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS {
|
||||
|
||||
dbScanLock(prec);
|
||||
dbProcess(prec);
|
||||
ret = dbProcess(prec);
|
||||
dbScanUnlock(prec);
|
||||
|
||||
} Py_END_ALLOW_THREADS
|
||||
|
||||
clearCausePyRecord(prec);
|
||||
|
||||
return PyLong_FromLong(ret);
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *pyRecord_asyncStart(pyRecord *self)
|
||||
{
|
||||
dbCommon *prec=self->entry.precnode->precord;
|
||||
epicsUInt8 pact = prec->pact;
|
||||
if(!isPyRecord(prec)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Not a Python Device record");
|
||||
return NULL;
|
||||
}
|
||||
prec->pact = 1;
|
||||
return PyLong_FromLong(pact);
|
||||
}
|
||||
|
||||
static PyObject *pyRecord_asyncFinish(pyRecord *self, PyObject *args, PyObject *kws)
|
||||
{
|
||||
long pact, ret;
|
||||
dbCommon *prec = self->entry.precnode->precord;
|
||||
|
||||
static char* names[] = {"reason", NULL};
|
||||
PyObject *reason = Py_None;
|
||||
|
||||
if(!PyArg_ParseTupleAndKeywords(args, kws, "|O", names, &reason))
|
||||
return NULL;
|
||||
|
||||
if(!isPyRecord(prec)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Not a Python Device record");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
Py_INCREF(self);
|
||||
|
||||
setCausePyRecord(prec, reason);
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS {
|
||||
rset *rsup = prec->rset;
|
||||
|
||||
dbScanLock(prec);
|
||||
pact = prec->pact;
|
||||
if(pact) {
|
||||
ret = (*rsup->process)(prec);
|
||||
/* Out devsup always clears PACT if initially set */
|
||||
}
|
||||
dbScanUnlock(prec);
|
||||
|
||||
} Py_END_ALLOW_THREADS
|
||||
|
||||
clearCausePyRecord(prec);
|
||||
|
||||
if(!pact) {
|
||||
PyErr_SetString(PyExc_ValueError, "Python Device record was not active");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_DECREF(self);
|
||||
|
||||
return PyLong_FromLong(ret);
|
||||
}
|
||||
|
||||
static PyMethodDef pyRecord_methods[] = {
|
||||
@ -159,8 +220,11 @@ static PyMethodDef pyRecord_methods[] = {
|
||||
{"scan", (PyCFunction)pyRecord_scan, METH_VARARGS|METH_KEYWORDS,
|
||||
"scan(sync=False)\nScan this record. If sync is False then"
|
||||
"a scan request is queued. If sync is True then the record"
|
||||
"is scannined immidately on the current thread."
|
||||
},
|
||||
"is scannined immidately on the current thread."},
|
||||
{"asyncStart", (PyCFunction)pyRecord_asyncStart, METH_NOARGS,
|
||||
"Begin an asynchronous action. Record must be locked!"},
|
||||
{"asyncFinish", (PyCFunction)pyRecord_asyncFinish, METH_VARARGS|METH_KEYWORDS,
|
||||
"Complete an asynchronous action. Record must *not* be locked!"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
@ -1,12 +1,23 @@
|
||||
|
||||
import weakref
|
||||
import threading, time
|
||||
from devsup.hooks import addHook
|
||||
|
||||
insts = {}
|
||||
|
||||
def done(obj):
|
||||
print obj,'Expires'
|
||||
|
||||
_tracking = {}
|
||||
def track(obj):
|
||||
W = weakref.ref(obj, done)
|
||||
print 'track',obj,'with',W
|
||||
_tracking[id(obj)] = W
|
||||
|
||||
class Driver(threading.Thread):
|
||||
def __init__(self, name):
|
||||
super(Driver,self).__init__()
|
||||
track(self)
|
||||
self.name = name
|
||||
self._lock = threading.Lock()
|
||||
self._recs = set()
|
||||
@ -48,6 +59,7 @@ def addDrv(name):
|
||||
|
||||
class Device(object):
|
||||
def __init__(self, rec, drv):
|
||||
track(self)
|
||||
self.driver, self.record = drv, rec
|
||||
self.driver.addrec(self)
|
||||
self.val = rec.field('VAL')
|
||||
|
Reference in New Issue
Block a user