Use cbuf for control event queue
Replace the control_event_queue implementation by cbuf.
This commit is contained in:
parent
b38292cd69
commit
241a3dcba5
6 changed files with 14 additions and 190 deletions
|
@ -157,10 +157,6 @@ tests = [
|
|||
['test_cbuf', [
|
||||
'tests/test_cbuf.c',
|
||||
]],
|
||||
['test_control_event_queue', [
|
||||
'tests/test_control_event_queue.c',
|
||||
'src/control_event.c'
|
||||
]],
|
||||
['test_control_event_serialize', [
|
||||
'tests/test_control_event_serialize.c',
|
||||
'src/control_event.c'
|
||||
|
|
|
@ -58,52 +58,3 @@ control_event_destroy(struct control_event *event) {
|
|||
SDL_free(event->text_event.text);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
control_event_queue_is_empty(const struct control_event_queue *queue) {
|
||||
return queue->head == queue->tail;
|
||||
}
|
||||
|
||||
bool
|
||||
control_event_queue_is_full(const struct control_event_queue *queue) {
|
||||
return (queue->head + 1) % CONTROL_EVENT_QUEUE_SIZE == queue->tail;
|
||||
}
|
||||
|
||||
bool
|
||||
control_event_queue_init(struct control_event_queue *queue) {
|
||||
queue->head = 0;
|
||||
queue->tail = 0;
|
||||
// the current implementation may not fail
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
control_event_queue_destroy(struct control_event_queue *queue) {
|
||||
int i = queue->tail;
|
||||
while (i != queue->head) {
|
||||
control_event_destroy(&queue->data[i]);
|
||||
i = (i + 1) % CONTROL_EVENT_QUEUE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
control_event_queue_push(struct control_event_queue *queue,
|
||||
const struct control_event *event) {
|
||||
if (control_event_queue_is_full(queue)) {
|
||||
return false;
|
||||
}
|
||||
queue->data[queue->head] = *event;
|
||||
queue->head = (queue->head + 1) % CONTROL_EVENT_QUEUE_SIZE;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
control_event_queue_take(struct control_event_queue *queue,
|
||||
struct control_event *event) {
|
||||
if (control_event_queue_is_empty(queue)) {
|
||||
return false;
|
||||
}
|
||||
*event = queue->data[queue->tail];
|
||||
queue->tail = (queue->tail + 1) % CONTROL_EVENT_QUEUE_SIZE;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "android/keycodes.h"
|
||||
#include "common.h"
|
||||
|
||||
#define CONTROL_EVENT_QUEUE_SIZE 64
|
||||
#define CONTROL_EVENT_TEXT_MAX_LENGTH 300
|
||||
#define CONTROL_EVENT_SERIALIZED_MAX_SIZE (3 + CONTROL_EVENT_TEXT_MAX_LENGTH)
|
||||
|
||||
|
@ -54,38 +53,11 @@ struct control_event {
|
|||
};
|
||||
};
|
||||
|
||||
struct control_event_queue {
|
||||
struct control_event data[CONTROL_EVENT_QUEUE_SIZE];
|
||||
int head;
|
||||
int tail;
|
||||
};
|
||||
|
||||
// buf size must be at least CONTROL_EVENT_SERIALIZED_MAX_SIZE
|
||||
// return the number of bytes written
|
||||
size_t
|
||||
control_event_serialize(const struct control_event *event, unsigned char *buf);
|
||||
|
||||
bool
|
||||
control_event_queue_init(struct control_event_queue *queue);
|
||||
|
||||
void
|
||||
control_event_queue_destroy(struct control_event_queue *queue);
|
||||
|
||||
bool
|
||||
control_event_queue_is_empty(const struct control_event_queue *queue);
|
||||
|
||||
bool
|
||||
control_event_queue_is_full(const struct control_event_queue *queue);
|
||||
|
||||
// the event is "moved": the queue takes ownership of its fields
|
||||
bool
|
||||
control_event_queue_push(struct control_event_queue *queue,
|
||||
const struct control_event *event);
|
||||
|
||||
bool
|
||||
control_event_queue_take(struct control_event_queue *queue,
|
||||
struct control_event *event);
|
||||
|
||||
void
|
||||
control_event_destroy(struct control_event *event);
|
||||
|
||||
|
|
|
@ -8,9 +8,7 @@
|
|||
|
||||
bool
|
||||
controller_init(struct controller *controller, socket_t video_socket) {
|
||||
if (!control_event_queue_init(&controller->queue)) {
|
||||
return false;
|
||||
}
|
||||
cbuf_init(&controller->queue);
|
||||
|
||||
if (!(controller->mutex = SDL_CreateMutex())) {
|
||||
return false;
|
||||
|
@ -31,16 +29,19 @@ void
|
|||
controller_destroy(struct controller *controller) {
|
||||
SDL_DestroyCond(controller->event_cond);
|
||||
SDL_DestroyMutex(controller->mutex);
|
||||
control_event_queue_destroy(&controller->queue);
|
||||
|
||||
struct control_event event;
|
||||
while (cbuf_take(&controller->queue, &event)) {
|
||||
control_event_destroy(&event);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
controller_push_event(struct controller *controller,
|
||||
const struct control_event *event) {
|
||||
bool res;
|
||||
mutex_lock(controller->mutex);
|
||||
bool was_empty = control_event_queue_is_empty(&controller->queue);
|
||||
res = control_event_queue_push(&controller->queue, event);
|
||||
bool was_empty = cbuf_is_empty(&controller->queue);
|
||||
bool res = cbuf_push(&controller->queue, *event);
|
||||
if (was_empty) {
|
||||
cond_signal(controller->event_cond);
|
||||
}
|
||||
|
@ -66,8 +67,7 @@ run_controller(void *data) {
|
|||
|
||||
for (;;) {
|
||||
mutex_lock(controller->mutex);
|
||||
while (!controller->stopped
|
||||
&& control_event_queue_is_empty(&controller->queue)) {
|
||||
while (!controller->stopped && cbuf_is_empty(&controller->queue)) {
|
||||
cond_wait(controller->event_cond, controller->mutex);
|
||||
}
|
||||
if (controller->stopped) {
|
||||
|
@ -76,8 +76,7 @@ run_controller(void *data) {
|
|||
break;
|
||||
}
|
||||
struct control_event event;
|
||||
bool non_empty = control_event_queue_take(&controller->queue,
|
||||
&event);
|
||||
bool non_empty = cbuf_take(&controller->queue, &event);
|
||||
SDL_assert(non_empty);
|
||||
mutex_unlock(controller->mutex);
|
||||
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
#ifndef CONTROL_H
|
||||
#define CONTROL_H
|
||||
|
||||
#include "control_event.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <SDL2/SDL_mutex.h>
|
||||
#include <SDL2/SDL_thread.h>
|
||||
|
||||
#include "cbuf.h"
|
||||
#include "control_event.h"
|
||||
#include "net.h"
|
||||
|
||||
struct control_event_queue CBUF(struct control_event, 64);
|
||||
|
||||
struct controller {
|
||||
socket_t video_socket;
|
||||
SDL_Thread *thread;
|
||||
|
@ -33,7 +35,6 @@ controller_stop(struct controller *controller);
|
|||
void
|
||||
controller_join(struct controller *controller);
|
||||
|
||||
// expose simple API to hide control_event_queue
|
||||
bool
|
||||
controller_push_event(struct controller *controller,
|
||||
const struct control_event *event);
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "control_event.h"
|
||||
|
||||
static void test_control_event_queue_empty(void) {
|
||||
struct control_event_queue queue;
|
||||
bool init_ok = control_event_queue_init(&queue);
|
||||
assert(init_ok);
|
||||
|
||||
assert(control_event_queue_is_empty(&queue));
|
||||
|
||||
struct control_event dummy_event;
|
||||
bool push_ok = control_event_queue_push(&queue, &dummy_event);
|
||||
assert(push_ok);
|
||||
assert(!control_event_queue_is_empty(&queue));
|
||||
|
||||
bool take_ok = control_event_queue_take(&queue, &dummy_event);
|
||||
assert(take_ok);
|
||||
assert(control_event_queue_is_empty(&queue));
|
||||
|
||||
bool take_empty_ok = control_event_queue_take(&queue, &dummy_event);
|
||||
assert(!take_empty_ok); // the queue is empty
|
||||
|
||||
control_event_queue_destroy(&queue);
|
||||
}
|
||||
|
||||
static void test_control_event_queue_full(void) {
|
||||
struct control_event_queue queue;
|
||||
bool init_ok = control_event_queue_init(&queue);
|
||||
assert(init_ok);
|
||||
|
||||
assert(!control_event_queue_is_full(&queue));
|
||||
|
||||
struct control_event dummy_event;
|
||||
// fill the queue
|
||||
while (control_event_queue_push(&queue, &dummy_event));
|
||||
|
||||
bool take_ok = control_event_queue_take(&queue, &dummy_event);
|
||||
assert(take_ok);
|
||||
assert(!control_event_queue_is_full(&queue));
|
||||
|
||||
control_event_queue_destroy(&queue);
|
||||
}
|
||||
|
||||
static void test_control_event_queue_push_take(void) {
|
||||
struct control_event_queue queue;
|
||||
bool init_ok = control_event_queue_init(&queue);
|
||||
assert(init_ok);
|
||||
|
||||
struct control_event event = {
|
||||
.type = CONTROL_EVENT_TYPE_KEYCODE,
|
||||
.keycode_event = {
|
||||
.action = AKEY_EVENT_ACTION_DOWN,
|
||||
.keycode = AKEYCODE_ENTER,
|
||||
.metastate = AMETA_CTRL_LEFT_ON | AMETA_CTRL_ON,
|
||||
},
|
||||
};
|
||||
|
||||
bool push1_ok = control_event_queue_push(&queue, &event);
|
||||
assert(push1_ok);
|
||||
|
||||
event = (struct control_event) {
|
||||
.type = CONTROL_EVENT_TYPE_TEXT,
|
||||
.text_event = {
|
||||
.text = "abc",
|
||||
},
|
||||
};
|
||||
|
||||
bool push2_ok = control_event_queue_push(&queue, &event);
|
||||
assert(push2_ok);
|
||||
|
||||
// overwrite event
|
||||
bool take1_ok = control_event_queue_take(&queue, &event);
|
||||
assert(take1_ok);
|
||||
assert(event.type == CONTROL_EVENT_TYPE_KEYCODE);
|
||||
assert(event.keycode_event.action == AKEY_EVENT_ACTION_DOWN);
|
||||
assert(event.keycode_event.keycode == AKEYCODE_ENTER);
|
||||
assert(event.keycode_event.metastate == (AMETA_CTRL_LEFT_ON | AMETA_CTRL_ON));
|
||||
|
||||
// overwrite event
|
||||
bool take2_ok = control_event_queue_take(&queue, &event);
|
||||
assert(take2_ok);
|
||||
assert(event.type == CONTROL_EVENT_TYPE_TEXT);
|
||||
assert(!strcmp(event.text_event.text, "abc"));
|
||||
|
||||
control_event_queue_destroy(&queue);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
test_control_event_queue_empty();
|
||||
test_control_event_queue_full();
|
||||
test_control_event_queue_push_take();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue