Reimplement queues as circular buffers

This commit is contained in:
2021-07-09 18:07:06 -04:00
parent 311575eb30
commit 16c0fd45de
5 changed files with 106 additions and 63 deletions

View File

@@ -131,76 +131,127 @@ LuaDefine(table_clear, "c") {
return LS.result();
}
/////////////////////////////////////////////////////////////
//
// Queue operators.
//
/////////////////////////////////////////////////////////////
#define QUEUE_POP 1
#define QUEUE_FILL 2
#define QUEUE_MAX 3
#define QUEUE_BASE 4
LuaDefine(queue_create, "c") {
LuaRet queue;
LuaStack LS(L, queue);
LS.newtable(queue);
LS.rawset(queue, "head", 1000000);
LS.rawset(queue, "tail", 1000000);
const int imax = 8;
LS.createtable(queue, QUEUE_BASE + imax - 1, 0);
LS.rawseti(queue, QUEUE_POP, 0);
LS.rawseti(queue, QUEUE_FILL, 0);
LS.rawseti(queue, QUEUE_MAX, imax);
for (int i = 0; i < imax; i++) {
LS.rawseti(queue, QUEUE_BASE + i, 0);
}
return LS.result();
}
LuaDefine(queue_push, "c") {
LuaArg queue, elt;
lua_Integer head;
LuaStack LS(L, queue, elt);
LS.rawget(head, queue, "head");
LS.rawset(queue, head, elt);
LS.rawset(queue, "head", head+1);
LuaVar qpop, qfill, qmax, t;
LuaStack LS(L, queue, elt, qpop, qfill, qmax, t);
LS.checktable(queue);
LS.rawgeti(qpop, queue, QUEUE_POP);
LS.rawgeti(qfill, queue, QUEUE_FILL);
LS.rawgeti(qmax, queue, QUEUE_MAX);
int pop = LS.ckint(qpop);
int fill = LS.ckint(qfill);
int max = LS.ckint(qmax);
if (fill == max) {
int overflow = (pop + fill) - max;
if (overflow < 0) overflow = 0;
for (int i = 0; i < overflow; i++) {
lua_rawgeti(L, queue.index(), QUEUE_BASE + i);
lua_rawseti(L, queue.index(), QUEUE_BASE + i + max);
lua_pushinteger(L, 0);
lua_rawseti(L, queue.index(), QUEUE_BASE + i);
}
for (int i = overflow; i < max; i++) {
lua_pushinteger(L, 0);
lua_rawseti(L, queue.index(), QUEUE_BASE + i + max);
}
max *= 2;
LS.rawseti(queue, QUEUE_MAX, max);
}
int target = pop + fill;
if (target >= max) target -= max;
LS.rawseti(queue, QUEUE_BASE + target, elt);
LS.rawseti(queue, QUEUE_FILL, fill + 1);
return LS.result();
}
LuaDefine(queue_pop, "c") {
LuaArg queue;
LuaRet elt;
lua_Integer head, tail;
LuaStack LS(L, queue, elt);
LS.rawget(tail, queue, "tail");
LS.rawget(head, queue, "head");
if (head == tail) {
LS.set(elt, LuaNil);
} else {
LS.rawget(elt, queue, tail);
LS.rawset(queue, tail, LuaNil);
LS.rawset(queue, "tail", tail + 1);
LuaVar qpop, qfill, qmax, t;
LuaRet result;
LuaStack LS(L, queue, qpop, qfill, qmax, result, t);
LS.checktable(queue);
LS.rawgeti(qpop, queue, QUEUE_POP);
LS.rawgeti(qfill, queue, QUEUE_FILL);
LS.rawgeti(qmax, queue, QUEUE_MAX);
int fill = LS.ckint(qfill);
if (fill <= 0) {
LS.set(result, LuaNil);
return LS.result();
}
int pop = LS.ckint(qpop);
int max = LS.ckint(qmax);
LS.rawgeti(result, queue, QUEUE_BASE + pop);
LS.rawseti(queue, QUEUE_BASE + pop, 0);
int next = pop + 1;
if (next == max) next = 0;
LS.rawseti(queue, QUEUE_POP, next);
LS.rawseti(queue, QUEUE_FILL, fill - 1);
return LS.result();
}
LuaDefine(queue_size, "c") {
LuaArg queue;
LuaRet size;
lua_Number head, tail;
LuaStack LS(L, queue, size);
LS.rawget(head, queue, "head");
LS.rawget(tail, queue, "tail");
LS.set(size, head - tail);
LS.checktable(queue);
LS.rawget(size, queue, QUEUE_FILL);
LS.checknumber(size);
return LS.result();
}
LuaDefine(queue_nth, "c") {
LuaArg queue, n;
LuaArg queue, nn;
LuaVar qpop, qfill, qmax;
LuaRet elt;
lua_Integer nth, head, tail;
LuaStack LS(L, queue, n, elt);
nth = LS.ckinteger(n) - 1;
LS.rawget(head, queue, "head");
LS.rawget(tail, queue, "tail");
if ((nth < 0) || (nth + tail >= head)) {
luaL_error(L, "index out of range");
LuaStack LS(L, queue, nn, qpop, qfill, qmax, elt);
LS.checktable(queue);
int n = LS.ckint(nn) - 1;
LS.rawgeti(qfill, queue, QUEUE_FILL);
int fill = LS.ckint(qfill);
if ((n < 0) || (n >= fill)) {
LS.set(elt, LuaNil);
return LS.result();
}
LS.rawget(elt, queue, tail + nth);
LS.rawgeti(qpop, queue, QUEUE_POP);
LS.rawgeti(qmax, queue, QUEUE_MAX);
int pop = LS.ckint(qpop);
int max = LS.ckint(qmax);
int index = pop + n;
if (index > max) index -= max;
LS.rawgeti(elt, queue, QUEUE_BASE + index);
return LS.result();
}
/////////////////////////////////////////////////////////////
//
// table_sortedpairs
// table_getpairs
//
// Given a table, return all the pairs in the table as a sequence.
// The resulting sequence contains a 1 in the first position,
@@ -209,6 +260,7 @@ LuaDefine(queue_nth, "c") {
// sortedpairs({a=1,b=2,c=3}) => {1,"a",1,"b",2,"c",3}
//
// Note that this function is not directly exposed to lua.
// It's exposed only through the 'sortedpairs' iterator.
//
/////////////////////////////////////////////////////////////
@@ -307,7 +359,7 @@ static void auxsort (lua_State *L, int tab, int l, int u) {
} /* repeat the routine for the larger one */
}
int table_getpairs(lua_State *L, bool sort, bool *unsortable) {
static int table_getpairs(lua_State *L, bool sort, bool *unsortable) {
lua_checkstack(L, 40);
LuaArg tab;
LuaVar key, value;