summaryrefslogtreecommitdiff
path: root/libmailutils
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2020-11-29 20:45:18 +0200
committerSergey Poznyakoff <gray@gnu.org>2020-11-29 20:45:18 +0200
commit42e0f735b48ab0f05e80eeec335684b25a93c4a3 (patch)
tree08dd50b85225caef48e427d12cf27f12467bab79 /libmailutils
parentb28243aff348d58cd27a1f8e8fa066149537a2d0 (diff)
downloadmailutils-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.c60
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;
+}
+

Return to:

Send suggestions and report system problems to the System administrator.