add skynet.cache lib

This commit is contained in:
云风
2013-12-17 19:18:42 +08:00
parent 8e031c1b21
commit 45196be66a
2 changed files with 102 additions and 12 deletions

View File

@@ -10,6 +10,9 @@ local pcall = pcall
local proto = {}
local skynet = {}
-- code cache
skynet.cache = require "skynet.codecache"
function skynet.register_protocol(class)
local name = class.name
local id = class.id

View File

@@ -16,6 +16,16 @@ struct codecache {
static struct codecache CC = { 0 , NULL };
static void
_clearcache() {
if (CC.L == NULL)
return;
LOCK(&CC)
lua_close(CC.L);
CC.L = luaL_newstate();
UNLOCK(&CC)
}
static void
_init() {
CC.lock = 0;
@@ -80,13 +90,6 @@ luacode_load(const char * key, const char * code, size_t *sz) {
return _save(key, code, sz);
}
/*
static int
cache_load(lua_State *L) {
return 0;
}
*/
// copy from lbaselib.c
static int
load_aux (lua_State *L, int status, int envidx) {
@@ -151,6 +154,76 @@ cache_loadfile(lua_State *L) {
return load_aux(L, status, env);
}
/*
** reserved slot, above all arguments, to hold a copy of the returned
** string to avoid it being collected while parsed. 'load' has four
** optional arguments (chunk, source name, mode, and environment).
*/
#define RESERVEDSLOT 5
/*
** Reader for generic `load' function: `lua_load' uses the
** stack for internal stuff, so the reader cannot change the
** stack top. Instead, it keeps its resulting string in a
** reserved slot inside the stack.
*/
static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
(void)(ud); /* not used */
luaL_checkstack(L, 2, "too many nested functions");
lua_pushvalue(L, 1); /* get function */
lua_call(L, 0, 1); /* call it */
if (lua_isnil(L, -1)) {
lua_pop(L, 1); /* pop result */
*size = 0;
return NULL;
}
else if (!lua_isstring(L, -1))
luaL_error(L, "reader function must return a string");
lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */
return lua_tolstring(L, RESERVEDSLOT, size);
}
static int
cache_load(lua_State *L) {
int status;
size_t l;
const char *s = lua_tolstring(L, 1, &l);
const char *mode = luaL_optstring(L, 3, "bt");
int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */
const char *cname = lua_tostring(L,2);
if (cname) {
// read cache
size_t sz = 0;
const char * bytecode = luacode_load(cname, NULL, &sz);
if (bytecode) {
// load from cache
status = luaL_loadbuffer(L, bytecode, sz, cname);
return load_aux(L, status, env);
}
}
if (s != NULL) { /* loading a string? */
const char *chunkname = luaL_optstring(L, 2, s);
status = luaL_loadbufferx(L, s, l, chunkname, mode);
}
else { /* loading from a reader function */
const char *chunkname = luaL_optstring(L, 2, "=(load)");
luaL_checktype(L, 1, LUA_TFUNCTION);
lua_settop(L, RESERVEDSLOT); /* create reserved slot */
status = lua_load(L, generic_reader, NULL, chunkname, mode);
}
if (cname && status == LUA_OK) {
size_t sz = 0;
str_dump(L);
const char * bytecode = lua_tolstring(L,-1,&sz);
// update cache
luacode_load(cname, bytecode, &sz);
lua_pop(L,1);
}
return load_aux(L, status, env);
}
int
luacode_loadfile(lua_State *L, const char *filename) {
size_t sz = 0;
@@ -264,30 +337,44 @@ searcher_cache (lua_State *L) {
return checkload(L, (luacode_loadfile(L, filename) == LUA_OK), filename);
}
static void
static int
replace_searcher_lua(lua_State *L) {
lua_getglobal(L, "package");
if (!lua_istable(L,-1)) {
luaL_error(L, "Can't find package");
// luaL_error(L, "Can't find package");
return 1;
}
lua_getfield(L, -1, "searchers");
if (!lua_istable(L,-1)) {
luaL_error(L, "Can't find package.searchers");
// luaL_error(L, "Can't find package.searchers");
return 1;
}
lua_pushvalue(L,-2);
lua_pushcclosure(L, searcher_cache, 1);
// package.searcher[2] is searcher_lua, replace it.
lua_rawseti(L, -2, 2);
lua_pop(L,2);
return 0;
}
static int
cache_clear(lua_State *L) {
_clearcache();
return 0;
}
//-------------------------
int
luacode_lib(lua_State *L) {
replace_searcher_lua(L);
if (replace_searcher_lua(L)) {
// Don't support package.searchers
return 0;
}
luaL_Reg l[] = {
// { "load", cache_load },
{ "load", cache_load },
{ "clear", cache_clear },
{ "loadfile", cache_loadfile },
{ NULL, NULL },
};