diff options
Diffstat (limited to 'src/nvim/event/multiqueue.c')
-rw-r--r-- | src/nvim/event/multiqueue.c | 93 |
1 files changed, 50 insertions, 43 deletions
diff --git a/src/nvim/event/multiqueue.c b/src/nvim/event/multiqueue.c index b144347fdb..a479a032f4 100644 --- a/src/nvim/event/multiqueue.c +++ b/src/nvim/event/multiqueue.c @@ -127,6 +127,7 @@ void multiqueue_free(MultiQueue *this) xfree(this); } +/// Removes the next item and returns its Event. Event multiqueue_get(MultiQueue *this) { return multiqueue_empty(this) ? NILEVENT : multiqueue_remove(this); @@ -145,45 +146,38 @@ void multiqueue_process_events(MultiQueue *this) { assert(this); while (!multiqueue_empty(this)) { - Event event = multiqueue_get(this); + Event event = multiqueue_remove(this); if (event.handler) { event.handler(event.argv); } } } -void multiqueue_process_debug(MultiQueue *this) +void multiqueue_process_priority(MultiQueue *this, int priority) { assert(this); QUEUE *start = QUEUE_HEAD(&this->headtail); - QUEUE *cur = start; - // MultiQueue *start = this; - // MultiQueue *cur = start; - do { + QUEUE *cur = start; + while (!multiqueue_empty(this)) { MultiQueueItem *item = multiqueue_node_data(cur); - Event ev; - if (item->link) { - assert(!this->parent); - // get the next node in the linked queue - MultiQueue *linked = item->data.queue; - assert(!multiqueue_empty(linked)); - MultiQueueItem *child = - multiqueue_node_data(QUEUE_HEAD(&linked->headtail)); - ev = child->data.item.event; + assert(!item->link || !this->parent); // Only a parent queue has link-nodes + Event ev = multiqueueitem_get_event(item, false); + + if (ev.priority >= priority) { + if (ev.handler) { + ev.handler(ev.argv); + } + // Processed. Remove this item and get the new head. + (void)multiqueue_remove(this); + cur = QUEUE_HEAD(&this->headtail); } else { - ev = item->data.item.event; + // Not processed. Skip this item and get the next one. + cur = cur->next->next; + if (!cur || cur == start) { + break; + } } - - // Event event = multiqueue_get(this); - // if (event.handler) { - // event.handler(event.argv); - // } - - ILOG("ev: priority=%d, handler=%p arg1=%s", ev.priority, ev.handler, - ev.argv ? ev.argv[0] : "(null)"); - - cur = cur->next; - } while (cur && cur != start); + } } /// Removes all events without processing them. @@ -213,36 +207,48 @@ size_t multiqueue_size(MultiQueue *this) return this->size; } -static Event multiqueue_remove(MultiQueue *this) +/// Gets an Event from an item. +/// +/// @param remove Remove the node from its queue, and free it. +static Event multiqueueitem_get_event(MultiQueueItem *item, bool remove) { - assert(!multiqueue_empty(this)); - QUEUE *h = QUEUE_HEAD(&this->headtail); - QUEUE_REMOVE(h); - MultiQueueItem *item = multiqueue_node_data(h); - Event rv; - + assert(item != NULL); + Event ev; if (item->link) { - assert(!this->parent); - // remove the next node in the linked queue + // get the next node in the linked queue MultiQueue *linked = item->data.queue; assert(!multiqueue_empty(linked)); MultiQueueItem *child = multiqueue_node_data(QUEUE_HEAD(&linked->headtail)); - QUEUE_REMOVE(&child->node); - rv = child->data.item.event; - xfree(child); + ev = child->data.item.event; + // remove the child node + if (remove) { + QUEUE_REMOVE(&child->node); + xfree(child); + } } else { - if (this->parent) { - // remove the corresponding link node in the parent queue + // remove the corresponding link node in the parent queue + if (remove && item->data.item.parent_item) { QUEUE_REMOVE(&item->data.item.parent_item->node); xfree(item->data.item.parent_item); + item->data.item.parent_item = NULL; } - rv = item->data.item.event; + ev = item->data.item.event; } + return ev; +} +static Event multiqueue_remove(MultiQueue *this) +{ + assert(!multiqueue_empty(this)); + QUEUE *h = QUEUE_HEAD(&this->headtail); + QUEUE_REMOVE(h); + MultiQueueItem *item = multiqueue_node_data(h); + assert(!item->link || !this->parent); // Only a parent queue has link-nodes + Event ev = multiqueueitem_get_event(item, true); this->size--; xfree(item); - return rv; + return ev; } static void multiqueue_push(MultiQueue *this, Event event) @@ -250,6 +256,7 @@ static void multiqueue_push(MultiQueue *this, Event event) MultiQueueItem *item = xmalloc(sizeof(MultiQueueItem)); item->link = false; item->data.item.event = event; + item->data.item.parent_item = NULL; QUEUE_INSERT_TAIL(&this->headtail, &item->node); if (this->parent) { // push link node to the parent queue |