aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/event/multiqueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/event/multiqueue.c')
-rw-r--r--src/nvim/event/multiqueue.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/nvim/event/multiqueue.c b/src/nvim/event/multiqueue.c
index ef9f3f1870..a1b75f66a5 100644
--- a/src/nvim/event/multiqueue.c
+++ b/src/nvim/event/multiqueue.c
@@ -78,6 +78,13 @@ struct multiqueue {
size_t size;
};
+typedef struct {
+ Event event;
+ bool fired;
+ int refcount;
+} SplitEvent;
+
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/multiqueue.c.generated.h"
#endif
@@ -245,3 +252,33 @@ static MultiQueueItem *multiqueue_node_data(QUEUE *q)
{
return QUEUE_DATA(q, MultiQueueItem, node);
}
+
+/// Allow an event to be processed by multiple child queues to the main queue
+///
+/// The handler will be fired once by the _first_ queue that processes the
+/// event. Later processing will do nothing (just memory cleanup).
+///
+/// @param ev the event
+/// @param num number of queues that the split event will be put on
+/// @return an Event that is safe to put onto `num` queues
+Event event_split(Event ev, int num)
+{
+ SplitEvent *data = xmalloc(sizeof(*data));
+ data->event = ev;
+ data->fired = false;
+ data->refcount = num;
+ return event_create(split_event, 1, data);
+}
+static void split_event(void ** argv)
+{
+ SplitEvent *data = argv[0];
+ if (!data->fired) {
+ data->fired = true;
+ if (data->event.handler) {
+ data->event.handler(data->event.argv);
+ }
+ }
+ if ((--data->refcount) == 0) {
+ xfree(data);
+ }
+}