This allows you to match on the same fields that you provided
in the add. Now including the userdata.
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
include/qb/qbmap.h | 18 ++++++++++++++++++
lib/hashtable.c | 26 ++++++++++++++++++++------
lib/map.c | 13 ++++++++++++-
lib/map_int.h | 8 ++++++--
lib/skiplist.c | 15 +++++++++++----
lib/trie.c | 26 ++++++++++++++++++++------
6 files changed, 87 insertions(+), 19 deletions(-)
diff --git a/include/qb/qbmap.h b/include/qb/qbmap.h
index 364c483..36f51f3 100644
--- a/include/qb/qbmap.h
+++ b/include/qb/qbmap.h
@@ -118,6 +118,24 @@ int32_t qb_map_notify_del(qb_map_t* m, const char* key,
qb_map_notify_fn fn, int32_t events);
/**
+ * Delete a notifier from the map (including the userdata).
+ *
+ * @note the key, fn, events and userdata must match those you added.
+ *
+ * @param m the map instance
+ * @param key the key (or prefix) to attach the notification to.
+ * @param fn the callback
+ * @param events the type of events to register for.
+ * @param user_data a pointer to be passed into the callback
+ *
+ * @retval 0 success
+ * @retval -errno failure
+ */
+int32_t qb_map_notify_del_2(qb_map_t* m, const char* key,
+ qb_map_notify_fn fn, int32_t events,
+ void *userdata);
+
+/**
* Inserts a new key and value into a qb_map_t.
*
* If the key already exists in the qb_map_t, it gets replaced by the new key.
diff --git a/lib/hashtable.c b/lib/hashtable.c
index fb6c6a2..27e41ac 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -288,13 +288,16 @@ hashtable_notify_add(qb_map_t * m, const char *key,
static int32_t
hashtable_notify_del(qb_map_t * m, const char *key,
- qb_map_notify_fn fn, int32_t events)
+ qb_map_notify_fn fn, int32_t events,
+ int32_t cmp_userdata, void *user_data)
{
struct hash_table *t = (struct hash_table *)m;
struct qb_map_notifier *f;
struct hash_node *n;
struct qb_list_head *head = NULL;
struct qb_list_head *list;
+ struct qb_list_head *next;
+ int32_t found = QB_FALSE;
if (key) {
n = hashtable_lookup(t, key);
@@ -308,16 +311,27 @@ hashtable_notify_del(qb_map_t * m, const char *key,
return -ENOENT;
}
- for (list = head->next; list != head; list = list->next) {
+ for (list = head->next; list != head; list = next) {
f = qb_list_entry(list, struct qb_map_notifier, list);
+ next = list->next;
if (f->events == events && f->callback == fn) {
- qb_list_del(&f->list);
- free(f);
- return 0;
+ if (cmp_userdata && (f->user_data == user_data)) {
+ found = QB_TRUE;
+ qb_list_del(&f->list);
+ free(f);
+ } else if (!cmp_userdata) {
+ found = QB_TRUE;
+ qb_list_del(&f->list);
+ free(f);
+ }
}
}
- return -ENOENT;
+ if (found) {
+ return 0;
+ } else {
+ return -ENOENT;
+ }
}
static size_t
diff --git a/lib/map.c b/lib/map.c
index 43f665e..2e28451 100644
--- a/lib/map.c
+++ b/lib/map.c
@@ -104,7 +104,18 @@ qb_map_notify_del(qb_map_t * m, const char *key, qb_map_notify_fn
fn,
int32_t events)
{
if (m->notify_del) {
- return m->notify_del(m, key, fn, events);
+ return m->notify_del(m, key, fn, events, QB_FALSE, NULL);
+ } else {
+ return -ENOSYS;
+ }
+}
+
+int32_t
+qb_map_notify_del_2(qb_map_t * m, const char *key, qb_map_notify_fn fn,
+ int32_t events, void *user_data)
+{
+ if (m->notify_del) {
+ return m->notify_del(m, key, fn, events, QB_TRUE, user_data);
} else {
return -ENOSYS;
}
diff --git a/lib/map_int.h b/lib/map_int.h
index 2b262e8..3d70b02 100644
--- a/lib/map_int.h
+++ b/lib/map_int.h
@@ -39,8 +39,12 @@ typedef void (*qb_map_iter_free_func)(qb_map_iter_t* i);
typedef int32_t (*qb_map_notify_add_func)(qb_map_t* m, const char* key,
qb_map_notify_fn fn, int32_t events,
void *user_data);
-typedef int32_t (*qb_map_notify_del_func)(qb_map_t* m, const char* key,
- qb_map_notify_fn fn, int32_t events);
+
+typedef int32_t (*qb_map_notify_del_func)(qb_map_t * m, const char *key,
+ qb_map_notify_fn fn,
+ int32_t events,
+ int32_t cmp_userdata,
+ void *user_data);
struct qb_map {
qb_map_put_func put;
diff --git a/lib/skiplist.c b/lib/skiplist.c
index dfacaae..b5b22db 100644
--- a/lib/skiplist.c
+++ b/lib/skiplist.c
@@ -264,7 +264,8 @@ skiplist_notify_add(qb_map_t * m, const char *key,
static int32_t
skiplist_notify_del(qb_map_t * m, const char *key,
- qb_map_notify_fn fn, int32_t events)
+ qb_map_notify_fn fn, int32_t events,
+ int32_t cmp_userdata, void *user_data)
{
struct skiplist *t = (struct skiplist *)m;
struct skiplist_node *n;
@@ -291,9 +292,15 @@ skiplist_notify_del(qb_map_t * m, const char *key,
next = list->next;
if (f->events == events && f->callback == fn) {
- found = QB_TRUE;
- qb_list_del(&f->list);
- free(f);
+ if (cmp_userdata && (f->user_data == user_data)) {
+ found = QB_TRUE;
+ qb_list_del(&f->list);
+ free(f);
+ } else if (!cmp_userdata) {
+ found = QB_TRUE;
+ qb_list_del(&f->list);
+ free(f);
+ }
}
}
if (found) {
diff --git a/lib/trie.c b/lib/trie.c
index df6d2b4..90f66dd 100644
--- a/lib/trie.c
+++ b/lib/trie.c
@@ -336,12 +336,15 @@ trie_notify_add(qb_map_t * m, const char *key,
static int32_t
trie_notify_del(qb_map_t * m, const char *key,
- qb_map_notify_fn fn, int32_t events)
+ qb_map_notify_fn fn, int32_t events,
+ int32_t cmp_userdata, void *user_data)
{
struct trie *t = (struct trie *)m;
struct qb_map_notifier *f;
struct trie_node *n;
struct qb_list_head *list;
+ struct qb_list_head *next;
+ int32_t found = QB_FALSE;
if (key) {
n = trie_lookup(t, key, QB_TRUE);
@@ -352,16 +355,27 @@ trie_notify_del(qb_map_t * m, const char *key,
return -ENOENT;
}
for (list = n->notifier_head.next;
- list != &n->notifier_head; list = list->next) {
+ list != &n->notifier_head; list = next) {
f = qb_list_entry(list, struct qb_map_notifier, list);
+ next = list->next;
if (f->events == events && f->callback == fn) {
- qb_list_del(&f->list);
- free(f);
- return 0;
+ if (cmp_userdata && (f->user_data == user_data)) {
+ found = QB_TRUE;
+ qb_list_del(&f->list);
+ free(f);
+ } else if (!cmp_userdata) {
+ found = QB_TRUE;
+ qb_list_del(&f->list);
+ free(f);
+ }
}
}
- return -ENOENT;
+ if (found) {
+ return 0;
+ } else {
+ return -ENOENT;
+ }
}
static qb_map_iter_t *
--
1.7.7.3