summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Palsson <karlp@etactica.com>2016-04-11 17:25:42 +0200
committerUwe Hermann <uwe@hermann-uwe.de>2017-02-20 16:28:27 +0100
commit3262ef0203e23399f3cab796391da06969c8306b (patch)
tree98a46c8eff87242c8cc89870e5008a116d5d23e0
parent1d4fe1c19c0948fb67b4a91495b126a763ea7adb (diff)
downloadlibsigrokdecode-3262ef0203e23399f3cab796391da06969c8306b.tar.gz
libsigrokdecode-3262ef0203e23399f3cab796391da06969c8306b.zip
Support adding multiple instances of a decoder
srd_inst_new() used the decoder ID as the instance ID, preventing the use of multiple instances of the same decoder in the same session. Simply append a numerical suffix to later instances to allow more. Required changes to cleanup to reliably free all memory. Valgrind checked. This fixes parts of bug #868. Based on original work by: Soeren Apel <soeren@apelpie.net> Signed-off-by: Karl Palsson <karlp@etactica.com>
-rw-r--r--decoder.c2
-rw-r--r--instance.c35
-rw-r--r--libsigrokdecode-internal.h2
-rw-r--r--session.c2
4 files changed, 20 insertions, 21 deletions
diff --git a/decoder.c b/decoder.c
index 8ad0c5a..f15a799 100644
--- a/decoder.c
+++ b/decoder.c
@@ -849,7 +849,7 @@ SRD_API int srd_decoder_unload(struct srd_decoder *dec)
*/
for (l = sessions; l; l = l->next) {
sess = l->data;
- srd_inst_free_all(sess, NULL);
+ srd_inst_free_all(sess);
}
/* Remove the PD from the list of loaded decoders. */
diff --git a/instance.c b/instance.c
index b56a3e6..79b72e1 100644
--- a/instance.c
+++ b/instance.c
@@ -297,6 +297,7 @@ SRD_API struct srd_decoder_inst *srd_inst_new(struct srd_session *sess,
struct srd_decoder_inst *di;
char *inst_id;
+ i = 1;
srd_dbg("Creating new %s instance.", decoder_id);
if (session_is_valid(sess) != SRD_OK) {
@@ -313,12 +314,22 @@ SRD_API struct srd_decoder_inst *srd_inst_new(struct srd_session *sess,
di->decoder = dec;
di->sess = sess;
+
if (options) {
inst_id = g_hash_table_lookup(options, "id");
- di->inst_id = g_strdup(inst_id ? inst_id : decoder_id);
+ if (inst_id)
+ di->inst_id = g_strdup(inst_id);
g_hash_table_remove(options, "id");
- } else
- di->inst_id = g_strdup(decoder_id);
+ }
+
+ /* Create a unique instance ID (as none was provided). */
+ if (!di->inst_id) {
+ di->inst_id = g_strdup_printf("%s-%d", decoder_id, i++);
+ while (srd_inst_find_by_id(sess, di->inst_id)) {
+ g_free(di->inst_id);
+ di->inst_id = g_strdup_printf("%s-%d", decoder_id, i++);
+ }
+ }
/*
* Prepare a default channel map, where samples come in the
@@ -368,6 +379,7 @@ SRD_API struct srd_decoder_inst *srd_inst_new(struct srd_session *sess,
/* Instance takes input from a frontend by default. */
sess->di_list = g_slist_append(sess->di_list, di);
+ srd_dbg("Created new %s instance with ID %s.", decoder_id, di->inst_id);
return di;
}
@@ -1018,27 +1030,14 @@ SRD_PRIV void srd_inst_free(struct srd_decoder_inst *di)
}
/** @private */
-SRD_PRIV void srd_inst_free_all(struct srd_session *sess, GSList *stack)
+SRD_PRIV void srd_inst_free_all(struct srd_session *sess)
{
- GSList *l;
- struct srd_decoder_inst *di;
-
if (session_is_valid(sess) != SRD_OK) {
srd_err("Invalid session.");
return;
}
- di = NULL;
- for (l = stack ? stack : sess->di_list; di == NULL && l != NULL; l = l->next) {
- di = l->data;
- if (di->next_di)
- srd_inst_free_all(sess, di->next_di);
- srd_inst_free(di);
- }
- if (!stack) {
- g_slist_free(sess->di_list);
- sess->di_list = NULL;
- }
+ g_slist_free_full(sess->di_list, (GDestroyNotify)srd_inst_free);
}
/** @} */
diff --git a/libsigrokdecode-internal.h b/libsigrokdecode-internal.h
index 9db255c..2609388 100644
--- a/libsigrokdecode-internal.h
+++ b/libsigrokdecode-internal.h
@@ -85,7 +85,7 @@ SRD_PRIV int srd_inst_decode(struct srd_decoder_inst *di,
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 void srd_inst_free(struct srd_decoder_inst *di);
-SRD_PRIV void srd_inst_free_all(struct srd_session *sess, GSList *stack);
+SRD_PRIV void srd_inst_free_all(struct srd_session *sess);
/* log.c */
#if defined(G_OS_WIN32) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
diff --git a/session.c b/session.c
index e1bb4f9..6a7628e 100644
--- a/session.c
+++ b/session.c
@@ -278,7 +278,7 @@ SRD_API int srd_session_destroy(struct srd_session *sess)
session_id = sess->session_id;
if (sess->di_list)
- srd_inst_free_all(sess, NULL);
+ srd_inst_free_all(sess);
if (sess->callbacks)
g_slist_free_full(sess->callbacks, g_free);
sessions = g_slist_remove(sessions, sess);