summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2014-01-08 16:00:24 -0800
committerMarcel Holtmann <marcel@holtmann.org>2014-01-08 16:00:24 -0800
commit0f3d964b794412e8bb5a461d33ffe4a712879797 (patch)
tree8c8aed8e4fc3b814eaa1c9de93a2dd0c58505b9b /src
parent70f38998469141d44c6d1f34794fa9ae0fec1098 (diff)
shared: Replace mgmt notify list with internal queue handling
Diffstat (limited to 'src')
-rw-r--r--src/shared/mgmt.c166
1 files changed, 84 insertions, 82 deletions
diff --git a/src/shared/mgmt.c b/src/shared/mgmt.c
index 3fbd122c3..d96a339f9 100644
--- a/src/shared/mgmt.c
+++ b/src/shared/mgmt.c
@@ -50,8 +50,7 @@ struct mgmt {
struct queue *request_queue;
struct queue *reply_queue;
struct queue *pending_list;
- GList *notify_list;
- GList *notify_destroyed;
+ struct queue *notify_list;
unsigned int next_request_id;
unsigned int next_notify_id;
bool in_notify;
@@ -111,7 +110,7 @@ static bool match_request_index(const void *a, const void *b)
return request->index == index;
}
-static void destroy_notify(gpointer data, gpointer user_data)
+static void destroy_notify(void *data)
{
struct mgmt_notify *notify = data;
@@ -121,12 +120,34 @@ static void destroy_notify(gpointer data, gpointer user_data)
g_free(notify);
}
-static int compare_notify_id(gconstpointer a, gconstpointer b)
+static void remove_notify(void *data)
+{
+ struct mgmt_notify *notify = data;
+
+ notify->destroyed = true;
+}
+
+static bool match_notify_id(const void *a, const void *b)
+{
+ const struct mgmt_notify *notify = a;
+ unsigned int id = PTR_TO_UINT(b);
+
+ return notify->id == id;
+}
+
+static bool match_notify_index(const void *a, const void *b)
+{
+ const struct mgmt_notify *notify = a;
+ uint16_t index = PTR_TO_UINT(b);
+
+ return notify->index == index;
+}
+
+static bool match_notify_destroyed(const void *a, const void *b)
{
const struct mgmt_notify *notify = a;
- unsigned int id = GPOINTER_TO_UINT(b);
- return notify->id - id;
+ return notify->destroyed;
}
static void write_watch_destroy(gpointer user_data)
@@ -231,40 +252,46 @@ static void request_complete(struct mgmt *mgmt, uint8_t status,
wakeup_writer(mgmt);
}
-static void process_notify(struct mgmt *mgmt, uint16_t event, uint16_t index,
- uint16_t length, const void *param)
+struct event_index {
+ uint16_t event;
+ uint16_t index;
+ uint16_t length;
+ const void *param;
+};
+
+static void notify_handler(void *data, void *user_data)
{
- GList *list;
+ struct mgmt_notify *notify = data;
+ struct event_index *match = user_data;
- mgmt->in_notify = true;
+ if (notify->destroyed)
+ return;
- for (list = g_list_first(mgmt->notify_list); list;
- list = g_list_next(list)) {
- struct mgmt_notify *notify = list->data;
+ if (notify->event != match->event)
+ return;
- if (notify->destroyed)
- continue;
+ if (notify->index != match->index && notify->index != MGMT_INDEX_NONE)
+ return;
- if (notify->event != event)
- continue;
+ if (notify->callback)
+ notify->callback(match->index, match->length, match->param,
+ notify->user_data);
+}
- if (notify->index != index && notify->index != MGMT_INDEX_NONE)
- continue;
+static void process_notify(struct mgmt *mgmt, uint16_t event, uint16_t index,
+ uint16_t length, const void *param)
+{
+ struct event_index match = { .event = event, .index = index,
+ .length = length, .param = param };
- if (notify->callback)
- notify->callback(index, length, param,
- notify->user_data);
+ mgmt->in_notify = true;
- if (mgmt->destroyed)
- break;
- }
+ queue_foreach(mgmt->notify_list, notify_handler, &match);
mgmt->in_notify = false;
- g_list_foreach(mgmt->notify_destroyed, destroy_notify, NULL);
- g_list_free(mgmt->notify_destroyed);
-
- mgmt->notify_destroyed = NULL;
+ queue_remove_all(mgmt->notify_list, match_notify_destroyed, NULL,
+ destroy_notify);
}
static void read_watch_destroy(gpointer user_data)
@@ -397,6 +424,16 @@ struct mgmt *mgmt_new(int fd)
return NULL;
}
+ mgmt->notify_list = queue_new();
+ if (!mgmt->notify_list) {
+ queue_destroy(mgmt->pending_list, NULL);
+ queue_destroy(mgmt->reply_queue, NULL);
+ queue_destroy(mgmt->request_queue, NULL);
+ g_free(mgmt->buf);
+ g_free(mgmt);
+ return NULL;
+ }
+
mgmt->read_watch = g_io_add_watch_full(mgmt->io, G_PRIORITY_DEFAULT,
G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
received_data, mgmt, read_watch_destroy);
@@ -699,7 +736,10 @@ unsigned int mgmt_register(struct mgmt *mgmt, uint16_t event, uint16_t index,
notify->id = mgmt->next_notify_id++;
- mgmt->notify_list = g_list_append(mgmt->notify_list, notify);
+ if (!queue_push_tail(mgmt->notify_list, notify)) {
+ g_free(notify);
+ return 0;
+ }
return notify->id;
}
@@ -707,87 +747,49 @@ unsigned int mgmt_register(struct mgmt *mgmt, uint16_t event, uint16_t index,
bool mgmt_unregister(struct mgmt *mgmt, unsigned int id)
{
struct mgmt_notify *notify;
- GList *list;
if (!mgmt || !id)
return false;
- list = g_list_find_custom(mgmt->notify_list,
- GUINT_TO_POINTER(id), compare_notify_id);
- if (!list)
+ notify = queue_remove_if(mgmt->notify_list, match_notify_id,
+ UINT_TO_PTR(id));
+ if (!notify)
return false;
- notify = list->data;
-
- mgmt->notify_list = g_list_remove_link(mgmt->notify_list, list);
-
if (!mgmt->in_notify) {
- g_list_free_1(list);
- destroy_notify(notify, NULL);
+ destroy_notify(notify);
return true;
}
notify->destroyed = true;
- mgmt->notify_destroyed = g_list_concat(mgmt->notify_destroyed, list);
-
return true;
}
bool mgmt_unregister_index(struct mgmt *mgmt, uint16_t index)
{
- GList *list, *next;
-
if (!mgmt)
return false;
- for (list = g_list_first(mgmt->notify_list); list; list = next) {
- struct mgmt_notify *notify = list->data;
-
- next = g_list_next(list);
-
- if (notify->index != index)
- continue;
-
- mgmt->notify_list = g_list_remove_link(mgmt->notify_list, list);
-
- if (!mgmt->in_notify) {
- g_list_free_1(list);
- destroy_notify(notify, NULL);
- continue;
- }
-
- notify->destroyed = true;
-
- mgmt->notify_destroyed = g_list_concat(mgmt->notify_destroyed,
- list);
- }
+ if (mgmt->in_notify)
+ queue_remove_all(mgmt->notify_list, match_notify_index,
+ UINT_TO_PTR(index), remove_notify);
+ else
+ queue_remove_all(mgmt->notify_list, match_notify_index,
+ UINT_TO_PTR(index), destroy_notify);
return true;
}
-static void mark_notify(gpointer data, gpointer user_data)
-{
- struct mgmt_notify *notify = data;
-
- notify->destroyed = true;
-}
-
bool mgmt_unregister_all(struct mgmt *mgmt)
{
if (!mgmt)
return false;
- if (!mgmt->in_notify) {
- g_list_foreach(mgmt->notify_list, destroy_notify, NULL);
- g_list_free(mgmt->notify_list);
- } else {
- g_list_foreach(mgmt->notify_list, mark_notify, NULL);
- mgmt->notify_destroyed = g_list_concat(mgmt->notify_destroyed,
- mgmt->notify_list);
- }
-
- mgmt->notify_list = NULL;
+ if (mgmt->in_notify)
+ queue_remove_all(mgmt->notify_list, NULL, NULL, remove_notify);
+ else
+ queue_remove_all(mgmt->notify_list, NULL, NULL, destroy_notify);
return true;
}