diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2020-11-29 20:45:18 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2020-11-29 20:45:18 +0200 |
commit | 42e0f735b48ab0f05e80eeec335684b25a93c4a3 (patch) | |
tree | 08dd50b85225caef48e427d12cf27f12467bab79 /libmailutils | |
parent | b28243aff348d58cd27a1f8e8fa066149537a2d0 (diff) | |
download | mailutils-42e0f735b48ab0f05e80eeec335684b25a93c4a3.tar.gz mailutils-42e0f735b48ab0f05e80eeec335684b25a93c4a3.tar.bz2 |
Optimize the observable interface
A bitmask of all requested event types is stored in the observable
structure. When an event is reported, mu_observable_notify first
check if the event type bit is set in that bitmap. If so, it starts
iterating over observers. That should allow us to avoid the loop in
most cases.
* include/mailutils/observer.h (mu_observable_wants): New proto.
* include/mailutils/sys/observer.h (_mu_observable): New member: types.
* libmailutils/base/observer.c (mu_observable_attach): Compute bitmask
of all types requested by attached observers.
(mu_observable_detach): Likewise.
(mu_observable_notify): Check if the event type is marked in the bitmap,
skip iteration if it is not.
(mu_observable_wants): New function.
Diffstat (limited to 'libmailutils')
-rw-r--r-- | libmailutils/base/observer.c | 60 |
1 files changed, 44 insertions, 16 deletions
diff --git a/libmailutils/base/observer.c b/libmailutils/base/observer.c index a2d8e9c51..f55da6e9f 100644 --- a/libmailutils/base/observer.c +++ b/libmailutils/base/observer.c @@ -169,9 +169,11 @@ mu_observable_get_owner (mu_observable_t observable) } int -mu_observable_attach (mu_observable_t observable, size_t type, mu_observer_t observer) +mu_observable_attach (mu_observable_t observable, size_t type, + mu_observer_t observer) { event_t event; + int rc; if (observable == NULL || observer == NULL) return EINVAL; event = calloc (1, sizeof (*event)); @@ -179,7 +181,14 @@ mu_observable_attach (mu_observable_t observable, size_t type, mu_observer_t ob return ENOMEM; event->type = type; event->observer = observer; - return mu_list_append (observable->list, event); + rc = mu_list_append (observable->list, event); + if (rc) + { + free (event); + return rc; + } + observable->types |= type; + return 0; } int @@ -188,7 +197,8 @@ mu_observable_detach (mu_observable_t observable, mu_observer_t observer) mu_iterator_t iterator; int status; event_t event = NULL; - + size_t types = 0; + if (observable == NULL || observer == NULL) return EINVAL; status = mu_list_get_iterator (observable->list, &iterator); @@ -204,10 +214,13 @@ mu_observable_detach (mu_observable_t observable, mu_observer_t observer) { mu_iterator_ctl (iterator, mu_itrctl_delete, NULL); status = 0; - break; } + else + types |= event->type; } mu_iterator_destroy (&iterator); + if (status == 0) + observable->types = types; return status; } @@ -217,21 +230,36 @@ mu_observable_notify (mu_observable_t observable, int type, void *data) mu_iterator_t iterator; event_t event = NULL; int status = 0; + if (observable == NULL) return EINVAL; - status = mu_list_get_iterator (observable->list, &iterator); - if (status != 0) - return status; - for (mu_iterator_first (iterator); !mu_iterator_is_done (iterator); - mu_iterator_next (iterator)) + if (observable->types & type) { - event = NULL; - mu_iterator_current (iterator, (void **)&event); - if (event && event->type & type) - { - status |= mu_observer_action (event->observer, type, data); - } + status = mu_list_get_iterator (observable->list, &iterator); + if (status != 0) + return status; + for (mu_iterator_first (iterator); !mu_iterator_is_done (iterator); + mu_iterator_next (iterator)) + { + event = NULL; + mu_iterator_current (iterator, (void **)&event); + if (event && event->type & type) + { + status = mu_observer_action (event->observer, type, data); + if (status) + break; + } + } + mu_iterator_destroy (&iterator); } - mu_iterator_destroy (&iterator); return status; } + +int +mu_observable_wants (mu_observable_t observable, int type) +{ + if (observable == NULL) + return 0; + return observable->types & type; +} + |