diff options
Diffstat (limited to 'src/linda.cpp')
-rw-r--r-- | src/linda.cpp | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/src/linda.cpp b/src/linda.cpp index 079ab9d..f4dd7e7 100644 --- a/src/linda.cpp +++ b/src/linda.cpp | |||
@@ -452,21 +452,23 @@ LUAG_FUNC(linda_get) | |||
452 | 452 | ||
453 | /* | 453 | /* |
454 | * [bool]|nil,cancel_error = linda:limit(key_num|str|bool|lightuserdata, [int]) | 454 | * [bool]|nil,cancel_error = linda:limit(key_num|str|bool|lightuserdata, [int]) |
455 | * "unlimited"|number = linda:limit(key) | ||
455 | * | 456 | * |
456 | * Set limit to 1 Linda keys. | 457 | * Read or set limit to 1 Linda keys. |
457 | * Optionally wake threads waiting to write on the linda, in case the limit enables them to do so | 458 | * Optionally wake threads waiting to write on the linda, in case the limit enables them to do so |
458 | * Limit can be 0 to completely block everything, nil to reset | 459 | * Limit can be 0 to completely block everything, "unlimited" to reset |
459 | */ | 460 | */ |
460 | LUAG_FUNC(linda_limit) | 461 | LUAG_FUNC(linda_limit) |
461 | { | 462 | { |
462 | static constexpr lua_CFunction _limit{ | 463 | static constexpr lua_CFunction _limit{ |
463 | +[](lua_State* const L_) { | 464 | +[](lua_State* const L_) { |
464 | Linda* const _linda{ ToLinda<false>(L_, 1) }; | 465 | Linda* const _linda{ ToLinda<false>(L_, 1) }; |
465 | // make sure we got 3 arguments: the linda, a key and a limit | 466 | // make sure we got 2 or 3 arguments: the linda, a key and optionally a limit |
466 | int const _nargs{ lua_gettop(L_) }; | 467 | int const _nargs{ lua_gettop(L_) }; |
467 | luaL_argcheck(L_, _nargs == 2 || _nargs == 3, 2, "wrong number of arguments"); | 468 | luaL_argcheck(L_, _nargs == 2 || _nargs == 3, 2, "wrong number of arguments"); |
468 | // make sure we got a numeric limit | 469 | // make sure we got a numeric limit, or "unlimited", (or nothing) |
469 | lua_Integer const _val{ luaL_optinteger(L_, 3, 0) }; | 470 | bool const _unlimited{ luaG_tostring(L_, 3) == "unlimited" }; |
471 | LindaLimit const _val{ _unlimited ? std::numeric_limits<LindaLimit::type>::max() : LindaLimit{ static_cast<LindaLimit::type>(luaL_optinteger(L_, 3, 0)) } }; | ||
470 | if (_val < 0) { | 472 | if (_val < 0) { |
471 | raise_luaL_argerror(L_, 3, "limit must be >= 0"); | 473 | raise_luaL_argerror(L_, 3, "limit must be >= 0"); |
472 | } | 474 | } |
@@ -476,10 +478,21 @@ LUAG_FUNC(linda_limit) | |||
476 | KeeperCallResult _pushed; | 478 | KeeperCallResult _pushed; |
477 | if (_linda->cancelRequest == CancelRequest::None) { | 479 | if (_linda->cancelRequest == CancelRequest::None) { |
478 | Keeper* const _keeper{ _linda->whichKeeper() }; | 480 | Keeper* const _keeper{ _linda->whichKeeper() }; |
481 | if (_unlimited) { | ||
482 | LUA_ASSERT(L_, lua_gettop(L_) == 3 && luaG_tostring(L_, 3) == "unlimited"); | ||
483 | // inside the Keeper, unlimited is signified with a -1 limit (can't use nil because of nil kNilSentinel conversions!) | ||
484 | lua_pop(L_, 1); // L_: linda key | ||
485 | lua_pushinteger(L_, -1); // L_: linda key nil | ||
486 | } | ||
479 | _pushed = keeper_call(_keeper->K, KEEPER_API(limit), L_, _linda, 2); | 487 | _pushed = keeper_call(_keeper->K, KEEPER_API(limit), L_, _linda, 2); |
480 | LUA_ASSERT(L_, _pushed.has_value() && (_pushed.value() == 1) && luaG_type(L_, -1) == LuaType::BOOLEAN); // no error, boolean value saying if we should wake blocked writer threads | 488 | LUA_ASSERT(L_, _pushed.has_value() && (_pushed.value() == 1)); |
481 | if (lua_toboolean(L_, -1)) { | 489 | if (_nargs == 3) { // 3 args: setting the limit |
482 | _linda->readHappened.notify_all(); // To be done from within the 'K' locking area | 490 | LUA_ASSERT(L_, luaG_type(L_, -1) == LuaType::BOOLEAN); // changing the limit: no error, boolean value saying if we should wake blocked writer threads |
491 | if (lua_toboolean(L_, -1)) { | ||
492 | _linda->readHappened.notify_all(); // To be done from within the 'K' locking area | ||
493 | } | ||
494 | } else { // 2 args: reading the limit | ||
495 | LUA_ASSERT(L_, luaG_type(L_, -1) == LuaType::NUMBER || luaG_tostring(L_, -1) == "unlimited"); // reading the limit: a number >=0 or "unlimited" | ||
483 | } | 496 | } |
484 | } else { // linda is cancelled | 497 | } else { // linda is cancelled |
485 | // do nothing and return nil,lanes.cancel_error | 498 | // do nothing and return nil,lanes.cancel_error |