123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- #define LUA_LIB
- #include <lua.h>
- #include <lauxlib.h>
- #include <lualib.h>
- #include "lgc.h"
- #ifdef makeshared
- static void
- mark_shared(lua_State *L) {
- if (lua_type(L, -1) != LUA_TTABLE) {
- luaL_error(L, "Not a table, it's a %s.", lua_typename(L, lua_type(L, -1)));
- }
- Table * t = (Table *)lua_topointer(L, -1);
- if (isshared(t))
- return;
- makeshared(t);
- luaL_checkstack(L, 4, NULL);
- if (lua_getmetatable(L, -1)) {
- luaL_error(L, "Can't share metatable");
- }
- lua_pushnil(L);
- while (lua_next(L, -2) != 0) {
- int i;
- for (i=0;i<2;i++) {
- int idx = -i-1;
- int t = lua_type(L, idx);
- switch (t) {
- case LUA_TTABLE:
- mark_shared(L);
- break;
- case LUA_TNUMBER:
- case LUA_TBOOLEAN:
- case LUA_TLIGHTUSERDATA:
- break;
- case LUA_TFUNCTION:
- if (lua_getupvalue(L, idx, 1) != NULL) {
- luaL_error(L, "Invalid function with upvalue");
- } else if (!lua_iscfunction(L, idx)) {
- LClosure *f = (LClosure *)lua_topointer(L, idx);
- makeshared(f);
- lua_sharefunction(L, idx);
- }
- break;
- case LUA_TSTRING:
- lua_sharestring(L, idx);
- break;
- default:
- luaL_error(L, "Invalid type [%s]", lua_typename(L, t));
- break;
- }
- }
- lua_pop(L, 1);
- }
- }
- static int
- lis_sharedtable(lua_State* L) {
- int b = 0;
- if(lua_type(L, 1) == LUA_TTABLE) {
- Table * t = (Table *)lua_topointer(L, 1);
- b = isshared(t);
- }
- lua_pushboolean(L, b);
- return 1;
- }
- static int
- make_matrix(lua_State *L) {
- // turn off gc , because marking shared will prevent gc mark.
- lua_gc(L, LUA_GCSTOP, 0);
- mark_shared(L);
- Table * t = (Table *)lua_topointer(L, -1);
- lua_pushlightuserdata(L, t);
- return 1;
- }
- static int
- clone_table(lua_State *L) {
- lua_clonetable(L, lua_touserdata(L, 1));
- return 1;
- }
- static int
- lco_stackvalues(lua_State* L) {
- lua_State *cL = lua_tothread(L, 1);
- luaL_argcheck(L, cL, 1, "thread expected");
- int n = 0;
- if(cL != L) {
- luaL_checktype(L, 2, LUA_TTABLE);
- n = lua_gettop(cL);
- if(n > 0) {
- luaL_checkstack(L, n+1, NULL);
- int top = lua_gettop(L);
- lua_xmove(cL, L, n);
- int i=0;
- for(i=1; i<=n; i++) {
- lua_pushvalue(L, top+i);
- lua_seti(L, 2, i);
- }
- lua_xmove(L, cL, n);
- }
- }
- lua_pushinteger(L, n);
- return 1;
- }
- struct state_ud {
- lua_State *L;
- };
- static int
- close_state(lua_State *L) {
- struct state_ud *ud = (struct state_ud *)luaL_checkudata(L, 1, "BOXMATRIXSTATE");
- if (ud->L) {
- lua_close(ud->L);
- ud->L = NULL;
- }
- return 0;
- }
- static int
- get_matrix(lua_State *L) {
- struct state_ud *ud = (struct state_ud *)luaL_checkudata(L, 1, "BOXMATRIXSTATE");
- if (ud->L) {
- const void * v = lua_topointer(ud->L, 1);
- lua_pushlightuserdata(L, (void *)v);
- return 1;
- }
- return 0;
- }
- static int
- get_size(lua_State *L) {
- struct state_ud *ud = (struct state_ud *)luaL_checkudata(L, 1, "BOXMATRIXSTATE");
- if (ud->L) {
- lua_Integer sz = lua_gc(ud->L, LUA_GCCOUNT, 0);
- sz *= 1024;
- sz += lua_gc(ud->L, LUA_GCCOUNTB, 0);
- lua_pushinteger(L, sz);
- } else {
- lua_pushinteger(L, 0);
- }
- return 1;
- }
- static int
- box_state(lua_State *L, lua_State *mL) {
- struct state_ud *ud = (struct state_ud *)lua_newuserdatauv(L, sizeof(*ud), 0);
- ud->L = mL;
- if (luaL_newmetatable(L, "BOXMATRIXSTATE")) {
- lua_pushvalue(L, -1);
- lua_setfield(L, -2, "__index");
- lua_pushcfunction(L, close_state);
- lua_setfield(L, -2, "close");
- lua_pushcfunction(L, get_matrix);
- lua_setfield(L, -2, "getptr");
- lua_pushcfunction(L, get_size);
- lua_setfield(L, -2, "size");
- }
- lua_setmetatable(L, -2);
- return 1;
- }
- static int
- load_matrixfile(lua_State *L) {
- luaL_openlibs(L);
- const char * source = (const char *)lua_touserdata(L, 1);
- if (source[0] == '@') {
- if (luaL_loadfilex_(L, source+1, NULL) != LUA_OK)
- lua_error(L);
- } else {
- if (luaL_loadstring(L, source) != LUA_OK)
- lua_error(L);
- }
- lua_replace(L, 1);
- if (lua_pcall(L, lua_gettop(L) - 1, 1, 0) != LUA_OK)
- lua_error(L);
- lua_gc(L, LUA_GCCOLLECT, 0);
- lua_pushcfunction(L, make_matrix);
- lua_insert(L, -2);
- lua_call(L, 1, 1);
- return 1;
- }
- static int
- matrix_from_file(lua_State *L) {
- lua_State *mL = luaL_newstate();
- if (mL == NULL) {
- return luaL_error(L, "luaL_newstate failed");
- }
- const char * source = luaL_checkstring(L, 1);
- int top = lua_gettop(L);
- lua_pushcfunction(mL, load_matrixfile);
- lua_pushlightuserdata(mL, (void *)source);
- if (top > 1) {
- if (!lua_checkstack(mL, top + 1)) {
- return luaL_error(L, "Too many argument %d", top);
- }
- int i;
- for (i=2;i<=top;i++) {
- switch(lua_type(L, i)) {
- case LUA_TBOOLEAN:
- lua_pushboolean(mL, lua_toboolean(L, i));
- break;
- case LUA_TNUMBER:
- if (lua_isinteger(L, i)) {
- lua_pushinteger(mL, lua_tointeger(L, i));
- } else {
- lua_pushnumber(mL, lua_tonumber(L, i));
- }
- break;
- case LUA_TLIGHTUSERDATA:
- lua_pushlightuserdata(mL, lua_touserdata(L, i));
- break;
- case LUA_TFUNCTION:
- if (lua_iscfunction(L, i) && lua_getupvalue(L, i, 1) == NULL) {
- lua_pushcfunction(mL, lua_tocfunction(L, i));
- break;
- }
- return luaL_argerror(L, i, "Only support light C function");
- default:
- return luaL_argerror(L, i, "Type invalid");
- }
- }
- }
- int ok = lua_pcall(mL, top, 1, 0);
- if (ok != LUA_OK) {
- lua_pushstring(L, lua_tostring(mL, -1));
- lua_close(mL);
- lua_error(L);
- }
- return box_state(L, mL);
- }
- LUAMOD_API int
- luaopen_skynet_sharetable_core(lua_State *L) {
- luaL_checkversion(L);
- luaL_Reg l[] = {
- { "clone", clone_table },
- { "stackvalues", lco_stackvalues },
- { "matrix", matrix_from_file },
- { "is_sharedtable", lis_sharedtable },
- { NULL, NULL },
- };
- luaL_newlib(L, l);
- return 1;
- }
- #else
- LUAMOD_API int
- luaopen_skynet_sharetable_core(lua_State *L) {
- return luaL_error(L, "No share string table support");
- }
- #endif
|