aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/event/queue.c
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2016-09-29 17:09:37 +0200
committerJustin M. Keyes <justinkz@gmail.com>2016-10-02 00:24:49 +0200
commit6186df3562e33e92f04ed8c850204ceabc4746e1 (patch)
tree90cc5779b0ba395e1b07069573ddb836a7d9de1f /src/nvim/event/queue.c
parentc8b6ec2e6a8599203b4cff762f148f62464d9725 (diff)
downloadrneovim-6186df3562e33e92f04ed8c850204ceabc4746e1.tar.gz
rneovim-6186df3562e33e92f04ed8c850204ceabc4746e1.tar.bz2
rneovim-6186df3562e33e92f04ed8c850204ceabc4746e1.zip
event/multiqueue.c: Rename "queue" to "multiqueue".
`lib/queue.h` implements a basic queue. `event/queue.c` implements a specialized data structure on top of lib/queue.h; it is not a "normal" queue. Rename the specialized multi-level queue implemented in event/queue.c to "multiqueue", to avoid confusion when reading the code. Before this change one can eventually notice that "macros (uppercase symbols) are for the normal queue, lowercase operations are for the multi-level queue", but that is unnecessary friction for new developers (or existing developers just visiting this part of the codebase).
Diffstat (limited to 'src/nvim/event/queue.c')
-rw-r--r--src/nvim/event/queue.c208
1 files changed, 0 insertions, 208 deletions
diff --git a/src/nvim/event/queue.c b/src/nvim/event/queue.c
deleted file mode 100644
index ee224b0a25..0000000000
--- a/src/nvim/event/queue.c
+++ /dev/null
@@ -1,208 +0,0 @@
-// Queue for selective async event processing. Instances of this queue support a
-// parent/child relationship with the following properties:
-//
-// - pushing a node to a child queue will push a corresponding link node to the
-// parent queue
-// - removing a link node from a parent queue will remove the next node
-// in the linked child queue
-// - removing a node from a child queue will remove the corresponding link node
-// in the parent queue
-//
-// These properties allow Nvim to organize and process events from different
-// sources with a certain degree of control. Here's how the queue is used:
-//
-// +----------------+
-// | Main loop |
-// +----------------+
-// ^
-// |
-// +----------------+
-// +-------------->| Event loop |<------------+
-// | +--+-------------+ |
-// | ^ ^ |
-// | | | |
-// +-----------+ +-----------+ +---------+ +---------+
-// | Channel 1 | | Channel 2 | | Job 1 | | Job 2 |
-// +-----------+ +-----------+ +---------+ +---------+
-//
-//
-// The lower boxes represents event emitters, each with its own private queue
-// having the event loop queue as the parent.
-//
-// When idle, the main loop spins the event loop which queues events from many
-// sources (channels, jobs, user...). Each event emitter pushes events to its
-// private queue which is propagated to the event loop queue. When the main loop
-// consumes an event, the corresponding event is removed from the emitter's
-// queue.
-//
-// The main reason for this queue hierarchy is to allow focusing on a single
-// event emitter while blocking the main loop. For example, if the `jobwait`
-// VimL function is called on job1, the main loop will temporarily stop polling
-// the event loop queue and poll job1 queue instead. Same with channels, when
-// calling `rpcrequest` we want to temporarily stop processing events from
-// other sources and focus on a specific channel.
-
-#include <assert.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdint.h>
-
-
-#include <uv.h>
-
-#include "nvim/event/queue.h"
-#include "nvim/memory.h"
-#include "nvim/os/time.h"
-
-typedef struct queue_item QueueItem;
-struct queue_item {
- union {
- Queue *queue;
- struct {
- Event event;
- QueueItem *parent;
- } item;
- } data;
- bool link; // this is just a link to a node in a child queue
- QUEUE node;
-};
-
-struct queue {
- Queue *parent;
- QUEUE headtail;
- put_callback put_cb;
- void *data;
-};
-
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "event/queue.c.generated.h"
-#endif
-
-static Event NILEVENT = {.handler = NULL, .argv = {NULL}};
-
-Queue *queue_new_parent(put_callback put_cb, void *data)
-{
- return queue_new(NULL, put_cb, data);
-}
-
-Queue *queue_new_child(Queue *parent)
- FUNC_ATTR_NONNULL_ALL
-{
- assert(!parent->parent);
- return queue_new(parent, NULL, NULL);
-}
-
-static Queue *queue_new(Queue *parent, put_callback put_cb, void *data)
-{
- Queue *rv = xmalloc(sizeof(Queue));
- QUEUE_INIT(&rv->headtail);
- rv->parent = parent;
- rv->put_cb = put_cb;
- rv->data = data;
- return rv;
-}
-
-void queue_free(Queue *queue)
-{
- assert(queue);
- while (!QUEUE_EMPTY(&queue->headtail)) {
- QUEUE *q = QUEUE_HEAD(&queue->headtail);
- QueueItem *item = queue_node_data(q);
- if (queue->parent) {
- QUEUE_REMOVE(&item->data.item.parent->node);
- xfree(item->data.item.parent);
- }
- QUEUE_REMOVE(q);
- xfree(item);
- }
-
- xfree(queue);
-}
-
-Event queue_get(Queue *queue)
-{
- return queue_empty(queue) ? NILEVENT : queue_remove(queue);
-}
-
-void queue_put_event(Queue *queue, Event event)
-{
- assert(queue);
- queue_push(queue, event);
- if (queue->parent && queue->parent->put_cb) {
- queue->parent->put_cb(queue->parent, queue->parent->data);
- }
-}
-
-void queue_process_events(Queue *queue)
-{
- assert(queue);
- while (!queue_empty(queue)) {
- Event event = queue_get(queue);
- if (event.handler) {
- event.handler(event.argv);
- }
- }
-}
-
-bool queue_empty(Queue *queue)
-{
- assert(queue);
- return QUEUE_EMPTY(&queue->headtail);
-}
-
-void queue_replace_parent(Queue *queue, Queue *new_parent)
-{
- assert(queue_empty(queue));
- queue->parent = new_parent;
-}
-
-static Event queue_remove(Queue *queue)
-{
- assert(!queue_empty(queue));
- QUEUE *h = QUEUE_HEAD(&queue->headtail);
- QUEUE_REMOVE(h);
- QueueItem *item = queue_node_data(h);
- Event rv;
-
- if (item->link) {
- assert(!queue->parent);
- // remove the next node in the linked queue
- Queue *linked = item->data.queue;
- assert(!queue_empty(linked));
- QueueItem *child =
- queue_node_data(QUEUE_HEAD(&linked->headtail));
- QUEUE_REMOVE(&child->node);
- rv = child->data.item.event;
- xfree(child);
- } else {
- if (queue->parent) {
- // remove the corresponding link node in the parent queue
- QUEUE_REMOVE(&item->data.item.parent->node);
- xfree(item->data.item.parent);
- }
- rv = item->data.item.event;
- }
-
- xfree(item);
- return rv;
-}
-
-static void queue_push(Queue *queue, Event event)
-{
- QueueItem *item = xmalloc(sizeof(QueueItem));
- item->link = false;
- item->data.item.event = event;
- QUEUE_INSERT_TAIL(&queue->headtail, &item->node);
- if (queue->parent) {
- // push link node to the parent queue
- item->data.item.parent = xmalloc(sizeof(QueueItem));
- item->data.item.parent->link = true;
- item->data.item.parent->data.queue = queue;
- QUEUE_INSERT_TAIL(&queue->parent->headtail, &item->data.item.parent->node);
- }
-}
-
-static QueueItem *queue_node_data(QUEUE *q)
-{
- return QUEUE_DATA(q, QueueItem, node);
-}