diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2014-01-08 16:00:24 -0800 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2014-01-08 16:00:24 -0800 |
commit | 0f3d964b794412e8bb5a461d33ffe4a712879797 (patch) | |
tree | 8c8aed8e4fc3b814eaa1c9de93a2dd0c58505b9b /src | |
parent | 70f38998469141d44c6d1f34794fa9ae0fec1098 (diff) |
shared: Replace mgmt notify list with internal queue handling
Diffstat (limited to 'src')
-rw-r--r-- | src/shared/mgmt.c | 166 |
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; } |