diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-10-24 11:30:18 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-10-24 11:30:18 +0200 |
commit | eba98e4e1adcf3ce11e5934e2dce54f29aef1e0a (patch) | |
tree | d51d51eb2d48208df1cfdf6eb0bd40a928d6243c | |
parent | 8745a54f88f31cd51dc86c96039ebe0b3e98f5ea (diff) | |
download | lanes-eba98e4e1adcf3ce11e5934e2dce54f29aef1e0a.tar.gz lanes-eba98e4e1adcf3ce11e5934e2dce54f29aef1e0a.tar.bz2 lanes-eba98e4e1adcf3ce11e5934e2dce54f29aef1e0a.zip |
Make Unique even stronger
-rw-r--r-- | deep_test/deep_test.cpp | 2 | ||||
-rw-r--r-- | src/allocator.h | 6 | ||||
-rw-r--r-- | src/compat.cpp | 2 | ||||
-rw-r--r-- | src/compat.h | 6 | ||||
-rw-r--r-- | src/intercopycontext.cpp | 10 | ||||
-rw-r--r-- | src/intercopycontext.h | 2 | ||||
-rw-r--r-- | src/keeper.cpp | 16 | ||||
-rw-r--r-- | src/keeper.h | 2 | ||||
-rw-r--r-- | src/lanes.cpp | 14 | ||||
-rw-r--r-- | src/linda.cpp | 8 | ||||
-rw-r--r-- | src/lindafactory.cpp | 2 | ||||
-rw-r--r-- | src/stackindex.hpp | 4 | ||||
-rw-r--r-- | src/unique.hpp | 9 | ||||
-rw-r--r-- | src/universe.h | 2 |
14 files changed, 49 insertions, 36 deletions
diff --git a/deep_test/deep_test.cpp b/deep_test/deep_test.cpp index a6c6296..974709f 100644 --- a/deep_test/deep_test.cpp +++ b/deep_test/deep_test.cpp | |||
@@ -229,7 +229,7 @@ static luaL_Reg const clonable_mt[] = { | |||
229 | 229 | ||
230 | int luaD_new_clonable(lua_State* L) | 230 | int luaD_new_clonable(lua_State* L) |
231 | { | 231 | { |
232 | int const _nuv{ static_cast<int>(luaL_optinteger(L, 1, 1)) }; | 232 | UserValueCount const _nuv{ static_cast<int>(luaL_optinteger(L, 1, 1)) }; |
233 | lua_newuserdatauv(L, sizeof(MyClonableUserdata), _nuv); | 233 | lua_newuserdatauv(L, sizeof(MyClonableUserdata), _nuv); |
234 | luaG_setmetatable(L, "clonable"); | 234 | luaG_setmetatable(L, "clonable"); |
235 | return 1; | 235 | return 1; |
diff --git a/src/allocator.h b/src/allocator.h index 0505251..e0ff9d6 100644 --- a/src/allocator.h +++ b/src/allocator.h | |||
@@ -16,11 +16,11 @@ namespace lanes { | |||
16 | lua_Alloc allocF{ nullptr }; | 16 | lua_Alloc allocF{ nullptr }; |
17 | void* allocUD{ nullptr }; | 17 | void* allocUD{ nullptr }; |
18 | 18 | ||
19 | [[nodiscard]] static void* operator new(size_t size_) noexcept = delete; // can't create one outside of a Lua state | 19 | [[nodiscard]] static void* operator new(size_t const size_) noexcept = delete; // can't create one outside of a Lua state |
20 | [[nodiscard]] static void* operator new(size_t size_, lua_State* L_) noexcept { return lua_newuserdatauv(L_, size_, 0); } | 20 | [[nodiscard]] static void* operator new(size_t const size_, lua_State* const L_) noexcept { return lua_newuserdatauv(L_, size_, UserValueCount{ 0 }); } |
21 | // always embedded somewhere else or "in-place constructed" as a full userdata | 21 | // always embedded somewhere else or "in-place constructed" as a full userdata |
22 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception | 22 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception |
23 | static void operator delete([[maybe_unused]] void* p_, [[maybe_unused]] lua_State* L_) {} | 23 | static void operator delete([[maybe_unused]] void* const p_, [[maybe_unused]] lua_State* const L_) {} |
24 | 24 | ||
25 | AllocatorDefinition(uintptr_t const version_, lua_Alloc const allocF_, void* const allocUD_) noexcept | 25 | AllocatorDefinition(uintptr_t const version_, lua_Alloc const allocF_, void* const allocUD_) noexcept |
26 | : version{ version_ } | 26 | : version{ version_ } |
diff --git a/src/compat.cpp b/src/compat.cpp index 1be910f..b661b28 100644 --- a/src/compat.cpp +++ b/src/compat.cpp | |||
@@ -83,7 +83,7 @@ void luaL_requiref(lua_State* L_, const char* modname_, lua_CFunction openf_, in | |||
83 | // ################################################################################################# | 83 | // ################################################################################################# |
84 | // ################################################################################################# | 84 | // ################################################################################################# |
85 | 85 | ||
86 | void* lua_newuserdatauv(lua_State* const L_, size_t const sz_, [[maybe_unused]] int const nuvalue_) | 86 | void* lua_newuserdatauv(lua_State* const L_, size_t const sz_, [[maybe_unused]] UserValueCount const nuvalue_) |
87 | { | 87 | { |
88 | LUA_ASSERT(L_, nuvalue_ <= 1); | 88 | LUA_ASSERT(L_, nuvalue_ <= 1); |
89 | return lua_newuserdata(L_, sz_); | 89 | return lua_newuserdata(L_, sz_); |
diff --git a/src/compat.h b/src/compat.h index af014b1..0b6b12b 100644 --- a/src/compat.h +++ b/src/compat.h | |||
@@ -80,7 +80,7 @@ inline int luaL_optint(lua_State* L_, int n_, lua_Integer d_) | |||
80 | 80 | ||
81 | #if LUA_VERSION_NUM < 504 | 81 | #if LUA_VERSION_NUM < 504 |
82 | 82 | ||
83 | void* lua_newuserdatauv(lua_State* L_, size_t sz_, int nuvalue_); | 83 | void* lua_newuserdatauv(lua_State* L_, size_t sz_, UserValueCount nuvalue_); |
84 | int lua_getiuservalue(lua_State* L_, StackIndex idx_, int n_); | 84 | int lua_getiuservalue(lua_State* L_, StackIndex idx_, int n_); |
85 | int lua_setiuservalue(lua_State* L_, StackIndex idx_, int n_); | 85 | int lua_setiuservalue(lua_State* L_, StackIndex idx_, int n_); |
86 | 86 | ||
@@ -138,7 +138,7 @@ inline LuaType luaG_type(lua_State* const L_, StackIndex const idx_) | |||
138 | // use this in place of lua_absindex to save a function call | 138 | // use this in place of lua_absindex to save a function call |
139 | inline StackIndex luaG_absindex(lua_State* const L_, StackIndex const idx_) | 139 | inline StackIndex luaG_absindex(lua_State* const L_, StackIndex const idx_) |
140 | { | 140 | { |
141 | return StackIndex{ (idx_ >= 0 || idx_ <= kIdxRegistry) ? idx_ : lua_gettop(L_) + idx_ + 1 }; | 141 | return StackIndex{ (idx_ >= 0 || idx_ <= kIdxRegistry) ? idx_ : StackIndex{ lua_gettop(L_) + idx_ + 1 } }; |
142 | } | 142 | } |
143 | 143 | ||
144 | // ################################################################################################# | 144 | // ################################################################################################# |
@@ -295,7 +295,7 @@ static inline void luaG_newlib(lua_State* const L_, luaL_Reg const (&funcs_)[N]) | |||
295 | // ################################################################################################# | 295 | // ################################################################################################# |
296 | 296 | ||
297 | template <typename T> | 297 | template <typename T> |
298 | [[nodiscard]] T* luaG_newuserdatauv(lua_State* L_, int nuvalue_) | 298 | [[nodiscard]] T* luaG_newuserdatauv(lua_State* L_, UserValueCount nuvalue_) |
299 | { | 299 | { |
300 | return static_cast<T*>(lua_newuserdatauv(L_, sizeof(T), nuvalue_)); | 300 | return static_cast<T*>(lua_newuserdatauv(L_, sizeof(T), nuvalue_)); |
301 | } | 301 | } |
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp index f54c152..5f3ce7d 100644 --- a/src/intercopycontext.cpp +++ b/src/intercopycontext.cpp | |||
@@ -738,7 +738,7 @@ LuaType InterCopyContext::processConversion() const | |||
738 | lua_getupvalue(L2, -1, 2); // L2: ... userdata_clone_sentinel u | 738 | lua_getupvalue(L2, -1, 2); // L2: ... userdata_clone_sentinel u |
739 | } | 739 | } |
740 | // assign uservalues | 740 | // assign uservalues |
741 | int _uvi{ _nuv }; | 741 | UserValueIndex _uvi{ _nuv.value() }; |
742 | while (_uvi > 0) { | 742 | while (_uvi > 0) { |
743 | _c.L1_i = SourceIndex{ luaG_absindex(L1, kIdxTop) }; | 743 | _c.L1_i = SourceIndex{ luaG_absindex(L1, kIdxTop) }; |
744 | if (_c.interCopyOne() != InterCopyResult::Success) { // L2: ... u uv | 744 | if (_c.interCopyOne() != InterCopyResult::Success) { // L2: ... u uv |
@@ -796,7 +796,7 @@ LuaType InterCopyContext::processConversion() const | |||
796 | InterCopyContext _c{ U, L2, L1, L2_cache_i, {}, VT::NORMAL, mode, name }; | 796 | InterCopyContext _c{ U, L2, L1, L2_cache_i, {}, VT::NORMAL, mode, name }; |
797 | StackIndex const _clone_i{ lua_gettop(L2) }; | 797 | StackIndex const _clone_i{ lua_gettop(L2) }; |
798 | STACK_GROW(L2, _nuv); | 798 | STACK_GROW(L2, _nuv); |
799 | int _uvi{ _nuv }; | 799 | UserValueIndex _uvi{ _nuv.value() }; |
800 | while (_uvi) { | 800 | while (_uvi) { |
801 | _c.L1_i = SourceIndex{ luaG_absindex(L1, kIdxTop) }; | 801 | _c.L1_i = SourceIndex{ luaG_absindex(L1, kIdxTop) }; |
802 | if (_c.interCopyOne() != InterCopyResult::Success) { // L1: ... deep ... [uv]* L2: deep uv | 802 | if (_c.interCopyOne() != InterCopyResult::Success) { // L1: ... deep ... [uv]* L2: deep uv |
@@ -880,7 +880,7 @@ LuaType InterCopyContext::processConversion() const | |||
880 | lua_setmetatable(L2, -2); // L2: ... mt u | 880 | lua_setmetatable(L2, -2); // L2: ... mt u |
881 | // transfer and assign uservalues | 881 | // transfer and assign uservalues |
882 | InterCopyContext _c{ *this }; | 882 | InterCopyContext _c{ *this }; |
883 | int _uvi{ _nuv }; | 883 | UserValueIndex _uvi{ _nuv.value() }; |
884 | while (_uvi > 0) { | 884 | while (_uvi > 0) { |
885 | _c.L1_i = SourceIndex{ luaG_absindex(L1, kIdxTop) }; | 885 | _c.L1_i = SourceIndex{ luaG_absindex(L1, kIdxTop) }; |
886 | if (_c.interCopyOne() != InterCopyResult::Success) { // L2: ... mt u uv | 886 | if (_c.interCopyOne() != InterCopyResult::Success) { // L2: ... mt u uv |
@@ -1276,7 +1276,7 @@ namespace { | |||
1276 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U }); | 1276 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U }); |
1277 | 1277 | ||
1278 | StackIndex const _top_L1{ lua_gettop(L1) }; | 1278 | StackIndex const _top_L1{ lua_gettop(L1) }; |
1279 | int const _available{ (L1_i != 0) ? (_top_L1 - L1_i + 1) : _top_L1 }; | 1279 | int const _available{ (L1_i != 0) ? (_top_L1 - L1_i + 1) : _top_L1.value() }; |
1280 | if (n_ > _available) { | 1280 | if (n_ > _available) { |
1281 | // requesting to copy more than is available? | 1281 | // requesting to copy more than is available? |
1282 | DEBUGSPEW_CODE(DebugSpew(U) << "nothing to copy" << std::endl); | 1282 | DEBUGSPEW_CODE(DebugSpew(U) << "nothing to copy" << std::endl); |
@@ -1298,7 +1298,7 @@ namespace { | |||
1298 | InterCopyResult _copyok{ InterCopyResult::Success }; | 1298 | InterCopyResult _copyok{ InterCopyResult::Success }; |
1299 | STACK_CHECK_START_REL(L1, 0); | 1299 | STACK_CHECK_START_REL(L1, 0); |
1300 | // if L1_i is specified, start here, else take the _n items off the top of the stack | 1300 | // if L1_i is specified, start here, else take the _n items off the top of the stack |
1301 | for (StackIndex _i{ L1_i != 0 ? L1_i : (_top_L1 - n_ + 1) }, _j{ 1 }; _j <= n_; ++_i, ++_j) { | 1301 | for (StackIndex _i{ (L1_i != 0) ? L1_i.value() : (_top_L1 - n_ + 1) }, _j{ 1 }; _j <= n_; ++_i, ++_j) { |
1302 | char _tmpBuf[16]; | 1302 | char _tmpBuf[16]; |
1303 | if (U->verboseErrors) { | 1303 | if (U->verboseErrors) { |
1304 | sprintf(_tmpBuf, "arg_%d", _j.operator int()); | 1304 | sprintf(_tmpBuf, "arg_%d", _j.operator int()); |
diff --git a/src/intercopycontext.h b/src/intercopycontext.h index a9be267..3a5db36 100644 --- a/src/intercopycontext.h +++ b/src/intercopycontext.h | |||
@@ -41,7 +41,7 @@ class InterCopyContext | |||
41 | [[nodiscard]] std::string_view findLookupName() const; | 41 | [[nodiscard]] std::string_view findLookupName() const; |
42 | // when mode == LookupMode::FromKeeper, L1 is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error | 42 | // when mode == LookupMode::FromKeeper, L1 is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error |
43 | // whon mode != LookupMode::FromKeeper, L1 is not a keeper state, therefore L1 is the state where we want to raise the error | 43 | // whon mode != LookupMode::FromKeeper, L1 is not a keeper state, therefore L1 is the state where we want to raise the error |
44 | lua_State* getErrL() const { return (mode == LookupMode::FromKeeper) ? L2 : L1; } | 44 | lua_State* getErrL() const { return (mode == LookupMode::FromKeeper) ? L2.value() : L1.value(); } |
45 | [[nodiscard]] LuaType processConversion() const; | 45 | [[nodiscard]] LuaType processConversion() const; |
46 | 46 | ||
47 | // for use in copyCachedFunction | 47 | // for use in copyCachedFunction |
diff --git a/src/keeper.cpp b/src/keeper.cpp index bea91a7..7deb2b3 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp | |||
@@ -75,7 +75,7 @@ class KeyUD | |||
75 | LindaLimit limit{ -1 }; | 75 | LindaLimit limit{ -1 }; |
76 | 76 | ||
77 | // a fifo full userdata has one uservalue, the table that holds the actual fifo contents | 77 | // a fifo full userdata has one uservalue, the table that holds the actual fifo contents |
78 | [[nodiscard]] static void* operator new([[maybe_unused]] size_t size_, KeeperState L_) noexcept { return luaG_newuserdatauv<KeyUD>(L_, 1); } | 78 | [[nodiscard]] static void* operator new([[maybe_unused]] size_t size_, KeeperState L_) noexcept { return luaG_newuserdatauv<KeyUD>(L_, UserValueCount{ 1 }); } |
79 | // always embedded somewhere else or "in-place constructed" as a full userdata | 79 | // always embedded somewhere else or "in-place constructed" as a full userdata |
80 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception | 80 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception |
81 | static void operator delete([[maybe_unused]] void* p_, [[maybe_unused]] KeeperState L_) { LUA_ASSERT(L_, !"should never be called"); } | 81 | static void operator delete([[maybe_unused]] void* p_, [[maybe_unused]] KeeperState L_) { LUA_ASSERT(L_, !"should never be called"); } |
@@ -275,7 +275,7 @@ bool KeyUD::reset(KeeperState const K_) | |||
275 | bool const _wasFull{ (limit > 0) && (count >= limit) }; | 275 | bool const _wasFull{ (limit > 0) && (count >= limit) }; |
276 | // empty the KeyUD: replace uservalue with a virgin table, reset counters, but leave limit unchanged! | 276 | // empty the KeyUD: replace uservalue with a virgin table, reset counters, but leave limit unchanged! |
277 | // if we have an actual limit, use it to preconfigure the table | 277 | // if we have an actual limit, use it to preconfigure the table |
278 | lua_createtable(K_, (limit <= 0) ? 0 : limit, 0); // K_: KeysDB key val... KeyUD {} | 278 | lua_createtable(K_, (limit <= 0) ? 0 : limit.value(), 0); // K_: KeysDB key val... KeyUD {} |
279 | lua_setiuservalue(K_, StackIndex{ -2 }, kContentsTableIndex); // K_: KeysDB key val... KeyUD | 279 | lua_setiuservalue(K_, StackIndex{ -2 }, kContentsTableIndex); // K_: KeysDB key val... KeyUD |
280 | first = 1; | 280 | first = 1; |
281 | count = 0; | 281 | count = 0; |
@@ -646,7 +646,7 @@ KeeperCallResult keeper_call(KeeperState const K_, keeper_api_t const func_, lua | |||
646 | lua_pushlightuserdata(K_, linda_); // L: ... args... K_: func_ linda | 646 | lua_pushlightuserdata(K_, linda_); // L: ... args... K_: func_ linda |
647 | if ( | 647 | if ( |
648 | (_args == 0) || | 648 | (_args == 0) || |
649 | (InterCopyContext{ linda_->U, DestState{ K_ }, SourceState{ L_ }, {}, {}, {}, LookupMode::ToKeeper, {} }.interCopy(_args) == InterCopyResult::Success) | 649 | (InterCopyContext{ linda_->U, DestState{ K_.value() }, SourceState{ L_ }, {}, {}, {}, LookupMode::ToKeeper, {} }.interCopy(_args) == InterCopyResult::Success) |
650 | ) { // L: ... args... K_: func_ linda args... | 650 | ) { // L: ... args... K_: func_ linda args... |
651 | lua_call(K_, 1 + _args, LUA_MULTRET); // L: ... args... K_: result... | 651 | lua_call(K_, 1 + _args, LUA_MULTRET); // L: ... args... K_: result... |
652 | int const _retvals{ lua_gettop(K_) - _top_K }; | 652 | int const _retvals{ lua_gettop(K_) - _top_K }; |
@@ -656,7 +656,7 @@ KeeperCallResult keeper_call(KeeperState const K_, keeper_api_t const func_, lua | |||
656 | // when attempting to grab the mutex again (WINVER <= 0x400 does this, but locks just fine, I don't know about pthread) | 656 | // when attempting to grab the mutex again (WINVER <= 0x400 does this, but locks just fine, I don't know about pthread) |
657 | if ( | 657 | if ( |
658 | (_retvals == 0) || | 658 | (_retvals == 0) || |
659 | (InterCopyContext{ linda_->U, DestState{ L_ }, SourceState{ K_ }, {}, {}, {}, LookupMode::FromKeeper, {} }.interMove(_retvals) == InterCopyResult::Success) | 659 | (InterCopyContext{ linda_->U, DestState{ L_ }, SourceState{ K_.value() }, {}, {}, {}, LookupMode::FromKeeper, {} }.interMove(_retvals) == InterCopyResult::Success) |
660 | ) { // L: ... args... result... K_: result... | 660 | ) { // L: ... args... result... K_: result... |
661 | _result.emplace(_retvals); | 661 | _result.emplace(_retvals); |
662 | } | 662 | } |
@@ -721,7 +721,7 @@ void Keeper::operator delete[](void* p_, Universe* U_) | |||
721 | int Keeper::PushLindaStorage(Linda& linda_, DestState const L_) | 721 | int Keeper::PushLindaStorage(Linda& linda_, DestState const L_) |
722 | { | 722 | { |
723 | Keeper* const _keeper{ linda_.whichKeeper() }; | 723 | Keeper* const _keeper{ linda_.whichKeeper() }; |
724 | KeeperState const _K{ _keeper ? _keeper->K : KeeperState{ nullptr } }; | 724 | KeeperState const _K{ _keeper ? _keeper->K : KeeperState{ static_cast<lua_State*>(nullptr) } }; |
725 | if (_K == nullptr) { | 725 | if (_K == nullptr) { |
726 | return 0; | 726 | return 0; |
727 | } | 727 | } |
@@ -740,7 +740,7 @@ int Keeper::PushLindaStorage(Linda& linda_, DestState const L_) | |||
740 | STACK_GROW(L_, 5); | 740 | STACK_GROW(L_, 5); |
741 | STACK_CHECK_START_REL(L_, 0); | 741 | STACK_CHECK_START_REL(L_, 0); |
742 | lua_newtable(L_); // _K: KeysDB L_: out | 742 | lua_newtable(L_); // _K: KeysDB L_: out |
743 | InterCopyContext _c{ linda_.U, L_, SourceState{ _K }, {}, {}, {}, LookupMode::FromKeeper, {} }; | 743 | InterCopyContext _c{ linda_.U, L_, SourceState{ _K.value() }, {}, {}, {}, LookupMode::FromKeeper, {} }; |
744 | lua_pushnil(_K); // _K: KeysDB nil L_: out | 744 | lua_pushnil(_K); // _K: KeysDB nil L_: out |
745 | while (lua_next(_K, -2)) { // _K: KeysDB key KeyUD L_: out | 745 | while (lua_next(_K, -2)) { // _K: KeysDB key KeyUD L_: out |
746 | KeyUD* const _key{ KeyUD::GetPtr(_K, kIdxTop) }; | 746 | KeyUD* const _key{ KeyUD::GetPtr(_K, kIdxTop) }; |
@@ -810,7 +810,7 @@ void Keepers::close() | |||
810 | } | 810 | } |
811 | 811 | ||
812 | auto _closeOneKeeper = [](Keeper& keeper_) { | 812 | auto _closeOneKeeper = [](Keeper& keeper_) { |
813 | lua_State* const _K{ std::exchange(keeper_.K, KeeperState{ nullptr }) }; | 813 | lua_State* const _K{ std::exchange(keeper_.K, KeeperState{ static_cast<lua_State*>(nullptr) }) }; |
814 | if (_K) { | 814 | if (_K) { |
815 | lua_close(_K); | 815 | lua_close(_K); |
816 | } | 816 | } |
@@ -928,7 +928,7 @@ void Keepers::initialize(Universe& U_, lua_State* L_, size_t const nbKeepers_, i | |||
928 | // copy package.path and package.cpath from the source state | 928 | // copy package.path and package.cpath from the source state |
929 | if (luaG_getmodule(L, LUA_LOADLIBNAME) != LuaType::NIL) { // L_: settings package _K: | 929 | if (luaG_getmodule(L, LUA_LOADLIBNAME) != LuaType::NIL) { // L_: settings package _K: |
930 | // when copying with mode LookupMode::ToKeeper, error message is pushed at the top of the stack, not raised immediately | 930 | // when copying with mode LookupMode::ToKeeper, error message is pushed at the top of the stack, not raised immediately |
931 | InterCopyContext _c{ U, DestState{ _K }, SourceState{ L }, {}, SourceIndex{ luaG_absindex(L, kIdxTop) }, {}, LookupMode::ToKeeper, {} }; | 931 | InterCopyContext _c{ U, DestState{ _K.value() }, SourceState{ L }, {}, SourceIndex{ luaG_absindex(L, kIdxTop) }, {}, LookupMode::ToKeeper, {} }; |
932 | if (_c.interCopyPackage() != InterCopyResult::Success) { // L_: settings ... error_msg _K: | 932 | if (_c.interCopyPackage() != InterCopyResult::Success) { // L_: settings ... error_msg _K: |
933 | // if something went wrong, the error message is at the top of the stack | 933 | // if something went wrong, the error message is at the top of the stack |
934 | lua_remove(L, -2); // L_: settings error_msg | 934 | lua_remove(L, -2); // L_: settings error_msg |
diff --git a/src/keeper.h b/src/keeper.h index 74bdbf2..7e3e1fa 100644 --- a/src/keeper.h +++ b/src/keeper.h | |||
@@ -16,7 +16,7 @@ DECLARE_UNIQUE_TYPE(KeeperIndex, int); | |||
16 | struct Keeper | 16 | struct Keeper |
17 | { | 17 | { |
18 | std::mutex mutex; | 18 | std::mutex mutex; |
19 | KeeperState K{ nullptr }; | 19 | KeeperState K{ static_cast<lua_State*>(nullptr) }; |
20 | 20 | ||
21 | [[nodiscard]] static void* operator new[](size_t size_, Universe* U_) noexcept; | 21 | [[nodiscard]] static void* operator new[](size_t size_, Universe* U_) noexcept; |
22 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception | 22 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception |
diff --git a/src/lanes.cpp b/src/lanes.cpp index 572d8f9..e545ca0 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -329,7 +329,7 @@ LUAG_FUNC(lane_new) | |||
329 | DEBUGSPEW_CODE(DebugSpew(lane->U) << "lane_new: preparing lane userdata" << std::endl); | 329 | DEBUGSPEW_CODE(DebugSpew(lane->U) << "lane_new: preparing lane userdata" << std::endl); |
330 | STACK_CHECK_START_REL(L, 0); | 330 | STACK_CHECK_START_REL(L, 0); |
331 | // a Lane full userdata needs a single uservalue | 331 | // a Lane full userdata needs a single uservalue |
332 | Lane** const _ud{ luaG_newuserdatauv<Lane*>(L, 1) }; // L: ... lane | 332 | Lane** const _ud{ luaG_newuserdatauv<Lane*>(L, UserValueCount{ 1 }) }; // L: ... lane |
333 | *_ud = lane; // don't forget to store the pointer in the userdata! | 333 | *_ud = lane; // don't forget to store the pointer in the userdata! |
334 | 334 | ||
335 | // Set metatable for the userdata | 335 | // Set metatable for the userdata |
@@ -342,7 +342,7 @@ LUAG_FUNC(lane_new) | |||
342 | lua_newtable(L); // L: ... lane {uv} | 342 | lua_newtable(L); // L: ... lane {uv} |
343 | 343 | ||
344 | // Store the gc_cb callback in the uservalue | 344 | // Store the gc_cb callback in the uservalue |
345 | StackIndex const _gc_cb_idx{ lua_isnoneornil(L, kGcCbIdx) ? 0 : kGcCbIdx }; | 345 | StackIndex const _gc_cb_idx{ lua_isnoneornil(L, kGcCbIdx) ? kIdxNone : kGcCbIdx }; |
346 | if (_gc_cb_idx > 0) { | 346 | if (_gc_cb_idx > 0) { |
347 | kLaneGC.pushKey(L); // L: ... lane {uv} k | 347 | kLaneGC.pushKey(L); // L: ... lane {uv} k |
348 | lua_pushvalue(L, _gc_cb_idx); // L: ... lane {uv} k gc_cb | 348 | lua_pushvalue(L, _gc_cb_idx); // L: ... lane {uv} k gc_cb |
@@ -354,7 +354,7 @@ LUAG_FUNC(lane_new) | |||
354 | 354 | ||
355 | lua_State* const _L2{ lane->L }; | 355 | lua_State* const _L2{ lane->L }; |
356 | STACK_CHECK_START_REL(_L2, 0); | 356 | STACK_CHECK_START_REL(_L2, 0); |
357 | StackIndex const _name_idx{ lua_isnoneornil(L, kNameIdx) ? 0 : kNameIdx }; | 357 | StackIndex const _name_idx{ lua_isnoneornil(L, kNameIdx) ? kIdxNone : kNameIdx }; |
358 | std::string_view const _debugName{ (_name_idx > 0) ? luaG_tostring(L, _name_idx) : std::string_view{} }; | 358 | std::string_view const _debugName{ (_name_idx > 0) ? luaG_tostring(L, _name_idx) : std::string_view{} }; |
359 | if (!_debugName.empty()) | 359 | if (!_debugName.empty()) |
360 | { | 360 | { |
@@ -393,7 +393,7 @@ LUAG_FUNC(lane_new) | |||
393 | // On some platforms, -3 is equivalent to -2 and +3 to +2 | 393 | // On some platforms, -3 is equivalent to -2 and +3 to +2 |
394 | int const _priority{ | 394 | int const _priority{ |
395 | std::invoke([L = L_]() { | 395 | std::invoke([L = L_]() { |
396 | int const _prio_idx{ lua_isnoneornil(L, kPrioIdx) ? 0 : kPrioIdx }; | 396 | StackIndex const _prio_idx{ lua_isnoneornil(L, kPrioIdx) ? kIdxNone : kPrioIdx }; |
397 | if (_prio_idx == 0) { | 397 | if (_prio_idx == 0) { |
398 | return kThreadPrioDefault; | 398 | return kThreadPrioDefault; |
399 | } | 399 | } |
@@ -412,7 +412,7 @@ LUAG_FUNC(lane_new) | |||
412 | STACK_CHECK_START_REL(L_, 0); | 412 | STACK_CHECK_START_REL(L_, 0); |
413 | 413 | ||
414 | // package | 414 | // package |
415 | StackIndex const _package_idx{ lua_isnoneornil(L_, kPackIdx) ? 0 : kPackIdx }; | 415 | StackIndex const _package_idx{ lua_isnoneornil(L_, kPackIdx) ? kIdxNone : kPackIdx }; |
416 | if (_package_idx != 0) { | 416 | if (_package_idx != 0) { |
417 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: update 'package'" << std::endl); | 417 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: update 'package'" << std::endl); |
418 | // when copying with mode LookupMode::LaneBody, should raise an error in case of problem, not leave it one the stack | 418 | // when copying with mode LookupMode::LaneBody, should raise an error in case of problem, not leave it one the stack |
@@ -424,7 +424,7 @@ LUAG_FUNC(lane_new) | |||
424 | STACK_CHECK(_L2, 0); | 424 | STACK_CHECK(_L2, 0); |
425 | 425 | ||
426 | // modules to require in the target lane *before* the function is transfered! | 426 | // modules to require in the target lane *before* the function is transfered! |
427 | StackIndex const _required_idx{ lua_isnoneornil(L_, kRequIdx) ? 0 : kRequIdx }; | 427 | StackIndex const _required_idx{ lua_isnoneornil(L_, kRequIdx) ? kIdxNone : kRequIdx }; |
428 | if (_required_idx != 0) { | 428 | if (_required_idx != 0) { |
429 | int _nbRequired{ 1 }; | 429 | int _nbRequired{ 1 }; |
430 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: process 'required' list" << std::endl); | 430 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: process 'required' list" << std::endl); |
@@ -473,7 +473,7 @@ LUAG_FUNC(lane_new) | |||
473 | // Appending the specified globals to the global environment | 473 | // Appending the specified globals to the global environment |
474 | // *after* stdlibs have been loaded and modules required, in case we transfer references to native functions they exposed... | 474 | // *after* stdlibs have been loaded and modules required, in case we transfer references to native functions they exposed... |
475 | // | 475 | // |
476 | StackIndex const _globals_idx{ lua_isnoneornil(L_, kGlobIdx) ? 0 : kGlobIdx }; | 476 | StackIndex const _globals_idx{ lua_isnoneornil(L_, kGlobIdx) ? kIdxNone : kGlobIdx }; |
477 | if (_globals_idx != 0) { | 477 | if (_globals_idx != 0) { |
478 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: transfer globals" << std::endl); | 478 | DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: transfer globals" << std::endl); |
479 | if (!lua_istable(L_, _globals_idx)) { | 479 | if (!lua_istable(L_, _globals_idx)) { |
diff --git a/src/linda.cpp b/src/linda.cpp index 6655ae4..15e7a2c 100644 --- a/src/linda.cpp +++ b/src/linda.cpp | |||
@@ -196,7 +196,7 @@ int Linda::ProtectedCall(lua_State* const L_, lua_CFunction const f_) | |||
196 | 196 | ||
197 | // acquire the keeper | 197 | // acquire the keeper |
198 | Keeper* const _keeper{ _linda->acquireKeeper() }; | 198 | Keeper* const _keeper{ _linda->acquireKeeper() }; |
199 | KeeperState const _K{ _keeper ? _keeper->K : KeeperState{ nullptr } }; | 199 | KeeperState const _K{ _keeper ? _keeper->K : KeeperState{ static_cast<lua_State*>(nullptr) } }; |
200 | if (_K == nullptr) | 200 | if (_K == nullptr) |
201 | return 0; | 201 | return 0; |
202 | 202 | ||
@@ -469,7 +469,7 @@ LUAG_FUNC(linda_limit) | |||
469 | luaL_argcheck(L_, _nargs == 2 || _nargs == 3, 2, "wrong number of arguments"); | 469 | luaL_argcheck(L_, _nargs == 2 || _nargs == 3, 2, "wrong number of arguments"); |
470 | // make sure we got a numeric limit, or "unlimited", (or nothing) | 470 | // make sure we got a numeric limit, or "unlimited", (or nothing) |
471 | bool const _unlimited{ luaG_tostring(L_, StackIndex{ 3 }) == "unlimited" }; | 471 | bool const _unlimited{ luaG_tostring(L_, StackIndex{ 3 }) == "unlimited" }; |
472 | LindaLimit const _val{ _unlimited ? std::numeric_limits<LindaLimit::type>::max() : LindaLimit{ static_cast<LindaLimit::type>(luaL_optinteger(L_, 3, 0)) } }; | 472 | LindaLimit const _val{ _unlimited ? std::numeric_limits<LindaLimit::type>::max() : static_cast<LindaLimit::type>(luaL_optinteger(L_, 3, 0)) }; |
473 | if (_val < 0) { | 473 | if (_val < 0) { |
474 | raise_luaL_argerror(L_, StackIndex{ 3 }, "limit must be >= 0"); | 474 | raise_luaL_argerror(L_, StackIndex{ 3 }, "limit must be >= 0"); |
475 | } | 475 | } |
@@ -575,7 +575,7 @@ LUAG_FUNC(linda_receive) | |||
575 | 575 | ||
576 | Lane* const _lane{ kLanePointerRegKey.readLightUserDataValue<Lane>(L_) }; | 576 | Lane* const _lane{ kLanePointerRegKey.readLightUserDataValue<Lane>(L_) }; |
577 | Keeper* const _keeper{ _linda->whichKeeper() }; | 577 | Keeper* const _keeper{ _linda->whichKeeper() }; |
578 | KeeperState const _K{ _keeper ? _keeper->K : KeeperState{ nullptr } }; | 578 | KeeperState const _K{ _keeper ? _keeper->K : KeeperState{ static_cast<lua_State*>(nullptr) } }; |
579 | if (_K == nullptr) | 579 | if (_K == nullptr) |
580 | return 0; | 580 | return 0; |
581 | 581 | ||
@@ -714,7 +714,7 @@ LUAG_FUNC(linda_send) | |||
714 | { | 714 | { |
715 | Lane* const _lane{ kLanePointerRegKey.readLightUserDataValue<Lane>(L_) }; | 715 | Lane* const _lane{ kLanePointerRegKey.readLightUserDataValue<Lane>(L_) }; |
716 | Keeper* const _keeper{ _linda->whichKeeper() }; | 716 | Keeper* const _keeper{ _linda->whichKeeper() }; |
717 | KeeperState const _K{ _keeper ? _keeper->K : KeeperState{ nullptr } }; | 717 | KeeperState const _K{ _keeper ? _keeper->K : KeeperState{ static_cast<lua_State*>(nullptr) } }; |
718 | if (_K == nullptr) | 718 | if (_K == nullptr) |
719 | return 0; | 719 | return 0; |
720 | 720 | ||
diff --git a/src/lindafactory.cpp b/src/lindafactory.cpp index e5903fb..cb801dd 100644 --- a/src/lindafactory.cpp +++ b/src/lindafactory.cpp | |||
@@ -80,7 +80,7 @@ void LindaFactory::deleteDeepObjectInternal(lua_State* L_, DeepPrelude* o_) cons | |||
80 | Keeper* const _keeper{ _need_acquire_release ? _linda->acquireKeeper() : _myKeeper }; | 80 | Keeper* const _keeper{ _need_acquire_release ? _linda->acquireKeeper() : _myKeeper }; |
81 | LUA_ASSERT(L_, _keeper == _myKeeper); // should always be the same | 81 | LUA_ASSERT(L_, _keeper == _myKeeper); // should always be the same |
82 | // hopefully this won't ever raise an error as we would jump to the closest pcall site while forgetting to release the keeper mutex... | 82 | // hopefully this won't ever raise an error as we would jump to the closest pcall site while forgetting to release the keeper mutex... |
83 | [[maybe_unused]] KeeperCallResult const result{ keeper_call(_keeper->K, KEEPER_API(destruct), L_, _linda, StackIndex{ 0 }) }; | 83 | [[maybe_unused]] KeeperCallResult const result{ keeper_call(_keeper->K, KEEPER_API(destruct), L_, _linda, kIdxNone) }; |
84 | LUA_ASSERT(L_, result.has_value() && result.value() == 0); | 84 | LUA_ASSERT(L_, result.has_value() && result.value() == 0); |
85 | if (_need_acquire_release) { | 85 | if (_need_acquire_release) { |
86 | _linda->releaseKeeper(_keeper); | 86 | _linda->releaseKeeper(_keeper); |
diff --git a/src/stackindex.hpp b/src/stackindex.hpp index 1c2ce8c..c414ce2 100644 --- a/src/stackindex.hpp +++ b/src/stackindex.hpp | |||
@@ -5,6 +5,9 @@ | |||
5 | DECLARE_UNIQUE_TYPE(StackIndex, int); | 5 | DECLARE_UNIQUE_TYPE(StackIndex, int); |
6 | static_assert(std::is_trivial_v<StackIndex>); | 6 | static_assert(std::is_trivial_v<StackIndex>); |
7 | 7 | ||
8 | DECLARE_UNIQUE_TYPE(UserValueIndex, int); | ||
9 | static_assert(std::is_trivial_v<UserValueIndex>); | ||
10 | |||
8 | DECLARE_UNIQUE_TYPE(UserValueCount, int); | 11 | DECLARE_UNIQUE_TYPE(UserValueCount, int); |
9 | static_assert(std::is_trivial_v<UserValueCount>); | 12 | static_assert(std::is_trivial_v<UserValueCount>); |
10 | 13 | ||
@@ -14,4 +17,5 @@ static_assert(std::is_trivial_v<UserValueCount>); | |||
14 | // ################################################################################################# | 17 | // ################################################################################################# |
15 | 18 | ||
16 | static constexpr StackIndex kIdxRegistry{ LUA_REGISTRYINDEX }; | 19 | static constexpr StackIndex kIdxRegistry{ LUA_REGISTRYINDEX }; |
20 | static constexpr StackIndex kIdxNone{ 0 }; | ||
17 | static constexpr StackIndex kIdxTop{ -1 }; | 21 | static constexpr StackIndex kIdxTop{ -1 }; |
diff --git a/src/unique.hpp b/src/unique.hpp index 98a9d48..27ea71e 100644 --- a/src/unique.hpp +++ b/src/unique.hpp | |||
@@ -10,6 +10,7 @@ class Unique | |||
10 | T val; // no default initialization so that std::is_trivial_v<Unique<T>> == true | 10 | T val; // no default initialization so that std::is_trivial_v<Unique<T>> == true |
11 | 11 | ||
12 | public: | 12 | public: |
13 | using self = Unique<T, TAG, specialization>; | ||
13 | using type = T; | 14 | using type = T; |
14 | 15 | ||
15 | ~Unique() = default; | 16 | ~Unique() = default; |
@@ -25,12 +26,20 @@ class Unique | |||
25 | constexpr Unique& operator=(Unique const&) = default; | 26 | constexpr Unique& operator=(Unique const&) = default; |
26 | constexpr Unique& operator=(Unique&&) = default; | 27 | constexpr Unique& operator=(Unique&&) = default; |
27 | 28 | ||
29 | // Forbid construction with any other class, especially with types that convert naturally to UnderlyingType. | ||
30 | // For instance, this prevents construction with a float when UnderlyingType is an integer type. | ||
31 | // Conversion will have to be explicit and the developer will be aware of it. | ||
32 | // However we want to keep the same-type copy constructors (including with an inherited class), hence the enable_if stuff. | ||
33 | template <typename AnyOtherClass, std::enable_if_t<!std::is_base_of_v<self, std::decay_t<AnyOtherClass>>, bool> = true> | ||
34 | Unique(AnyOtherClass&&) = delete; | ||
35 | |||
28 | // can't implicitly affect from base type | 36 | // can't implicitly affect from base type |
29 | Unique& operator=(T const&) = delete; | 37 | Unique& operator=(T const&) = delete; |
30 | constexpr Unique& operator=(T&&) = delete; | 38 | constexpr Unique& operator=(T&&) = delete; |
31 | 39 | ||
32 | // cast | 40 | // cast |
33 | constexpr operator T() const noexcept { return val; } | 41 | constexpr operator T() const noexcept { return val; } |
42 | constexpr T value() const noexcept { return val; } | ||
34 | 43 | ||
35 | // pre-increment | 44 | // pre-increment |
36 | auto& operator++() noexcept | 45 | auto& operator++() noexcept |
diff --git a/src/universe.h b/src/universe.h index dc8940f..75e2198 100644 --- a/src/universe.h +++ b/src/universe.h | |||
@@ -119,7 +119,7 @@ class Universe | |||
119 | std::atomic<int> selfdestructingCount{ 0 }; | 119 | std::atomic<int> selfdestructingCount{ 0 }; |
120 | 120 | ||
121 | public: | 121 | public: |
122 | [[nodiscard]] static void* operator new([[maybe_unused]] size_t size_, lua_State* L_) noexcept { return luaG_newuserdatauv<Universe>(L_, 0); }; | 122 | [[nodiscard]] static void* operator new([[maybe_unused]] size_t size_, lua_State* L_) noexcept { return luaG_newuserdatauv<Universe>(L_, UserValueCount{ 0 }); }; |
123 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception | 123 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception |
124 | static void operator delete([[maybe_unused]] void* p_, [[maybe_unused]] lua_State* L_) {} // nothing to do, as nothing is allocated independently | 124 | static void operator delete([[maybe_unused]] void* p_, [[maybe_unused]] lua_State* L_) {} // nothing to do, as nothing is allocated independently |
125 | 125 | ||