Skip to content

Commit

Permalink
add sharemap , an example of stm
Browse files Browse the repository at this point in the history
  • Loading branch information
cloudwu committed Feb 28, 2015
1 parent 688cc84 commit 9a6e26d
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 7 deletions.
31 changes: 26 additions & 5 deletions lualib-src/lua-stm.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <string.h>

#include "rwlock.h"
#include "skynet_malloc.h"
Expand Down Expand Up @@ -126,8 +127,16 @@ lcopy(lua_State *L) {

static int
lnewwriter(lua_State *L) {
void * msg = lua_touserdata(L, 1);
uint32_t sz = (uint32_t)luaL_checkinteger(L, 2);
void * msg;
size_t sz;
if (lua_isuserdata(L,1)) {
msg = lua_touserdata(L, 1);
sz = (size_t)luaL_checkinteger(L, 2);
} else {
const char * tmp = luaL_checklstring(L,1,&sz);
msg = skynet_malloc(sz);
memcpy(msg, tmp, sz);
}
struct boxstm * box = lua_newuserdata(L, sizeof(*box));
box->obj = stm_new(msg,sz);
lua_pushvalue(L, lua_upvalueindex(1));
Expand All @@ -148,8 +157,16 @@ ldeletewriter(lua_State *L) {
static int
lupdate(lua_State *L) {
struct boxstm * box = lua_touserdata(L, 1);
void * msg = lua_touserdata(L, 2);
uint32_t sz = (uint32_t)luaL_checkinteger(L, 3);
void * msg;
size_t sz;
if (lua_isuserdata(L, 2)) {
msg = lua_touserdata(L, 2);
sz = (size_t)luaL_checkinteger(L, 3);
} else {
const char * tmp = luaL_checklstring(L,2,&sz);
msg = skynet_malloc(sz);
memcpy(msg, tmp, sz);
}
stm_update(box->obj, msg, sz);

return 0;
Expand Down Expand Up @@ -186,6 +203,7 @@ static int
lread(lua_State *L) {
struct boxreader * box = lua_touserdata(L, 1);
luaL_checktype(L, 2, LUA_TFUNCTION);

struct stm_copy * copy = stm_copy(box->obj);
if (copy == box->lastcopy) {
// not update
Expand All @@ -197,10 +215,13 @@ lread(lua_State *L) {
stm_releasecopy(box->lastcopy);
box->lastcopy = copy;
if (copy) {
lua_settop(L, 3);
lua_replace(L, 1);
lua_settop(L, 2);
lua_pushlightuserdata(L, copy->msg);
lua_pushinteger(L, copy->sz);
lua_call(L, 2, LUA_MULTRET);
lua_pushvalue(L, 1);
lua_call(L, 3, LUA_MULTRET);
lua_pushboolean(L, 1);
lua_replace(L, 1);
return lua_gettop(L);
Expand Down
69 changes: 69 additions & 0 deletions lualib/sharemap.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
local stm = require "stm"
local sprotoloader = require "sprotoloader"
local sproto = require "sproto"
local setmetatable = setmetatable

local sharemap = {}

function sharemap.register(protofile)
-- use global slot 0 for type define
sprotoloader.register(protofile, 0)
end

local sprotoobj
local function loadsp()
if sprotoobj == nil then
sprotoobj = sprotoloader.load(0)
end
return sprotoobj
end

function sharemap:commit()
self.__obj(sprotoobj:encode(self.__typename, self.__data))
end

function sharemap:copy()
return stm.copy(self.__obj)
end

function sharemap.writer(typename, obj)
local sp = loadsp()
obj = obj or {}
local stmobj = stm.new(sp:encode(typename,obj))
obj.__typename = typename
obj.__obj = stmobj
obj.__data = obj
obj.commit = sharemap.commit
obj.copy = sharemap.copy
return setmetatable(obj, { __index = obj.__data, __newindex = obj.__data })
end

local function decode(msg, sz, self)
local data = self.__data
for k in pairs(data) do
data[k] = nil
end
return sprotoobj:decode(self.__typename, msg, sz, data)
end

function sharemap:update()
return self.__obj(decode, self)
end

function sharemap.reader(typename, stmcpy)
local sp = loadsp()
local stmobj = stm.newcopy(stmcpy)
local _, data = stmobj(function(msg, sz)
return sp:decode(typename, msg, sz)
end)

local obj = {
__typename = typename,
__obj = stmobj,
__data = data,
update = sharemap.update,
}
return setmetatable(obj, { __index = obj.__data, __newindex = error })
end

return sharemap
4 changes: 2 additions & 2 deletions lualib/sproto.lua
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ function sproto:encode(typename, tbl)
return core.encode(st, tbl)
end

function sproto:decode(typename, bin)
function sproto:decode(typename, ...)
local st = querytype(self, typename)
return core.decode(st, bin)
return core.decode(st, ...)
end

function sproto:pencode(typename, tbl)
Expand Down
5 changes: 5 additions & 0 deletions test/sharemap.sp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.foobar {
x 0 : integer
y 1 : integer
s 2 : string
}
48 changes: 48 additions & 0 deletions test/testsm.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
local skynet = require "skynet"
local sharemap = require "sharemap"

local mode = ...

if mode == "slave" then
--slave

local function dump(reader)
reader:update()
print("x=", reader.x)
print("y=", reader.y)
print("s=", reader.s)
end

skynet.start(function()
local reader
skynet.dispatch("lua", function(_,_,cmd,...)
if cmd == "init" then
reader = sharemap.reader(...)
else
assert(cmd == "ping")
dump(reader)
end
skynet.ret()
end)
end)

else
-- master
skynet.start(function()
-- register share type schema
sharemap.register("./test/sharemap.sp")
local slave = skynet.newservice(SERVICE_NAME, "slave")
local writer = sharemap.writer("foobar", { x=0,y=0,s="hello" })
skynet.call(slave, "lua", "init", "foobar", writer:copy())
writer.x = 1
writer:commit()
skynet.call(slave, "lua", "ping")
writer.y = 2
writer:commit()
skynet.call(slave, "lua", "ping")
writer.s = "world"
writer:commit()
skynet.call(slave, "lua", "ping")
end)

end

0 comments on commit 9a6e26d

Please sign in to comment.