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 stm_releasecopy(copy); lua_pushboolean(L, 0); return 1; } 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_pushvalue(L, 1); lua_call(L, 3, LUA_MULTRET); lua_pushboolean(L, 1); lua_replace(L, 1); return lua_gettop(L); } else { lua_pushboolean(L, 0); return 1; } }
static void stm_update(struct stm_object *obj, void *msg, int32_t sz) { struct stm_copy *copy = stm_newcopy(msg, sz); WLock l(obj->lock); struct stm_copy *oldcopy = obj->copy; obj->copy = copy; stm_releasecopy(oldcopy); }
static int ldeletereader(lua_State *L) { struct boxreader * box = lua_touserdata(L, 1); stm_releasereader(box->obj); box->obj = NULL; stm_releasecopy(box->lastcopy); box->lastcopy = NULL; return 0; }
static void stm_release(struct stm_object *obj) { assert(obj->copy); WLock l(obj->lock); // writer release the stm object, so release the last copy . stm_releasecopy(obj->copy); obj->copy = NULL; if (--obj->reference > 0) { // stm object grab by readers, reset the copy to NULL. return; } // no one grab the stm object, no need to unlock wlock. skynet_free(obj); }