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;
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;
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;
if (!eloop)
return -EINVAL;
- return shl_hook_add_cast(eloop->pres, cb, data);
+ return shl_hook_add_cast(eloop->pres, cb, data, false);
}
/**
if (!eloop)
return -EINVAL;
- return shl_hook_add_cast(eloop->posts, cb, data);
+ return shl_hook_add_cast(eloop->posts, cb, data, false);
}
/**
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))
struct shl_dlist list;
shl_hook_cb cb;
void *data;
+ bool oneshot;
};
struct shl_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;
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;
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,
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;
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,
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,