Skip to content
This repository has been archived by the owner on Aug 19, 2021. It is now read-only.

Commit

Permalink
Added function for chaining event queues together
Browse files Browse the repository at this point in the history
The equeue_chain function chains one queue onto a target queue.
Calling equeue_dispatch on the target queue will also dispatch events
on the target, however each queue uses their own buffers and events
are handled independently.

The equeue_chain adds a very powerful level of composability for
equeues freely built on the equeue_background function. This allows
multiple modules to own their own event queues while maintaining
composability on threadless systems.
  • Loading branch information
geky committed Aug 7, 2016
1 parent bac1fb6 commit 3a55c74
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 1 deletion.
32 changes: 32 additions & 0 deletions equeue.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,3 +484,35 @@ void equeue_background(equeue_t *q,
q->background.active = true;
equeue_mutex_unlock(&q->queuelock);
}

struct equeue_chain_context {
equeue_t *q;
equeue_t *target;
int id;
};

static void equeue_chain_dispatch(void *p) {
equeue_dispatch((equeue_t *)p, 0);
}

static void equeue_chain_update(void *p, int ms) {
struct equeue_chain_context *c = (struct equeue_chain_context *)p;
equeue_cancel(c->target, c->id);

if (ms >= 0) {
c->id = equeue_call_in(c->target, ms, equeue_chain_dispatch, c->q);
} else {
equeue_dealloc(c->target, c);
}
}

void equeue_chain(equeue_t *q, equeue_t *target) {
struct equeue_chain_context *c = equeue_alloc(q,
sizeof(struct equeue_chain_context));

c->q = q;
c->target = target;
c->id = 0;

equeue_background(q, equeue_chain_update, c);
}
11 changes: 10 additions & 1 deletion equeue.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,19 @@ void equeue_cancel(equeue_t *queue, int event);
//
// The provided update function will be called to indicate when the queue
// should be dispatched. A negative timeout will be passed to the update
// function when the timer is no longer needed.
// function when the timer is no longer needed. A null update function
// will disable the existing timer.
void equeue_background(equeue_t *queue,
void (*update)(void *timer, int ms), void *timer);

// Chain an event queue onto another event queue
//
// After chaining a queue to a target, calling equeue_dispatch on the
// target queue will also dispatch events from this queue. The queues
// will use their own buffers and events are handled independently.
// A null queue as the target will unchain this queue.
void equeue_chain(equeue_t *queue, equeue_t *target);


#ifdef __cplusplus
}
Expand Down
38 changes: 38 additions & 0 deletions tests/tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,43 @@ void background_test(void) {
test_assert(ms == -1);
}

void chain_test(void) {
equeue_t q1;
int err = equeue_create(&q1, 2048);
test_assert(!err);

equeue_t q2;
err = equeue_create(&q2, 2048);
test_assert(!err);

equeue_chain(&q2, &q1);

int touched = 0;

int id1 = equeue_call_in(&q1, 20, simple_func, &touched);
int id2 = equeue_call_in(&q2, 20, simple_func, &touched);
test_assert(id1 && id2);

id1 = equeue_call(&q1, simple_func, &touched);
id2 = equeue_call(&q2, simple_func, &touched);
test_assert(id1 && id2);

id1 = equeue_call_in(&q1, 5, simple_func, &touched);
id2 = equeue_call_in(&q2, 5, simple_func, &touched);
test_assert(id1 && id2);

equeue_cancel(&q1, id1);
equeue_cancel(&q2, id2);

id1 = equeue_call_in(&q1, 10, simple_func, &touched);
id2 = equeue_call_in(&q2, 10, simple_func, &touched);
test_assert(id1 && id2);

equeue_dispatch(&q1, 30);

test_assert(touched == 6);
}

// Barrage tests
void simple_barrage_test(int N) {
equeue_t q;
Expand Down Expand Up @@ -621,6 +658,7 @@ int main() {
test_run(nested_test);
test_run(sloth_test);
test_run(background_test);
test_run(chain_test);
test_run(multithread_test);
test_run(simple_barrage_test, 20);
test_run(fragmenting_barrage_test, 20);
Expand Down

0 comments on commit 3a55c74

Please sign in to comment.