shl: hook: add 'oneshot' flag
If an entry is marked as 'oneshot' then it will get deleted after it has been called once. Note that the entry is unlinked _before_ the callback is called. If you use 'oneshot'-entries and normal entries with the same cb+data combination, then you will probably get unexpected behavior. It is not recommended to do that. In detail, you cannot control which entry is deleted via a shl_hook_rm() call so you can never be sure whether the oneshot entry or a normal entry is deleted. Do not mix oneshot entries with normal entries! Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
parent
8fa28926cb
commit
5ee2338b60
10
src/eloop.c
10
src/eloop.c
@ -2196,7 +2196,7 @@ int ev_eloop_register_signal_cb(struct ev_eloop *loop, int signum,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = shl_hook_add_cast(sig->hook, cb, data);
|
||||
ret = shl_hook_add_cast(sig->hook, cb, data, false);
|
||||
if (ret) {
|
||||
signal_free(sig);
|
||||
return ret;
|
||||
@ -2257,7 +2257,7 @@ int ev_eloop_register_child_cb(struct ev_eloop *loop, ev_child_cb cb,
|
||||
return -EINVAL;
|
||||
|
||||
empty = !shl_hook_num(loop->chlds);
|
||||
ret = shl_hook_add_cast(loop->chlds, cb, data);
|
||||
ret = shl_hook_add_cast(loop->chlds, cb, data, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -2311,7 +2311,7 @@ int ev_eloop_register_idle_cb(struct ev_eloop *eloop, ev_idle_cb cb,
|
||||
if (!eloop)
|
||||
return -EINVAL;
|
||||
|
||||
ret = shl_hook_add_cast(eloop->idlers, cb, data);
|
||||
ret = shl_hook_add_cast(eloop->idlers, cb, data, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -2371,7 +2371,7 @@ int ev_eloop_register_pre_cb(struct ev_eloop *eloop, ev_idle_cb cb,
|
||||
if (!eloop)
|
||||
return -EINVAL;
|
||||
|
||||
return shl_hook_add_cast(eloop->pres, cb, data);
|
||||
return shl_hook_add_cast(eloop->pres, cb, data, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2420,7 +2420,7 @@ int ev_eloop_register_post_cb(struct ev_eloop *eloop, ev_idle_cb cb,
|
||||
if (!eloop)
|
||||
return -EINVAL;
|
||||
|
||||
return shl_hook_add_cast(eloop->posts, cb, data);
|
||||
return shl_hook_add_cast(eloop->posts, cb, data, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,8 +43,8 @@ struct shl_hook;
|
||||
struct shl_hook_entry;
|
||||
typedef void (*shl_hook_cb) (void *parent, void *arg, void *data);
|
||||
|
||||
#define shl_hook_add_cast(hook, cb, data) \
|
||||
shl_hook_add((hook), (shl_hook_cb)(cb), (data))
|
||||
#define shl_hook_add_cast(hook, cb, data, oneshot) \
|
||||
shl_hook_add((hook), (shl_hook_cb)(cb), (data), (oneshot))
|
||||
#define shl_hook_rm_cast(hook, cb, data) \
|
||||
shl_hook_rm((hook), (shl_hook_cb)(cb), (data))
|
||||
|
||||
@ -52,6 +52,7 @@ struct shl_hook_entry {
|
||||
struct shl_dlist list;
|
||||
shl_hook_cb cb;
|
||||
void *data;
|
||||
bool oneshot;
|
||||
};
|
||||
|
||||
struct shl_hook {
|
||||
@ -110,7 +111,7 @@ static inline unsigned int shl_hook_num(struct shl_hook *hook)
|
||||
}
|
||||
|
||||
static inline int shl_hook_add(struct shl_hook *hook, shl_hook_cb cb,
|
||||
void *data)
|
||||
void *data, bool oneshot)
|
||||
{
|
||||
struct shl_hook_entry *entry;
|
||||
|
||||
@ -123,14 +124,18 @@ static inline int shl_hook_add(struct shl_hook *hook, shl_hook_cb cb,
|
||||
memset(entry, 0, sizeof(*entry));
|
||||
entry->cb = cb;
|
||||
entry->data = data;
|
||||
entry->oneshot = oneshot;
|
||||
|
||||
shl_dlist_link_tail(&hook->entries, &entry->list);
|
||||
hook->num++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This adds an entry only if it is not already in the list. But notice that if
|
||||
* the entry is already registered twice or with a different \oneshot flag, the
|
||||
* list will _not_ be changed! */
|
||||
static inline int shl_hook_add_single(struct shl_hook *hook, shl_hook_cb cb,
|
||||
void *data)
|
||||
void *data, bool oneshot)
|
||||
{
|
||||
struct shl_hook_entry *entry;
|
||||
struct shl_dlist *iter;
|
||||
@ -144,7 +149,7 @@ static inline int shl_hook_add_single(struct shl_hook *hook, shl_hook_cb cb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
return shl_hook_add(hook, cb, data);
|
||||
return shl_hook_add(hook, cb, data, oneshot);
|
||||
}
|
||||
|
||||
static inline void shl_hook_rm(struct shl_hook *hook, shl_hook_cb cb,
|
||||
@ -204,9 +209,17 @@ static inline void shl_hook_call(struct shl_hook *hook, void *parent,
|
||||
hook->cur_entry != &hook->entries; ) {
|
||||
entry = shl_dlist_entry(hook->cur_entry,
|
||||
struct shl_hook_entry, list);
|
||||
hook->cur_entry = entry->list.next;
|
||||
|
||||
if (entry->oneshot)
|
||||
shl_dlist_unlink(&entry->list);
|
||||
|
||||
entry->cb(parent, arg, entry->data);
|
||||
if (hook->cur_entry == &entry->list)
|
||||
hook->cur_entry = hook->cur_entry->next;
|
||||
|
||||
if (entry->oneshot) {
|
||||
free(entry);
|
||||
--hook->num;
|
||||
}
|
||||
}
|
||||
|
||||
hook->cur_entry = NULL;
|
||||
|
@ -394,7 +394,7 @@ int uterm_input_register_cb(struct uterm_input *input,
|
||||
if (!input || !cb)
|
||||
return -EINVAL;
|
||||
|
||||
return shl_hook_add_cast(input->hook, cb, data);
|
||||
return shl_hook_add_cast(input->hook, cb, data, false);
|
||||
}
|
||||
|
||||
void uterm_input_unregister_cb(struct uterm_input *input,
|
||||
|
@ -324,7 +324,7 @@ int uterm_display_register_cb(struct uterm_display *disp, uterm_display_cb cb,
|
||||
if (!disp)
|
||||
return -EINVAL;
|
||||
|
||||
return shl_hook_add_cast(disp->hook, cb, data);
|
||||
return shl_hook_add_cast(disp->hook, cb, data, false);
|
||||
}
|
||||
|
||||
void uterm_display_unregister_cb(struct uterm_display *disp,
|
||||
@ -589,7 +589,7 @@ int uterm_video_register_cb(struct uterm_video *video, uterm_video_cb cb,
|
||||
if (!video || !cb)
|
||||
return -EINVAL;
|
||||
|
||||
return shl_hook_add_cast(video->hook, cb, data);
|
||||
return shl_hook_add_cast(video->hook, cb, data, false);
|
||||
}
|
||||
|
||||
void uterm_video_unregister_cb(struct uterm_video *video, uterm_video_cb cb,
|
||||
|
Loading…
x
Reference in New Issue
Block a user