Last active
May 13, 2021 13:38
-
-
Save CandyMi/411bdfd798998eaa675bc84b0fee9d45 to your computer and use it in GitHub Desktop.
Lua queue implemented with C API.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local queue = require "lqueue" | |
local q = queue:new() | |
-- local min, max = 1, 1 | |
local min, max = 1, 10 | |
for i = min, max do | |
q:push(string.char(math.random(97, 97 + 26))) | |
end | |
print("长度为: ", q:len()) | |
print("pop :", q:pop()) | |
for item, typename in q:next() do | |
print("Iteration:", item, typename, #item) | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define LUA_LIB | |
#include <core.h> | |
struct lua_queue_item { | |
int32_t ref; /* 在注册表的引用位置 */ | |
struct lua_queue_item *next; | |
}; | |
struct lua_queue { | |
int64_t cap; | |
struct lua_queue_item *head; /* 链表首部 */ | |
struct lua_queue_item *tail; /* 链表尾部 */ | |
}; | |
/* 创建元素 */ | |
static inline struct lua_queue_item* new_queue_item(void) { | |
struct lua_queue_item* q = xmalloc(sizeof(struct lua_queue_item)); | |
if (!q) | |
return NULL; | |
/* 初始化数据结构属性 */ | |
q->ref = LUA_NOREF; q->next = NULL; | |
return q; | |
} | |
/* 销毁元素 */ | |
static inline void free_queue_item(struct lua_queue_item* q) { | |
xfree(q); | |
} | |
/* 插入一个元素到队列中 */ | |
static int linsert(lua_State *L) { | |
struct lua_queue* q = luaL_testudata(L, 1, "__LUA_QUEUE__"); | |
if (!q) | |
return luaL_error(L, "Need a lua_queue object but get other value (%s).", lua_typename(L, lua_type(L, 1))); | |
struct lua_queue_item* qitem = new_queue_item(); | |
if (!qitem) | |
return luaL_error(L, "lua_queue Queue addition failed: out of memory."); | |
/* 插入并调整队列 */ | |
if (!q->head) { | |
q->tail = q->head = qitem; | |
} else { | |
q->tail->next = qitem; | |
q->tail = qitem; | |
} | |
qitem->ref = luaL_ref(L, LUA_REGISTRYINDEX); | |
// 增加容量计数. | |
q->cap++; | |
return 0; | |
} | |
/* 从队列内取出一个元素 */ | |
static int lremove(lua_State *L) { | |
struct lua_queue* q = luaL_testudata(L, 1, "__LUA_QUEUE__"); | |
if (!q) | |
return luaL_error(L, "Need a lua_queue object but get other value (%s).", lua_typename(L, lua_type(L, 1))); | |
struct lua_queue_item* qitem = q->head; | |
if (!qitem) | |
return 0; | |
lua_rawgeti(L, LUA_REGISTRYINDEX, qitem->ref); | |
lua_pushstring(L, lua_typename(L, lua_type(L, -1))); | |
luaL_unref(L, LUA_REGISTRYINDEX, qitem->ref); | |
/* 删除并调整队列 */ | |
if (qitem->next) { | |
q->head = qitem->next; | |
} else { | |
q->head = NULL; | |
q->tail = NULL; | |
} | |
q->cap--; | |
free_queue_item(qitem); | |
return 2; | |
} | |
/* 获取队列长度 */ | |
static int llen(lua_State *L) { | |
struct lua_queue* q = luaL_testudata(L, 1, "__LUA_QUEUE__"); | |
if (!q) | |
return luaL_error(L, "Need a lua_queue object but get othe value (%s).", lua_typename(L, lua_type(L, 1))); | |
lua_pushinteger(L, q->cap); | |
return 1; | |
} | |
/* 迭代器函数 */ | |
static int lnext(lua_State *L) { | |
struct lua_queue* q = luaL_testudata(L, 1, "__LUA_QUEUE__"); | |
if (!q) | |
return luaL_error(L, "Need a lua_queue object but get othe value (%s).", lua_typename(L, lua_type(L, 1))); | |
lua_pushcfunction(L, lremove); | |
lua_pushvalue(L, -2); | |
lua_pushinteger(L, 0); | |
return 3; | |
} | |
/* 触发gc后的动作 */ | |
static int lgc(lua_State *L) { | |
struct lua_queue* q = luaL_testudata(L, 1, "__LUA_QUEUE__"); | |
while (q->head != NULL) { | |
struct lua_queue_item* qitem = q->head; | |
struct lua_queue_item* qnext = q->head->next; | |
luaL_unref(L, LUA_REGISTRYINDEX, qitem->ref); | |
free_queue_item(qitem); | |
if (qnext) | |
q->head = qnext; | |
} | |
return 0; | |
} | |
/* 创建队列对象 */ | |
static int lnew(lua_State *L) { | |
struct lua_queue* q = lua_newuserdata(L, sizeof(struct lua_queue)); | |
if (!q) | |
return luaL_error(L, "lua_queue Failed to create object: out of memory."); | |
/* 初始化数据结构属性 */ | |
q->cap = 0; q->head = NULL; q->tail = NULL; | |
/* 设置元表 */ | |
luaL_setmetatable(L, "__LUA_QUEUE__"); | |
return 1; | |
} | |
int luaopen_lqueue(lua_State *L) { | |
luaL_checkversion(L); | |
luaL_newmetatable(L, "__LUA_QUEUE__"); | |
lua_pushstring (L, "__index"); | |
lua_pushvalue(L, -2); | |
lua_rawset(L, -3); | |
lua_pushliteral(L, "__mode"); | |
lua_pushliteral(L, "kv"); | |
lua_rawset(L, -3); | |
lua_pushliteral(L, "version"); | |
lua_pushnumber(L, 0.1); | |
lua_rawset(L, -3); | |
luaL_Reg queue_lib1[] = { | |
{"push", linsert}, | |
{"pop", lremove}, | |
{"next", lnext}, | |
{"len", llen}, | |
{"__gc", lgc}, | |
{NULL, NULL}, | |
}; | |
luaL_setfuncs(L, queue_lib1, 0); | |
luaL_Reg queue_lib2[] = { | |
{"new", lnew}, | |
{NULL, NULL}, | |
}; | |
luaL_newlib(L, queue_lib2); | |
lua_pushliteral(L, "version"); | |
lua_pushnumber(L, 0.1); | |
lua_rawset(L, -3); | |
return 1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment