Skip to content

Commit ae2b6e4

Browse files
Avoid multiple dispatcher() calls for non-async
This implementation still leaks abstractions - the device now needs to know about the difference between cothread and async calls. Perhaps another round of refactoring is required...
1 parent 0a49421 commit ae2b6e4

File tree

2 files changed

+22
-19
lines changed

2 files changed

+22
-19
lines changed

softioc/device.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from inspect import isawaitable
12
import os
23
import time
34
import ctypes
@@ -161,7 +162,6 @@ def __init__(self, name, **kargs):
161162

162163
self._blocking = kargs.pop('blocking', blocking)
163164
if self._blocking:
164-
self._completion_event = Event()
165165
self._callback = create_callback_capsule()
166166

167167

@@ -185,19 +185,21 @@ def init_record(self, record):
185185
recGblResetAlarms(record)
186186
return self._epics_rc_
187187

188-
def __completion(self):
188+
def __completion(self, record):
189189
if self._blocking:
190-
self._completion_event.set()
190+
signal_processing_complete(record, self._callback)
191191
pass
192192

193-
def __wait_for_completion(self, record):
194-
self._completion_event.wait()
195-
signal_processing_complete(record, self._callback)
196-
self._completion_event.clear()
193+
def __wrap_completion(self, value, record):
194+
update = self.__on_update(value)
195+
if isawaitable(update):
196+
dispatcher(self._complete_update, update, record)
197+
else:
198+
self.__completion(record)
197199

198-
def __wrap_completion(self, value):
199-
dispatcher(self.__on_update, value)
200-
self.__completion()
200+
async def _complete_update(self, future, record):
201+
await future
202+
self.__completion(record)
201203

202204
def _process(self, record):
203205
'''Processing suitable for output records. Performs immediate value
@@ -225,11 +227,8 @@ def _process(self, record):
225227
record.UDF = 0
226228
if self.__on_update and self.__enable_write:
227229
record.PACT = self._blocking
228-
dispatcher(self.__wrap_completion, python_value)
230+
dispatcher(self.__wrap_completion, python_value, record)
229231

230-
if self._blocking:
231-
# Create a process to wait for on_update to finish
232-
dispatcher(self.__wait_for_completion, record)
233232
return EPICS_OK
234233

235234

softioc/extension.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -215,17 +215,13 @@ static PyObject *install_pv_logging(PyObject *self, PyObject *args)
215215

216216
static void capsule_destructor(PyObject *obj)
217217
{
218-
void *callback = PyCapsule_GetPointer(obj, CAPSULE_NAME);
219-
free(callback);
218+
free(PyCapsule_GetPointer(obj, CAPSULE_NAME));
220219
}
221220

222221

223222
static PyObject *create_callback_capsule(PyObject *self, PyObject *args)
224223
{
225224
void *callback = malloc(sizeof(CALLBACK));
226-
227-
printf("Created CALLBACK struct %p\n", callback);
228-
229225
return PyCapsule_New(callback, CAPSULE_NAME, &capsule_destructor);
230226
}
231227

@@ -240,6 +236,14 @@ static PyObject *signal_processing_complete(PyObject *self, PyObject *args)
240236
return NULL;
241237
}
242238

239+
if (!PyCapsule_IsValid(callback_capsule, CAPSULE_NAME))
240+
{
241+
return PyErr_Format(
242+
PyExc_TypeError,
243+
"Given object was not a capsule with name \"%s\"",
244+
CAPSULE_NAME);
245+
}
246+
243247
CALLBACK *callback = PyCapsule_GetPointer(callback_capsule, CAPSULE_NAME);
244248

245249
callbackRequestProcessCallback(callback, priority, record);

0 commit comments

Comments
 (0)