mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-25 04:33:05 +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
|
service/localcast.so : service-src/service_localcast.c
|
||||||
gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src
|
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
|
gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ -Iskynet-src -Iservice-src -Ilualib-src
|
||||||
|
|
||||||
service/client.so : service-src/service_client.c
|
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
|
// hibits 0~31 : len
|
||||||
#define TYPE_LONG_STRING 5
|
#define TYPE_LONG_STRING 5
|
||||||
#define TYPE_TABLE 6
|
#define TYPE_TABLE 6
|
||||||
#define TYPE_REMOTE 7
|
|
||||||
|
|
||||||
#define MAX_COOKIE 32
|
#define MAX_COOKIE 32
|
||||||
#define COMBINE_TYPE(t,v) ((t) | (v) << 3)
|
#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) {
|
if (index < 0) {
|
||||||
index = lua_gettop(L) + index + 1;
|
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);
|
wb_table(L, b, index, depth+1);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -531,21 +521,8 @@ _push_value(lua_State *L, struct read_block *rb, int type, int cookie) {
|
|||||||
_unpack_table(L,rb,cookie);
|
_unpack_table(L,rb,cookie);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TYPE_REMOTE: {
|
default: {
|
||||||
lua_pushvalue(L,lua_upvalueindex(1)); // metatable
|
_invalid_stream(L,rb);
|
||||||
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);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -454,19 +454,10 @@ _reload(lua_State *L) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// define in lua-remoteobj.c
|
|
||||||
int remoteobj_init(lua_State *L);
|
|
||||||
|
|
||||||
int
|
int
|
||||||
luaopen_skynet_c(lua_State *L) {
|
luaopen_skynet_c(lua_State *L) {
|
||||||
luaL_checkversion(L);
|
luaL_checkversion(L);
|
||||||
|
|
||||||
luaL_Reg pack[] = {
|
|
||||||
{ "pack", _luaseri_pack },
|
|
||||||
{ "unpack", _luaseri_unpack },
|
|
||||||
{ NULL, NULL },
|
|
||||||
};
|
|
||||||
|
|
||||||
luaL_Reg l[] = {
|
luaL_Reg l[] = {
|
||||||
{ "send" , _send },
|
{ "send" , _send },
|
||||||
{ "genid", _genid },
|
{ "genid", _genid },
|
||||||
@@ -477,12 +468,13 @@ luaopen_skynet_c(lua_State *L) {
|
|||||||
{ "tostring", _tostring },
|
{ "tostring", _tostring },
|
||||||
{ "harbor", _harbor },
|
{ "harbor", _harbor },
|
||||||
{ "context", _context },
|
{ "context", _context },
|
||||||
|
{ "pack", _luaseri_pack },
|
||||||
|
{ "unpack", _luaseri_unpack },
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
luaL_Reg l2[] = {
|
luaL_Reg l2[] = {
|
||||||
{ "stat", _stat },
|
{ "stat", _stat },
|
||||||
{ "remote_init", remoteobj_init },
|
|
||||||
{ "trace_new", _trace_new },
|
{ "trace_new", _trace_new },
|
||||||
{ "trace_delete", _trace_delete },
|
{ "trace_delete", _trace_delete },
|
||||||
{ "trace_switch", _trace_switch },
|
{ "trace_switch", _trace_switch },
|
||||||
@@ -491,10 +483,7 @@ luaopen_skynet_c(lua_State *L) {
|
|||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
lua_createtable(L, 0, (sizeof(pack) + sizeof(l) + sizeof(l2))/sizeof(luaL_Reg)-1);
|
lua_createtable(L, 0, (sizeof(l) + sizeof(l2))/sizeof(luaL_Reg)-1);
|
||||||
lua_newtable(L);
|
|
||||||
lua_pushstring(L,"__remote");
|
|
||||||
luaL_setfuncs(L,pack,2);
|
|
||||||
|
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, "skynet_lua");
|
lua_getfield(L, LUA_REGISTRYINDEX, "skynet_lua");
|
||||||
struct snlua *lua = lua_touserdata(L,-1);
|
struct snlua *lua = lua_touserdata(L,-1);
|
||||||
|
|||||||
@@ -481,87 +481,6 @@ function skynet.harbor(addr)
|
|||||||
return c.harbor(addr)
|
return c.harbor(addr)
|
||||||
end
|
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
|
----- debug
|
||||||
|
|
||||||
local internal_info_func
|
local internal_info_func
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ skynet.start(function()
|
|||||||
skynet.monitor "simplemonitor"
|
skynet.monitor "simplemonitor"
|
||||||
local lualog = skynet.newservice("lualog")
|
local lualog = skynet.newservice("lualog")
|
||||||
local console = skynet.newservice("console")
|
local console = skynet.newservice("console")
|
||||||
local remoteroot = skynet.newservice("remote_root")
|
|
||||||
local watchdog = skynet.newservice("watchdog","8888 4 0")
|
local watchdog = skynet.newservice("watchdog","8888 4 0")
|
||||||
local db = skynet.newservice("simpledb")
|
local db = skynet.newservice("simpledb")
|
||||||
-- skynet.launch("snlua","testgroup")
|
-- 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