mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-24 20:23:06 +00:00
remove feature: remote object. Issue #58
This commit is contained in:
2
Makefile
2
Makefile
@@ -80,7 +80,7 @@ service/gate.so : service-src/service_gate.c
|
||||
service/localcast.so : service-src/service_localcast.c
|
||||
gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src
|
||||
|
||||
luaclib/skynet.so : lualib-src/lua-skynet.c lualib-src/lua-seri.c lualib-src/lua-remoteobj.c lualib-src/trace_service.c | luaclib
|
||||
luaclib/skynet.so : lualib-src/lua-skynet.c lualib-src/lua-seri.c lualib-src/trace_service.c | luaclib
|
||||
gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ -Iskynet-src -Iservice-src -Ilualib-src
|
||||
|
||||
service/client.so : service-src/service_client.c
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include "luacompat52.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_REMOTE_OBJECT 0x40000
|
||||
|
||||
struct remote_address {
|
||||
int handle;
|
||||
uint32_t address;
|
||||
};
|
||||
|
||||
struct remote_objects {
|
||||
int handle_index;
|
||||
struct remote_address addr[MAX_REMOTE_OBJECT];
|
||||
};
|
||||
|
||||
static struct remote_objects * _R = NULL;
|
||||
|
||||
static struct remote_objects *
|
||||
_create() {
|
||||
struct remote_objects * r = malloc(sizeof(*r));
|
||||
r->handle_index = 0;
|
||||
memset(r, 0, sizeof(*r));
|
||||
r->addr[0].address = 0xffffffff;
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
_remove(struct remote_objects *r, uint32_t address) {
|
||||
int i;
|
||||
for (i=0;i<MAX_REMOTE_OBJECT;i++) {
|
||||
if (r->addr[i].address == address) {
|
||||
r->addr[i].address = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
_alloc(struct remote_objects *r, uint32_t address) {
|
||||
int i = 0;
|
||||
for (i=0;i<MAX_REMOTE_OBJECT;i++) {
|
||||
int handle = __sync_add_and_fetch(&r->handle_index, 1);
|
||||
struct remote_address * slot = r->addr + handle % MAX_REMOTE_OBJECT;
|
||||
if (slot->address == 0) {
|
||||
if (__sync_bool_compare_and_swap(&slot->address, 0, address)) {
|
||||
slot->handle = handle;
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
_bind(struct remote_objects *r, int handle, uint32_t address) {
|
||||
struct remote_address * slot = r->addr + handle % MAX_REMOTE_OBJECT;
|
||||
if (slot->handle != handle) {
|
||||
return 0;
|
||||
}
|
||||
for (;;) {
|
||||
uint32_t old = slot->address;
|
||||
if (__sync_bool_compare_and_swap(&slot->address, old, address)) {
|
||||
return old;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
_query(struct remote_objects *r, int handle) {
|
||||
struct remote_address * slot = r->addr + handle % MAX_REMOTE_OBJECT;
|
||||
if (slot->handle == handle) {
|
||||
return slot->address;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lbind(lua_State *L) {
|
||||
uint32_t addr = lua_tounsigned(L,lua_upvalueindex(1));
|
||||
int handle = luaL_checkinteger(L,1);
|
||||
uint32_t old = _bind(_R, handle, addr);
|
||||
if (old == 0) {
|
||||
luaL_error(L, "handle %d is not exist", handle);
|
||||
}
|
||||
lua_pushnumber(L, old);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
lremove(lua_State *L) {
|
||||
uint32_t * addr = lua_touserdata(L,1);
|
||||
_remove(_R, *addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lalloc(lua_State *L) {
|
||||
uint32_t addr = lua_tounsigned(L,lua_upvalueindex(1));
|
||||
int handle = _alloc(_R, addr);
|
||||
if (handle < 0) {
|
||||
return luaL_error(L, "Too many remote object");
|
||||
}
|
||||
lua_pushinteger(L,handle);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
lquery(lua_State *L) {
|
||||
int handle = luaL_checkinteger(L,1);
|
||||
uint32_t addr = _query(_R, handle);
|
||||
if (addr == 0) {
|
||||
return 0;
|
||||
}
|
||||
lua_pushnumber(L, addr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
remoteobj_init(lua_State *L) {
|
||||
if (_R == NULL) {
|
||||
struct remote_objects * r = _create();
|
||||
if (!__sync_bool_compare_and_swap(&_R, NULL, r)) {
|
||||
free(r);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t address = luaL_checkunsigned(L, -1);
|
||||
lua_pushcfunction(L, lquery);
|
||||
lua_pushnumber(L, address);
|
||||
|
||||
uint32_t * addr = lua_newuserdata(L, sizeof(*addr));
|
||||
*addr = address;
|
||||
lua_createtable(L, 0, 1);
|
||||
lua_pushcfunction(L, lremove);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
lua_setmetatable(L,-2);
|
||||
|
||||
lua_pushcclosure(L, lalloc, 2);
|
||||
lua_pushnumber(L, address);
|
||||
lua_pushcclosure(L, lbind, 1);
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
// hibits 0~31 : len
|
||||
#define TYPE_LONG_STRING 5
|
||||
#define TYPE_TABLE 6
|
||||
#define TYPE_REMOTE 7
|
||||
|
||||
#define MAX_COOKIE 32
|
||||
#define COMBINE_TYPE(t,v) ((t) | (v) << 3)
|
||||
@@ -360,16 +359,7 @@ _pack_one(lua_State *L, struct write_block *b, int index, int depth) {
|
||||
if (index < 0) {
|
||||
index = lua_gettop(L) + index + 1;
|
||||
}
|
||||
lua_pushvalue(L, lua_upvalueindex(2)); // __remote
|
||||
lua_rawget(L, index);
|
||||
if (lua_isnumber(L,-1)) {
|
||||
int handle = lua_tointeger(L,-1);
|
||||
lua_pop(L,1);
|
||||
wb_integer(b, handle, TYPE_REMOTE);
|
||||
} else {
|
||||
lua_pop(L,1);
|
||||
wb_table(L, b, index, depth+1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -531,21 +521,8 @@ _push_value(lua_State *L, struct read_block *rb, int type, int cookie) {
|
||||
_unpack_table(L,rb,cookie);
|
||||
break;
|
||||
}
|
||||
case TYPE_REMOTE: {
|
||||
lua_pushvalue(L,lua_upvalueindex(1)); // metatable
|
||||
int handle = _get_integer(L,rb,cookie);
|
||||
lua_rawgeti(L,-1,handle);
|
||||
if (lua_isnil(L,-1)) {
|
||||
lua_pop(L,2);
|
||||
lua_createtable(L,0,1);
|
||||
lua_pushvalue(L,lua_upvalueindex(2)); // __remote
|
||||
lua_pushinteger(L,handle);
|
||||
lua_rawset(L,-3);
|
||||
lua_pushvalue(L,lua_upvalueindex(1)); // metatable
|
||||
lua_setmetatable(L,-2);
|
||||
} else {
|
||||
lua_replace(L, -2);
|
||||
}
|
||||
default: {
|
||||
_invalid_stream(L,rb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,19 +454,10 @@ _reload(lua_State *L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// define in lua-remoteobj.c
|
||||
int remoteobj_init(lua_State *L);
|
||||
|
||||
int
|
||||
luaopen_skynet_c(lua_State *L) {
|
||||
luaL_checkversion(L);
|
||||
|
||||
luaL_Reg pack[] = {
|
||||
{ "pack", _luaseri_pack },
|
||||
{ "unpack", _luaseri_unpack },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
luaL_Reg l[] = {
|
||||
{ "send" , _send },
|
||||
{ "genid", _genid },
|
||||
@@ -477,12 +468,13 @@ luaopen_skynet_c(lua_State *L) {
|
||||
{ "tostring", _tostring },
|
||||
{ "harbor", _harbor },
|
||||
{ "context", _context },
|
||||
{ "pack", _luaseri_pack },
|
||||
{ "unpack", _luaseri_unpack },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
luaL_Reg l2[] = {
|
||||
{ "stat", _stat },
|
||||
{ "remote_init", remoteobj_init },
|
||||
{ "trace_new", _trace_new },
|
||||
{ "trace_delete", _trace_delete },
|
||||
{ "trace_switch", _trace_switch },
|
||||
@@ -491,10 +483,7 @@ luaopen_skynet_c(lua_State *L) {
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
lua_createtable(L, 0, (sizeof(pack) + sizeof(l) + sizeof(l2))/sizeof(luaL_Reg)-1);
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L,"__remote");
|
||||
luaL_setfuncs(L,pack,2);
|
||||
lua_createtable(L, 0, (sizeof(l) + sizeof(l2))/sizeof(luaL_Reg)-1);
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "skynet_lua");
|
||||
struct snlua *lua = lua_touserdata(L,-1);
|
||||
|
||||
@@ -481,87 +481,6 @@ function skynet.harbor(addr)
|
||||
return c.harbor(addr)
|
||||
end
|
||||
|
||||
------ remote object --------
|
||||
|
||||
do
|
||||
-- proto is 11
|
||||
|
||||
local remote_query, remote_alloc, remote_bind = c.remote_init(skynet.self())
|
||||
local weak_meta = { __mode = "kv" }
|
||||
local meta = getmetatable(c.unpack(c.pack({ __remote = 0 })))
|
||||
local remote_call_func = setmetatable({}, weak_meta)
|
||||
|
||||
local _send = assert(c.send)
|
||||
local _pack = assert(c.pack)
|
||||
local _unpack = assert(c.unpack)
|
||||
local _local = skynet.self()
|
||||
|
||||
function meta__index(t, method)
|
||||
local f = remote_call_func[method]
|
||||
if f == nil then
|
||||
f = function(...)
|
||||
local addr = remote_query(t.__remote)
|
||||
-- the proto is 11 (lua is 10)
|
||||
local session = assert(_send(addr, 11 , nil, _pack(t,method,...)), "call to invalid address")
|
||||
local succ, msg, sz = coroutine_yield("CALL", session)
|
||||
if succ then
|
||||
return select(2,assert(_unpack(msg,sz)))
|
||||
else
|
||||
error "call to dead remote object"
|
||||
end
|
||||
end
|
||||
remote_call_func[method] = f
|
||||
end
|
||||
rawset(t,method,f)
|
||||
return f
|
||||
end
|
||||
|
||||
-- prevent gc
|
||||
meta.__index = meta__index
|
||||
|
||||
meta.__newindex = error
|
||||
|
||||
function skynet.remote_create(t, handle)
|
||||
t = t or {}
|
||||
if handle then
|
||||
remote_bind(handle)
|
||||
else
|
||||
handle = remote_alloc()
|
||||
end
|
||||
rawset(t, "__remote" , handle)
|
||||
rawset(meta, handle, t)
|
||||
return t
|
||||
end
|
||||
|
||||
function skynet.remote_bind(handle)
|
||||
return setmetatable( { __remote = handle } , meta)
|
||||
end
|
||||
|
||||
local function remote_call(obj, method, ...)
|
||||
if type(obj) ~= "table" or type(method) ~= "string" then
|
||||
return coroutine_yield("RETURN", _pack(false, "Invalid call"))
|
||||
end
|
||||
local f = obj[method]
|
||||
if type(f) ~= "function" then
|
||||
return coroutine_yield("RETURN", _pack(false, "Object has not method " .. method))
|
||||
end
|
||||
return coroutine_yield("RETURN", _pack(pcall(f,...)))
|
||||
end
|
||||
|
||||
function skynet.remote_root()
|
||||
return skynet.remote_bind(0)
|
||||
end
|
||||
|
||||
skynet.register_protocol {
|
||||
name = "remoteobj",
|
||||
id = 11,
|
||||
unpack = c.unpack,
|
||||
dispatch = function (session, source, ...)
|
||||
remote_call(...)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
----- debug
|
||||
|
||||
local internal_info_func
|
||||
|
||||
@@ -6,7 +6,6 @@ skynet.start(function()
|
||||
skynet.monitor "simplemonitor"
|
||||
local lualog = skynet.newservice("lualog")
|
||||
local console = skynet.newservice("console")
|
||||
local remoteroot = skynet.newservice("remote_root")
|
||||
local watchdog = skynet.newservice("watchdog","8888 4 0")
|
||||
local db = skynet.newservice("simpledb")
|
||||
-- skynet.launch("snlua","testgroup")
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
local skynet = require "skynet"
|
||||
|
||||
local service = {}
|
||||
local root = {}
|
||||
|
||||
function root.register(name, obj)
|
||||
service[name] = obj
|
||||
end
|
||||
|
||||
function root.query(name)
|
||||
return service[name]
|
||||
end
|
||||
|
||||
function root.echo(hello)
|
||||
return hello
|
||||
end
|
||||
|
||||
skynet.remote_create(root,0)
|
||||
|
||||
skynet.start(function() end)
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
local skynet = require "skynet"
|
||||
|
||||
local obj = { id = 0 }
|
||||
|
||||
function obj.hello()
|
||||
return "Hello"
|
||||
end
|
||||
|
||||
function obj:inc()
|
||||
self.id = self.id + 1
|
||||
return self.id
|
||||
end
|
||||
|
||||
skynet.start(function()
|
||||
skynet.remote_create(obj)
|
||||
local root = skynet.remote_root()
|
||||
print(root.echo("hello"))
|
||||
root.register("test",obj)
|
||||
local qobj = root.query "test"
|
||||
print(qobj.hello())
|
||||
print(qobj:inc())
|
||||
skynet.exit()
|
||||
end)
|
||||
Reference in New Issue
Block a user