[Spice-devel] [RFC PATCH 1/4] notifiers: add support for async notifiers handlers
Alon Levy
alevy at redhat.com
Wed May 30 02:27:00 PDT 2012
On Wed, May 30, 2012 at 12:02:36PM +0300, Yonit Halperin wrote:
> Signed-off-by: Yonit Halperin <yhalperi at redhat.com>
One empty line that snuck in below.
> ---
> input.c | 2 +-
> migration.c | 2 +-
> notify.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
> notify.h | 55 ++++++++++++++++++++++++++++++++++++---
> qemu-timer.c | 2 +-
> vl.c | 2 +-
> 6 files changed, 129 insertions(+), 13 deletions(-)
>
> diff --git a/input.c b/input.c
> index 6968b31..06f6f9f 100644
> --- a/input.c
> +++ b/input.c
> @@ -274,5 +274,5 @@ void qemu_add_mouse_mode_change_notifier(Notifier *notify)
>
> void qemu_remove_mouse_mode_change_notifier(Notifier *notify)
> {
> - notifier_remove(notify);
> + notifier_remove(¬ify->base);
> }
> diff --git a/migration.c b/migration.c
> index 3f485d3..acaf293 100644
> --- a/migration.c
> +++ b/migration.c
> @@ -320,7 +320,7 @@ void add_migration_state_change_notifier(Notifier *notify)
>
> void remove_migration_state_change_notifier(Notifier *notify)
> {
> - notifier_remove(notify);
> + notifier_remove(¬ify->base);
> }
>
> bool migration_is_active(MigrationState *s)
> diff --git a/notify.c b/notify.c
> index 12282a6..dde190e 100644
> --- a/notify.c
> +++ b/notify.c
> @@ -19,23 +19,94 @@
> void notifier_list_init(NotifierList *list)
> {
> QLIST_INIT(&list->notifiers);
> + QLIST_INIT(&list->wait_notifiers);
> }
>
> void notifier_list_add(NotifierList *list, Notifier *notifier)
> {
> - QLIST_INSERT_HEAD(&list->notifiers, notifier, node);
> + notifier->base.type = NOTIFIER_TYPE_SYNC;
> + QLIST_INSERT_HEAD(&list->notifiers, ¬ifier->base, node);
> }
>
> -void notifier_remove(Notifier *notifier)
> +void notifier_list_add_async(NotifierList *list, AsyncNotifier *notifier)
> +{
> + notifier->base.type = NOTIFIER_TYPE_ASYNC;
> + QLIST_INSERT_HEAD(&list->notifiers, ¬ifier->base, node);
> +}
> +
> +void notifier_remove(BaseNotifier *notifier)
> {
> QLIST_REMOVE(notifier, node);
> }
>
> +static void notified_complete_cb(AsyncNotifier *notifier, void *opaque)
> +{
> + NotifierList *list = opaque;
> +
> + QLIST_REMOVE(notifier, wait_node);
> +
> + if (QLIST_EMPTY(&list->wait_notifiers) && !list->during_notify) {
> + if (list->complete_cb) {
> + list->complete_cb(list->complete_opaque);
> + }
> + }
> +}
> +
> void notifier_list_notify(NotifierList *list, void *data)
> {
> - Notifier *notifier, *next;
> + BaseNotifier *notifier, *next;
> + bool async = false;
> +
> + if (notifier_list_async_waiting(list)) {
> + AsyncNotifier *wait_notifier, *wait_next;
> +
> + fprintf(stderr, "%s: previous notify hasn't completed\n", __func__);
> + QLIST_FOREACH_SAFE(wait_notifier, &list->wait_notifiers,
> + wait_node, wait_next) {
> + QLIST_REMOVE(wait_notifier, wait_node);
> + }
> +
Unnecessary empty line.
> + }
> +
> + list->during_notify = true;
>
> QLIST_FOREACH_SAFE(notifier, &list->notifiers, node, next) {
> - notifier->notify(notifier, data);
> + switch (notifier->type) {
> + case NOTIFIER_TYPE_SYNC:
> + {
> + Notifier *sync_notifier;
> +
> + sync_notifier = container_of(notifier, Notifier, base);
> + sync_notifier->notify(sync_notifier, data);
> + break;
> + }
> + case NOTIFIER_TYPE_ASYNC:
> + {
> + AsyncNotifier *async_notifier;
> +
> + async = true;
> + async_notifier = container_of(notifier, AsyncNotifier, base);
> + QLIST_INSERT_HEAD(&list->wait_notifiers,
> + async_notifier,
> + wait_node);
> + async_notifier->notify_async(async_notifier, data,
> + notified_complete_cb, list);
> + break;
> + }
> + default:
> + fprintf(stderr, "%s: invalid notifier type %d\n", __func__,
> + notifier->type);
> + break;
> + }
> }
> +
> + list->during_notify = false;
> + if ((!async || !notifier_list_async_waiting(list)) && list->complete_cb) {
> + list->complete_cb(list->complete_opaque);
> + }
> +}
> +
> +bool notifier_list_async_waiting(NotifierList *list)
> +{
> + return !QLIST_EMPTY(&list->wait_notifiers);
> }
> diff --git a/notify.h b/notify.h
> index 03cf26c..8660920 100644
> --- a/notify.h
> +++ b/notify.h
> @@ -16,28 +16,73 @@
>
> #include "qemu-queue.h"
>
> +typedef enum NotifierType {
> + NOTIFIER_TYPE_NONE,
> + NOTIFIER_TYPE_SYNC,
> + NOTIFIER_TYPE_ASYNC,
> +} NotifierType;
> +
> +typedef struct BaseNotifier BaseNotifier;
> +
> +struct BaseNotifier {
> + QLIST_ENTRY(BaseNotifier) node;
> + NotifierType type;
> +};
> typedef struct Notifier Notifier;
>
> struct Notifier
> {
> + BaseNotifier base;
> void (*notify)(Notifier *notifier, void *data);
> - QLIST_ENTRY(Notifier) node;
> };
>
> +typedef struct AsyncNotifier AsyncNotifier;
> +typedef void (NotifiedCompletionFunc)(AsyncNotifier *notifier, void *opaque);
> +
> +struct AsyncNotifier {
> + BaseNotifier base;
> + void (*notify_async)(AsyncNotifier *notifier, void *data,
> + NotifiedCompletionFunc *complete_cb, void *cb_data);
> + QLIST_ENTRY(AsyncNotifier) wait_node;
> +};
> +
> +typedef void (NotifyListCompletion)(void *opaque);
> +
> typedef struct NotifierList
> {
> - QLIST_HEAD(, Notifier) notifiers;
> + QLIST_HEAD(, BaseNotifier) notifiers;
> +
> + NotifyListCompletion *complete_cb;
> + void *complete_opaque;
> +
> + QLIST_HEAD(, AsyncNotifier) wait_notifiers;
> + bool during_notify;
> } NotifierList;
>
> -#define NOTIFIER_LIST_INITIALIZER(head) \
> - { QLIST_HEAD_INITIALIZER((head).notifiers) }
> +#define NOTIFIER_LIST_INITIALIZER(head) \
> + { QLIST_HEAD_INITIALIZER((head).notifiers), \
> + NULL, \
> + NULL, \
> + QLIST_HEAD_INITIALIZER((head).wait_notifiers) \
> + }
>
> +#define ASYNC_NOTIFIER_LIST_INITIALIZER(head, cb, cb_data) \
> + { QLIST_HEAD_INITIALIZER((head).notifiers), \
> + cb, \
> + cb_data, \
> + QLIST_HEAD_INITIALIZER((head).wait_notifiers) \
> + }
> void notifier_list_init(NotifierList *list);
>
> void notifier_list_add(NotifierList *list, Notifier *notifier);
> +void notifier_list_add_async(NotifierList *list, AsyncNotifier *notifier);
>
> -void notifier_remove(Notifier *notifier);
> +void notifier_remove(BaseNotifier *notifier);
>
> void notifier_list_notify(NotifierList *list, void *data);
>
> +/* returns true when there are async notifiers that still hasn't
> + * called complete_cb for the last notification */
> +bool notifier_list_async_waiting(NotifierList *list);
> +
> #endif
> diff --git a/qemu-timer.c b/qemu-timer.c
> index de98977..2b2f84a 100644
> --- a/qemu-timer.c
> +++ b/qemu-timer.c
> @@ -430,7 +430,7 @@ void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
>
> void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
> {
> - notifier_remove(notifier);
> + notifier_remove(¬ifier->base);
> }
>
> void init_clocks(void)
> diff --git a/vl.c b/vl.c
> index 23ab3a3..646b16b 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -2183,7 +2183,7 @@ void qemu_add_exit_notifier(Notifier *notify)
>
> void qemu_remove_exit_notifier(Notifier *notify)
> {
> - notifier_remove(notify);
> + notifier_remove(¬ify->base);
> }
>
> static void qemu_run_exit_notifiers(void)
> --
> 1.7.7.6
>
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
More information about the Spice-devel
mailing list