summaryrefslogtreecommitdiff
path: root/srd.c
diff options
context:
space:
mode:
authorUwe Hermann <uwe@hermann-uwe.de>2017-06-28 22:29:06 +0200
committerUwe Hermann <uwe@hermann-uwe.de>2017-06-30 13:05:09 +0200
commit514b2edc54efda9c6698456748c4256bb901eddd (patch)
tree3a46086d63e37dec48fa0acedaa204513abb44ec /srd.c
parentc1495906011ebabf97e799fe0f73e68ab0f1611a (diff)
downloadlibsigrokdecode-514b2edc54efda9c6698456748c4256bb901eddd.tar.gz
libsigrokdecode-514b2edc54efda9c6698456748c4256bb901eddd.zip
Acquire/release the Python GIL where needed to avoid threading issues.
With these additions, frontends can now call libsigrokdecode API functions from different threads without running into threading issues. The backend releases the GIL when it is performing tasks that might take a while and it doesn't need to run Python/C API calls during that time. This allows frontends to run multiple PD stacks (in multiple frontend threads) "at the same time" in a time-sharing, "interlocked" manner. Whenever one of the decoders is inside e.g. self.wait() it releases the GIL and thus allows other decoders to do some work in the mean time. The user-visible effect is that for use-cases such as running 3 different decoder stacks at the same time for an acquisition, the user will not have to wait for PD 1 to finish decoding, then wait for PD 2 to finish decoding, and only *then* being able to see annotations from PD 3. Instead, all three PDs will decode some chunks of data from time to time, thus the user is able to inspect annotations from all 3 PDs while the acquisition and decoding is still going on.
Diffstat (limited to 'srd.c')
-rw-r--r--srd.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/srd.c b/srd.c
index e8fd751..efd1c8e 100644
--- a/srd.c
+++ b/srd.c
@@ -232,6 +232,12 @@ SRD_API int srd_init(const char *path)
}
}
+ /* Initialize the Python GIL (this also happens to acquire it). */
+ PyEval_InitThreads();
+
+ /* Release the GIL (ignore return value, we don't need it here). */
+ (void)PyEval_SaveThread();
+
max_session_id = 0;
return SRD_OK;
@@ -261,9 +267,17 @@ SRD_API int srd_exit(void)
g_slist_free_full(searchpaths, g_free);
searchpaths = NULL;
+ /*
+ * Acquire the GIL, otherwise Py_Finalize() might have issues.
+ * Ignore the return value, we don't need it here.
+ */
+ (void)PyGILState_Ensure();
+
/* Py_Finalize() returns void, any finalization errors are ignored. */
Py_Finalize();
+ /* Note: No need to release the GIL since Python is shut down now. */
+
max_session_id = -1;
return SRD_OK;
@@ -291,28 +305,38 @@ SRD_API int srd_exit(void)
SRD_PRIV int srd_decoder_searchpath_add(const char *path)
{
PyObject *py_cur_path, *py_item;
+ PyGILState_STATE gstate;
srd_dbg("Adding '%s' to module path.", path);
+ gstate = PyGILState_Ensure();
+
py_cur_path = PySys_GetObject("path");
if (!py_cur_path)
- return SRD_ERR_PYTHON;
+ goto err;
py_item = PyUnicode_FromString(path);
if (!py_item) {
srd_exception_catch("Failed to create Unicode object");
- return SRD_ERR_PYTHON;
+ goto err;
}
if (PyList_Insert(py_cur_path, 0, py_item) < 0) {
srd_exception_catch("Failed to insert path element");
Py_DECREF(py_item);
- return SRD_ERR_PYTHON;
+ goto err;
}
Py_DECREF(py_item);
+ PyGILState_Release(gstate);
+
searchpaths = g_slist_prepend(searchpaths, g_strdup(path));
return SRD_OK;
+
+err:
+ PyGILState_Release(gstate);
+
+ return SRD_ERR_PYTHON;
}
/** @} */