]> sigrok.org Git - libsigrok.git/commitdiff
input: clear sdi_ready flag and receive() buffer in common code
authorGerhard Sittig <redacted>
Sun, 3 Jun 2018 06:05:43 +0000 (08:05 +0200)
committerUwe Hermann <redacted>
Sun, 3 Jun 2018 17:28:46 +0000 (19:28 +0200)
Rephrase common input reset logic such that additional common code can
execute after the individual module's reset callback. No behaviour has
changed, the module's reset callback still is optional, and identical
log output gets emitted.

Do clear the sdi_ready flag in the common sr_input_reset() routine, so
that all input modules will parse header information again before
processing sample data when subsequent calls receive new file content.
Void the input module's receive() buffer from common reset code. This
unbreaks the feature of re-reading previously consumed input files.

Extend comments in the common reset and free code paths, which involve
the modules' reset and cleanup routines, which interact in non-trivial
ways. Discuss the responsibilities of common and individual routines, to
remain aware during maintenance.

src/input/input.c

index 2a23aec2bd81d4a7a4326fb8c06c9acf3b1c47f4..4d3eb9856744271879f2f93fc866c7ddbad6c07b 100644 (file)
@@ -610,16 +610,49 @@ SR_API int sr_input_end(const struct sr_input *in)
  *
  * @since 0.5.0
  */
-SR_API int sr_input_reset(const struct sr_input *in)
+SR_API int sr_input_reset(const struct sr_input *in_ro)
 {
-       if (!in->module->reset) {
+       struct sr_input *in;
+       int rc;
+
+       in = (struct sr_input *)in_ro;  /* "un-const" */
+       if (!in || !in->module)
+               return SR_ERR_ARG;
+
+       /*
+        * Run the optional input module's .reset() method. This shall
+        * take care of the context (kept in the 'inc' variable).
+        */
+       if (in->module->reset) {
+               sr_spew("Resetting %s module.", in->module->id);
+               rc = in->module->reset(in);
+       } else {
                sr_spew("Tried to reset %s module but no reset handler found.",
                        in->module->id);
-               return SR_OK;
+               rc = SR_OK;
        }
 
-       sr_spew("Resetting %s module.", in->module->id);
-       return in->module->reset((struct sr_input *)in);
+       /*
+        * Handle input module status (kept in the 'in' variable) here
+        * in common logic. This agrees with how input module's receive()
+        * and end() routines "amend but never seed" the 'in' information.
+        *
+        * Void potentially accumulated receive() buffer content, and
+        * clear the sdi_ready flag. This makes sure that subsequent
+        * processing will scan the header again before sample data gets
+        * interpreted, and stale content from previous calls won't affect
+        * the result.
+        *
+        * This common logic does not harm when the input module implements
+        * .reset() and contains identical assignments. In the absence of
+        * an individual .reset() method, simple input modules can completely
+        * rely on common code and keep working across resets.
+        */
+       if (in->buf)
+               g_string_truncate(in->buf, 0);
+       in->sdi_ready = FALSE;
+
+       return rc;
 }
 
 /**
@@ -632,8 +665,19 @@ SR_API void sr_input_free(const struct sr_input *in)
        if (!in)
                return;
 
+       /*
+        * Run the input module's optional .cleanup() routine. This
+        * takes care of the context (kept in the 'inc' variable).
+        */
        if (in->module->cleanup)
                in->module->cleanup((struct sr_input *)in);
+
+       /*
+        * Common code releases the input module's state (kept in the
+        * 'in' variable). Release the device instance, the receive()
+        * buffer, the shallow 'in->priv' block which is 'inc' (after
+        * .cleanup() released potentially nested resources under 'inc').
+        */
        sr_dev_inst_free(in->sdi);
        if (in->buf->len > 64) {
                /* That seems more than just some sub-unitsize leftover... */