From 08040747494fe7839d2ab049e37f8e23fb8141b4 Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Mon, 20 May 2024 10:58:06 +0200 Subject: linda:limit errors on limits < 1 --- src/deep.cpp | 26 +++----------------------- src/linda.cpp | 6 ++++-- src/uniquekey.h | 17 +++++++++++++++++ tests/basic.lua | 3 ++- tests/errhangtest.lua | 5 ++++- 5 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/deep.cpp b/src/deep.cpp index 9474666..2f4f1ed 100644 --- a/src/deep.cpp +++ b/src/deep.cpp @@ -159,7 +159,7 @@ void DeepFactory::DeleteDeepObject(lua_State* L_, DeepPrelude* o_) bool const isLastRef{ _p->refcount.fetch_sub(1, std::memory_order_relaxed) == 1 }; if (isLastRef) { - // retrieve wrapped __gc + // retrieve wrapped __gc, if any lua_pushvalue(L_, lua_upvalueindex(1)); // L_: self __gc? if (!lua_isnil(L_, -1)) { lua_insert(L_, -2); // L_: __gc self @@ -175,26 +175,6 @@ void DeepFactory::DeleteDeepObject(lua_State* L_, DeepPrelude* o_) // ################################################################################################# -// TODO: convert to UniqueKey::getSubTableMode -static void push_registry_subtable_mode(lua_State* L_, RegistryUniqueKey key_, const char* mode_) -{ - STACK_GROW(L_, 4); - STACK_CHECK_START_REL(L_, 0); - if (!key_.getSubTable(L_, 0, 0)) { // L_: {} - // Set its metatable if requested - if (mode_) { - lua_createtable(L_, 0, 1); // L_: {} mt - lua_pushliteral(L_, "__mode"); // L_: {} mt "__mode" - lua_pushstring(L_, mode_); // L_: {} mt "__mode" mode - lua_rawset(L_, -3); // L_: {} mt - lua_setmetatable(L_, -2); // L_: {} - } - } - STACK_CHECK(L_, 1); -} - -// ################################################################################################# - /* * Push a proxy userdata on the stack. * returns nullptr if ok, else some error string related to bad factory behavior or module require problem @@ -207,7 +187,7 @@ static void push_registry_subtable_mode(lua_State* L_, RegistryUniqueKey key_, c char const* DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int nuv_, LookupMode mode_) { // Check if a proxy already exists - push_registry_subtable_mode(L_, kDeepProxyCacheRegKey, "v"); // L_: DPC + kDeepProxyCacheRegKey.getSubTableMode(L_, "v"); // L_: DPC lua_pushlightuserdata(L_, prelude_); // L_: DPC deep lua_rawget(L_, -2); // L_: DPC proxy if (!lua_isnil(L_, -1)) { @@ -256,7 +236,7 @@ char const* DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int lua_pushcfunction(L_, deep_userdata_gc); // L_: DPC proxy metatable deep_userdata_gc } else { // Add our own '__gc' method wrapping the original - lua_pushcclosure(L_, deep_userdata_gc, 1); // DPC proxy metatable deep_userdata_gc + lua_pushcclosure(L_, deep_userdata_gc, 1); // L_: DPC proxy metatable deep_userdata_gc } lua_setfield(L_, -2, "__gc"); // L_: DPC proxy metatable diff --git a/src/linda.cpp b/src/linda.cpp index a7cf011..4086211 100644 --- a/src/linda.cpp +++ b/src/linda.cpp @@ -487,7 +487,6 @@ LUAG_FUNC(linda_receive) * [true|lanes.cancel_error] = linda_set( linda_ud, key_num|str|bool|lightuserdata [, value [, ...]]) * * Set one or more value to Linda. - * TODO: what do we do if we set to non-nil and limit is 0? * * Existing slot value is replaced, and possible queued entries removed. */ @@ -603,7 +602,10 @@ LUAG_FUNC(linda_limit) // make sure we got 3 arguments: the linda, a key and a limit luaL_argcheck(L_, lua_gettop(L_) == 3, 2, "wrong number of arguments"); // make sure we got a numeric limit - luaL_checknumber(L_, 3); + lua_Number const _limit{ luaL_checknumber(L_, 3) }; + if (_limit < 1) { + raise_luaL_argerror(L_, 3, "limit must be >= 1"); + } // make sure the key is of a valid type check_key_types(L_, 2, 2); diff --git a/src/uniquekey.h b/src/uniquekey.h index 6265a56..67b3279 100644 --- a/src/uniquekey.h +++ b/src/uniquekey.h @@ -107,6 +107,23 @@ class RegistryUniqueKey STACK_CHECK(L_, 1); return false; } + // --------------------------------------------------------------------------------------------- + void getSubTableMode(lua_State* L_, const char* mode_) const + { + STACK_CHECK_START_REL(L_, 0); + if (!getSubTable(L_, 0, 0)) { // L_: {} + // Set its metatable if requested + if (mode_) { + STACK_GROW(L_, 3); + lua_createtable(L_, 0, 1); // L_: {} mt + lua_pushliteral(L_, "__mode"); // L_: {} mt "__mode" + lua_pushstring(L_, mode_); // L_: {} mt "__mode" mode + lua_rawset(L_, -3); // L_: {} mt + lua_setmetatable(L_, -2); // L_: {} + } + } + STACK_CHECK(L_, 1); + } }; // ################################################################################################# diff --git a/tests/basic.lua b/tests/basic.lua index 85a9889..68a7e2a 100644 --- a/tests/basic.lua +++ b/tests/basic.lua @@ -155,7 +155,8 @@ assert(st == "cancelled") -- cancellation of lanes waiting on a linda local limited = lanes.linda("limited") -limited:limit("key", 1) +assert.fails(function() limited:limit("key", 0) end) +assert.failsnot(function() limited:limit("key", 1) end) -- [[################################################ limited:send("key", "hello") -- saturate linda for k, v in pairs(limited:dump()) do diff --git a/tests/errhangtest.lua b/tests/errhangtest.lua index 811601e..84de8c6 100644 --- a/tests/errhangtest.lua +++ b/tests/errhangtest.lua @@ -39,7 +39,10 @@ if true then print(pcall(linda.send, linda, 'test', t_in)) local k,t_out = linda:receive('test') -- read the contents successfully sent t_out.fun() - -- TODO: t_out should contain a single entry, as [fun] = fun should have been discarded because functions are not acceptable keys + -- t_out should contain a single entry, as [fun] = fun should have been discarded because functions are not acceptable keys + local count = 0 + for k,v in pairs(t_out) do count = count + 1 end + assert(count == 1) print "OK" end -- cgit v1.2.3-55-g6feb