support async processing
This commit is contained in:
@ -216,6 +216,7 @@ static long process_record(dbCommon *prec)
|
|||||||
{
|
{
|
||||||
pyDevice *priv = prec->dpvt;
|
pyDevice *priv = prec->dpvt;
|
||||||
PyGILState_STATE pystate;
|
PyGILState_STATE pystate;
|
||||||
|
long pact = prec->pact;
|
||||||
|
|
||||||
if(!priv || !priv->support)
|
if(!priv || !priv->support)
|
||||||
return 0;
|
return 0;
|
||||||
@ -227,6 +228,10 @@ static long process_record(dbCommon *prec)
|
|||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* always clear PACT if it was initially set */
|
||||||
|
if(pact)
|
||||||
|
prec->pact = 0;
|
||||||
|
|
||||||
PyGILState_Release(pystate);
|
PyGILState_Release(pystate);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <dbCommon.h>
|
#include <dbCommon.h>
|
||||||
#include <dbAccess.h>
|
#include <dbAccess.h>
|
||||||
#include <dbStaticLib.h>
|
#include <dbStaticLib.h>
|
||||||
|
#include <recSup.h>
|
||||||
#include <dbScan.h>
|
#include <dbScan.h>
|
||||||
|
|
||||||
#include "pydevsup.h"
|
#include "pydevsup.h"
|
||||||
@ -132,21 +133,81 @@ static PyObject* pyRecord_scan(pyRecord *self, PyObject *args, PyObject *kws)
|
|||||||
|
|
||||||
if(!PyObject_IsTrue(sync)) {
|
if(!PyObject_IsTrue(sync)) {
|
||||||
scanOnce(prec);
|
scanOnce(prec);
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
long ret;
|
||||||
setCausePyRecord(prec, reason);
|
setCausePyRecord(prec, reason);
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS {
|
Py_BEGIN_ALLOW_THREADS {
|
||||||
|
|
||||||
dbScanLock(prec);
|
dbScanLock(prec);
|
||||||
dbProcess(prec);
|
ret = dbProcess(prec);
|
||||||
dbScanUnlock(prec);
|
dbScanUnlock(prec);
|
||||||
|
|
||||||
} Py_END_ALLOW_THREADS
|
} Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
clearCausePyRecord(prec);
|
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[] = {
|
static PyMethodDef pyRecord_methods[] = {
|
||||||
@ -159,8 +220,11 @@ static PyMethodDef pyRecord_methods[] = {
|
|||||||
{"scan", (PyCFunction)pyRecord_scan, METH_VARARGS|METH_KEYWORDS,
|
{"scan", (PyCFunction)pyRecord_scan, METH_VARARGS|METH_KEYWORDS,
|
||||||
"scan(sync=False)\nScan this record. If sync is False then"
|
"scan(sync=False)\nScan this record. If sync is False then"
|
||||||
"a scan request is queued. If sync is True then the record"
|
"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}
|
{NULL, NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,12 +1,23 @@
|
|||||||
|
|
||||||
|
import weakref
|
||||||
import threading, time
|
import threading, time
|
||||||
from devsup.hooks import addHook
|
from devsup.hooks import addHook
|
||||||
|
|
||||||
insts = {}
|
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):
|
class Driver(threading.Thread):
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
super(Driver,self).__init__()
|
super(Driver,self).__init__()
|
||||||
|
track(self)
|
||||||
self.name = name
|
self.name = name
|
||||||
self._lock = threading.Lock()
|
self._lock = threading.Lock()
|
||||||
self._recs = set()
|
self._recs = set()
|
||||||
@ -48,6 +59,7 @@ def addDrv(name):
|
|||||||
|
|
||||||
class Device(object):
|
class Device(object):
|
||||||
def __init__(self, rec, drv):
|
def __init__(self, rec, drv):
|
||||||
|
track(self)
|
||||||
self.driver, self.record = drv, rec
|
self.driver, self.record = drv, rec
|
||||||
self.driver.addrec(self)
|
self.driver.addrec(self)
|
||||||
self.val = rec.field('VAL')
|
self.val = rec.field('VAL')
|
||||||
|
Reference in New Issue
Block a user