mirror of https://github.com/minetest/minetest.git
Add minetest.ipc_swap
This commit is contained in:
parent
dfe0f1b7d7
commit
aa9057218b
|
@ -6897,10 +6897,13 @@ different Lua environments (main, mapgen and async).
|
|||
* Write a value to the shared data area.
|
||||
* `key`: as above
|
||||
* `value`: an arbitrary Lua value, cannot be or contain userdata.
|
||||
* `minetest.ipc_swap(key, value)`:
|
||||
* Like `minetest.ipc_set` but returns the value that was at the same key
|
||||
before writing the new one. This is atomic.
|
||||
|
||||
Interacting with the shared data will perform an operation comparable to
|
||||
(de)serialization.
|
||||
Modifying references will not do anything, as in this example:
|
||||
Modifying references will not have any effect, as in this example:
|
||||
```lua
|
||||
minetest.ipc_set("test:foo", {})
|
||||
minetest.ipc_get("test:foo").subkey = "value"
|
||||
|
|
|
@ -22,8 +22,11 @@ local function do_tests()
|
|||
assert(core.registered_items["unittests:description_test"].on_place == true)
|
||||
end
|
||||
|
||||
-- this is checked from the main env
|
||||
core.ipc_set("unittests:mg", { pcall(do_tests) })
|
||||
-- first thread to get here runs the tests
|
||||
if core.ipc_swap("unittests:mg_once", 1) == nil then
|
||||
-- this is checked from the main env
|
||||
core.ipc_set("unittests:mg", { pcall(do_tests) })
|
||||
end
|
||||
|
||||
core.register_on_generated(function(vm, pos1, pos2, blockseed)
|
||||
local n = tonumber(core.get_mapgen_setting("chunksize")) * 16 - 1
|
||||
|
|
|
@ -27,26 +27,38 @@ int ModApiIPC::l_ipc_get(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int ModApiIPC::l_ipc_set(lua_State *L)
|
||||
int ModApiIPC::ipc_put(lua_State *L, bool push_old)
|
||||
{
|
||||
auto *store = getGameDef(L)->getModIPCStore();
|
||||
|
||||
auto key = readParam<std::string>(L, 1);
|
||||
|
||||
std::unique_ptr<PackedValue> vnew, vold;
|
||||
luaL_checkany(L, 2);
|
||||
std::unique_ptr<PackedValue> pv;
|
||||
if (!lua_isnil(L, 2)) {
|
||||
pv.reset(script_pack(L, 2));
|
||||
if (pv->contains_userdata)
|
||||
vnew.reset(script_pack(L, 2));
|
||||
if (vnew->contains_userdata)
|
||||
throw LuaError("Userdata not allowed");
|
||||
}
|
||||
|
||||
{
|
||||
SharedWriteLock autolock(store->mutex);
|
||||
if (pv)
|
||||
store->map[key] = std::move(pv);
|
||||
auto it = store->map.find(key);
|
||||
if (it == store->map.end()) {
|
||||
[[maybe_unused]] auto r = store->map.emplace(std::move(key), std::move(vnew));
|
||||
assert(r.second);
|
||||
} else {
|
||||
vold = std::move(it->second);
|
||||
it->second = std::move(vnew);
|
||||
}
|
||||
}
|
||||
|
||||
if (push_old) {
|
||||
if (vold)
|
||||
script_unpack(L, vold.get());
|
||||
else
|
||||
store->map.erase(key); // delete the map value for nil
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -65,4 +77,5 @@ void ModApiIPC::Initialize(lua_State *L, int top)
|
|||
|
||||
API_FCT(ipc_get);
|
||||
API_FCT(ipc_set);
|
||||
API_FCT(ipc_swap);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
class ModApiIPC : public ModApiBase {
|
||||
private:
|
||||
static int l_ipc_get(lua_State *L);
|
||||
static int l_ipc_set(lua_State *L);
|
||||
static int ipc_put(lua_State *L, bool push_old);
|
||||
static int l_ipc_set(lua_State *L) { return ipc_put(L, false); }
|
||||
static int l_ipc_swap(lua_State *L) { return ipc_put(L, true); }
|
||||
|
||||
public:
|
||||
static void Initialize(lua_State *L, int top);
|
||||
|
|
Loading…
Reference in New Issue