X-Git-Url: https://sigrok.org/gitweb/?p=libsigrokdecode.git;a=blobdiff_plain;f=instance.c;h=a94118f2430de4991f70708522999fc49e02b53c;hp=528151029f1287be3fcad71bd311c4edde569c02;hb=60d4764a9c699d0b4aca656831a4d8d09568b659;hpb=63bbdb445fc2ade82c15766b419c869a41ed8f38 diff --git a/instance.c b/instance.c index 5281510..a94118f 100644 --- a/instance.c +++ b/instance.c @@ -280,6 +280,7 @@ SRD_API int srd_inst_channel_set_all(struct srd_decoder_inst *di, pdch = g_slist_nth(di->decoder->channels, i)->data; srd_err("Required channel '%s' (index %d) was not specified.", pdch->id, i); + g_free(new_channelmap); return SRD_ERR; } @@ -1255,7 +1256,6 @@ SRD_PRIV int srd_inst_decode(struct srd_decoder_inst *di, di->inbuflen = inbuflen; di->got_new_samples = TRUE; di->handled_all_samples = FALSE; - di->want_wait_terminate = FALSE; /* Signal the thread that we have new data. */ g_cond_signal(&di->got_new_samples_cond); @@ -1267,6 +1267,72 @@ SRD_PRIV int srd_inst_decode(struct srd_decoder_inst *di, g_cond_wait(&di->handled_all_samples_cond, &di->data_mutex); g_mutex_unlock(&di->data_mutex); + if (di->want_wait_terminate) + return SRD_ERR_TERM_REQ; + 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; }