summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerhard Sittig <gerhard.sittig@gmx.net>2017-12-17 18:55:46 +0100
committerUwe Hermann <uwe@hermann-uwe.de>2018-03-31 20:44:21 +0200
commit9553e9622bb26dfbe6296ef6f330b1cf0f5b40e6 (patch)
tree54229df143c86283ff1aca2db86ae337d9b6413e
parent7d82e3c1ec96ac8a9ef358de1e9c87715dcb8f43 (diff)
downloadlibsigrokdecode-9553e9622bb26dfbe6296ef6f330b1cf0f5b40e6.tar.gz
libsigrokdecode-9553e9622bb26dfbe6296ef6f330b1cf0f5b40e6.zip
session: add "terminate and reset" support for protocol stacks
Implement routines which terminate currently pending decoder operations and reset internal state (on the C and Python sides) for instances as well as sessions. This allows to re-use previously created stacks for new input data.
-rw-r--r--instance.c64
-rw-r--r--libsigrokdecode-internal.h1
-rw-r--r--libsigrokdecode.h1
-rw-r--r--session.c39
4 files changed, 105 insertions, 0 deletions
diff --git a/instance.c b/instance.c
index 5281510..6fbdc01 100644
--- a/instance.c
+++ b/instance.c
@@ -1270,6 +1270,70 @@ SRD_PRIV int srd_inst_decode(struct srd_decoder_inst *di,
return SRD_OK;
}
+/**
+ * Terminate current decoder work, prepare for re-use on new input data.
+ *
+ * Terminates all decoder operations in the specified decoder instance
+ * and the instances stacked on top of it. Resets internal state such
+ * that the previously constructed stack can process new input data that
+ * is not related to previously processed input data. This avoids the
+ * expensive and complex re-construction of decoder stacks.
+ *
+ * Callers are expected to follow up with start, metadata, and decode
+ * calls like they would for newly constructed decoder stacks.
+ *
+ * @param di The decoder instance to call. Must not be NULL.
+ * @return SRD_OK upon success, a (negative) error code otherwise.
+ * @private
+ */
+SRD_PRIV int srd_inst_terminate_reset(struct srd_decoder_inst *di)
+{
+ PyGILState_STATE gstate;
+ PyObject *py_ret;
+ GSList *l;
+ int ret;
+
+ if (!di)
+ return SRD_ERR_ARG;
+
+ /*
+ * Request termination and wait for previously initiated
+ * background operation to finish. Reset internal state, but
+ * do not start releasing resources yet. This shall result in
+ * decoders' state just like after creation. This block handles
+ * the C language library side.
+ */
+ srd_dbg("Terminating instance %s", di->inst_id);
+ srd_inst_join_decode_thread(di);
+ srd_inst_reset_state(di);
+
+ /*
+ * Have the Python side's .reset() method executed (if the PD
+ * implements it). It's assumed that .reset() assigns variables
+ * very much like __init__() used to do in the past. Thus memory
+ * that was allocated in previous calls gets released by Python
+ * as it's not referenced any longer.
+ */
+ gstate = PyGILState_Ensure();
+ if (PyObject_HasAttrString(di->py_inst, "reset")) {
+ srd_dbg("Calling .reset() of instance %s", di->inst_id);
+ py_ret = PyObject_CallMethod(di->py_inst, "reset", NULL);
+ Py_XDECREF(py_ret);
+ }
+ PyGILState_Release(gstate);
+
+ /*
+ * Pass the "restart" request to all stacked decoders.
+ */
+ for (l = di->next_di; l; l = l->next) {
+ ret = srd_inst_terminate_reset(l->data);
+ if (ret != SRD_OK)
+ return ret;
+ }
+
+ return SRD_OK;
+}
+
/** @private */
SRD_PRIV void srd_inst_free(struct srd_decoder_inst *di)
{
diff --git a/libsigrokdecode-internal.h b/libsigrokdecode-internal.h
index eb79287..6fb590c 100644
--- a/libsigrokdecode-internal.h
+++ b/libsigrokdecode-internal.h
@@ -84,6 +84,7 @@ SRD_PRIV int srd_inst_decode(struct srd_decoder_inst *di,
uint64_t abs_start_samplenum, uint64_t abs_end_samplenum,
const uint8_t *inbuf, uint64_t inbuflen, uint64_t unitsize);
SRD_PRIV int process_samples_until_condition_match(struct srd_decoder_inst *di, gboolean *found_match);
+SRD_PRIV int srd_inst_terminate_reset(struct srd_decoder_inst *di);
SRD_PRIV void srd_inst_free(struct srd_decoder_inst *di);
SRD_PRIV void srd_inst_free_all(struct srd_session *sess);
diff --git a/libsigrokdecode.h b/libsigrokdecode.h
index 982ae19..ee610c9 100644
--- a/libsigrokdecode.h
+++ b/libsigrokdecode.h
@@ -330,6 +330,7 @@ SRD_API int srd_session_metadata_set(struct srd_session *sess, int key,
SRD_API int srd_session_send(struct srd_session *sess,
uint64_t abs_start_samplenum, uint64_t abs_end_samplenum,
const uint8_t *inbuf, uint64_t inbuflen, uint64_t unitsize);
+SRD_API int srd_session_terminate_reset(struct srd_session *sess);
SRD_API int srd_session_destroy(struct srd_session *sess);
SRD_API int srd_pd_output_callback_add(struct srd_session *sess,
int output_type, srd_pd_output_callback cb, void *cb_data);
diff --git a/session.c b/session.c
index 0c1ef82..4d794df 100644
--- a/session.c
+++ b/session.c
@@ -298,6 +298,45 @@ SRD_API int srd_session_send(struct srd_session *sess,
}
/**
+ * Terminate currently executing decoders in a session, reset internal state.
+ *
+ * All decoder instances have their .wait() method terminated, which
+ * shall terminate .decode() as well. Afterwards the decoders' optional
+ * .reset() method gets executed.
+ *
+ * This routine allows callers to abort pending expensive operations,
+ * when they are no longer interested in the decoders' results. Note
+ * that the decoder state is lost and aborted work cannot resume.
+ *
+ * This routine also allows callers to re-use previously created decoder
+ * stacks to process new input data which is not related to previously
+ * processed input data. This avoids the necessity to re-construct the
+ * decoder stack.
+ *
+ * @param sess The session in which to terminate decoders.
+ * @return SRD_OK upon success, a (negative) error code otherwise.
+ *
+ * @since 0.6.0
+ */
+SRD_API int srd_session_terminate_reset(struct srd_session *sess)
+{
+ GSList *d;
+ int ret;
+
+ if (session_is_valid(sess) != SRD_OK) {
+ srd_err("Invalid session.");
+ return SRD_ERR_ARG;
+ }
+
+ for (d = sess->di_list; d; d = d->next) {
+ ret = srd_inst_terminate_reset(d->data);
+ if (ret != SRD_OK)
+ return ret;
+ }
+ return SRD_OK;
+}
+
+/**
* Destroy a decoding session.
*
* All decoder instances and output callbacks are properly released.