diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-04-26 12:02:49 +0200 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-04-26 12:02:49 +0200 |
| commit | 8aff7818754d24e230a22220db1ed834487d0559 (patch) | |
| tree | 628d0d38057421bfde8dd6226e121b4336c9cf87 /src | |
| parent | 8508f12ab2f84ecc4472254564b4585d697b5778 (diff) | |
| download | lanes-8aff7818754d24e230a22220db1ed834487d0559.tar.gz lanes-8aff7818754d24e230a22220db1ed834487d0559.tar.bz2 lanes-8aff7818754d24e230a22220db1ed834487d0559.zip | |
Move LindaFactory in separate files
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile | 2 | ||||
| -rw-r--r-- | src/deep.h | 16 | ||||
| -rw-r--r-- | src/lanesconf.h | 6 | ||||
| -rw-r--r-- | src/linda.cpp | 164 | ||||
| -rw-r--r-- | src/linda.h | 5 | ||||
| -rw-r--r-- | src/lindafactory.cpp | 136 | ||||
| -rw-r--r-- | src/lindafactory.h | 28 |
7 files changed, 205 insertions, 152 deletions
diff --git a/src/Makefile b/src/Makefile index d6bdfd7..06bbcd0 100644 --- a/src/Makefile +++ b/src/Makefile | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | MODULE=lanes | 8 | MODULE=lanes |
| 9 | 9 | ||
| 10 | SRC=lanes.c cancel.cpp compat.cpp threading.cpp tools.cpp state.cpp linda.cpp deep.cpp keeper.cpp universe.cpp | 10 | SRC=lanes.c cancel.cpp compat.cpp threading.cpp tools.cpp state.cpp linda.cpp lindafactory.cpp deep.cpp keeper.cpp universe.cpp |
| 11 | 11 | ||
| 12 | OBJ=$(SRC:.c=.o) | 12 | OBJ=$(SRC:.c=.o) |
| 13 | 13 | ||
| @@ -2,7 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | /* | 3 | /* |
| 4 | * public 'deep' API to be used by external modules if they want to implement Lanes-aware userdata | 4 | * public 'deep' API to be used by external modules if they want to implement Lanes-aware userdata |
| 5 | * said modules will have to link against lanes (it is not really possible to separate the 'deep userdata' implementation from the rest of Lanes) | 5 | * said modules can either link against lanes, or embed compat.cpp/h deep.cpp/h tools.cpp/h universe.cpp/h |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #ifdef __cplusplus | 8 | #ifdef __cplusplus |
| @@ -69,16 +69,16 @@ class DeepFactory | |||
| 69 | private: | 69 | private: |
| 70 | 70 | ||
| 71 | // NVI: private overrides | 71 | // NVI: private overrides |
| 72 | virtual DeepPrelude* newDeepObjectInternal(lua_State* L) const = 0; | 72 | virtual DeepPrelude* newDeepObjectInternal(lua_State* L_) const = 0; |
| 73 | virtual void deleteDeepObjectInternal(lua_State* L, DeepPrelude* o_) const = 0; | 73 | virtual void deleteDeepObjectInternal(lua_State* L_, DeepPrelude* o_) const = 0; |
| 74 | virtual void createMetatable(lua_State* L) const = 0; | 74 | virtual void createMetatable(lua_State* L_) const = 0; |
| 75 | virtual char const* moduleName() const = 0; | 75 | virtual char const* moduleName() const = 0; |
| 76 | 76 | ||
| 77 | public: | 77 | public: |
| 78 | 78 | ||
| 79 | // NVI: public interface | 79 | // NVI: public interface |
| 80 | int pushDeepUserdata(DestState L, int nuv_) const; | 80 | int pushDeepUserdata(DestState L_, int nuv_) const; |
| 81 | DeepPrelude* toDeep(lua_State* L, int index) const; | 81 | DeepPrelude* toDeep(lua_State* L_, int index_) const; |
| 82 | static void DeleteDeepObject(lua_State* L, DeepPrelude* o_); | 82 | static void DeleteDeepObject(lua_State* L_, DeepPrelude* o_); |
| 83 | static char const* PushDeepProxy(DestState L, DeepPrelude* prelude, int nuv_, LookupMode mode_); | 83 | static char const* PushDeepProxy(DestState L_, DeepPrelude* o_, int nuv_, LookupMode mode_); |
| 84 | }; | 84 | }; |
diff --git a/src/lanesconf.h b/src/lanesconf.h index 8c66bd1..7b4ff93 100644 --- a/src/lanesconf.h +++ b/src/lanesconf.h | |||
| @@ -19,10 +19,8 @@ | |||
| 19 | // file-level static variable: in 'global' namespace, prefix s, followed by an uppercase letter | 19 | // file-level static variable: in 'global' namespace, prefix s, followed by an uppercase letter |
| 20 | // file-level function (static or not): no prefix, start with an uppercase letter | 20 | // file-level function (static or not): no prefix, start with an uppercase letter |
| 21 | // class/struct/enum type: no prefix, start with an uppercase letter | 21 | // class/struct/enum type: no prefix, start with an uppercase letter |
| 22 | // static class member: prefix s, followed by an uppercase letter | 22 | // static class member/method: no prefix, start with an uppercase letter |
| 23 | // regular class member: no prefix, start with a lowercase letter | 23 | // regular class member/method: no prefix, start with a lowercase letter |
| 24 | // static class method: no prefix, start with an uppercase letter | ||
| 25 | // regular class method: no prefix, start with a lowercase letter | ||
| 26 | // function argument: suffix _ | 24 | // function argument: suffix _ |
| 27 | // static function variable: prefix s, followed by an uppercase letter | 25 | // static function variable: prefix s, followed by an uppercase letter |
| 28 | // function local variable: prefix l, followed by an uppercase letter | 26 | // function local variable: prefix l, followed by an uppercase letter |
diff --git a/src/linda.cpp b/src/linda.cpp index 590b487..bc931ac 100644 --- a/src/linda.cpp +++ b/src/linda.cpp | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | /* | 7 | /* |
| 8 | =============================================================================== | 8 | =============================================================================== |
| 9 | 9 | ||
| 10 | Copyright (C) 2018 benoit Germain <bnt.germain@gmail.com> | 10 | Copyright (C) 2018-2024 benoit Germain <bnt.germain@gmail.com> |
| 11 | 11 | ||
| 12 | Permission is hereby granted, free of charge, to any person obtaining a copy | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy |
| 13 | of this software and associated documentation files (the "Software"), to deal | 13 | of this software and associated documentation files (the "Software"), to deal |
| @@ -35,29 +35,13 @@ THE SOFTWARE. | |||
| 35 | #include "compat.h" | 35 | #include "compat.h" |
| 36 | #include "keeper.h" | 36 | #include "keeper.h" |
| 37 | #include "lanes_private.h" | 37 | #include "lanes_private.h" |
| 38 | #include "lindafactory.h" | ||
| 38 | #include "threading.h" | 39 | #include "threading.h" |
| 39 | #include "tools.h" | 40 | #include "tools.h" |
| 40 | #include "universe.h" | 41 | #include "universe.h" |
| 41 | 42 | ||
| 42 | #include <functional> | 43 | #include <functional> |
| 43 | 44 | ||
| 44 | // xxh64 of string "kLindaBatched" generated at https://www.pelock.com/products/hash-calculator | ||
| 45 | static constexpr UniqueKey kLindaBatched{ 0xB8234DF772646567ull, "linda.batched" }; | ||
| 46 | |||
| 47 | // ################################################################################################# | ||
| 48 | |||
| 49 | class LindaFactory : public DeepFactory | ||
| 50 | { | ||
| 51 | private: | ||
| 52 | |||
| 53 | DeepPrelude* newDeepObjectInternal(lua_State* L) const override; | ||
| 54 | void deleteDeepObjectInternal(lua_State* L, DeepPrelude* o_) const override; | ||
| 55 | void createMetatable(lua_State* L) const override; | ||
| 56 | char const* moduleName() const override; | ||
| 57 | }; | ||
| 58 | // I'm not totally happy with having a global variable. But since it's stateless, it will do for the time being. | ||
| 59 | static LindaFactory g_LindaFactory; | ||
| 60 | |||
| 61 | // ################################################################################################# | 45 | // ################################################################################################# |
| 62 | // ################################################################################################# | 46 | // ################################################################################################# |
| 63 | 47 | ||
| @@ -67,7 +51,7 @@ static LindaFactory g_LindaFactory; | |||
| 67 | static constexpr uintptr_t kPointerMagicShift{ 3 }; | 51 | static constexpr uintptr_t kPointerMagicShift{ 3 }; |
| 68 | 52 | ||
| 69 | Linda::Linda(Universe* U_, LindaGroup group_, char const* name_, size_t len_) | 53 | Linda::Linda(Universe* U_, LindaGroup group_, char const* name_, size_t len_) |
| 70 | : DeepPrelude{ g_LindaFactory } | 54 | : DeepPrelude{ LindaFactory::Instance } |
| 71 | , U{ U_ } | 55 | , U{ U_ } |
| 72 | , m_keeper_index{ (group_ ? group_ : static_cast<int>(std::bit_cast<uintptr_t>(this) >> kPointerMagicShift)) % U_->keepers->nb_keepers } | 56 | , m_keeper_index{ (group_ ? group_ : static_cast<int>(std::bit_cast<uintptr_t>(this) >> kPointerMagicShift)) % U_->keepers->nb_keepers } |
| 73 | { | 57 | { |
| @@ -132,7 +116,7 @@ char const* Linda::getName() const | |||
| 132 | template <bool OPT> | 116 | template <bool OPT> |
| 133 | [[nodiscard]] static inline Linda* ToLinda(lua_State* L_, int idx_) | 117 | [[nodiscard]] static inline Linda* ToLinda(lua_State* L_, int idx_) |
| 134 | { | 118 | { |
| 135 | Linda* const linda{ static_cast<Linda*>(g_LindaFactory.toDeep(L_, idx_)) }; | 119 | Linda* const linda{ static_cast<Linda*>(LindaFactory::Instance.toDeep(L_, idx_)) }; |
| 136 | if constexpr (!OPT) | 120 | if constexpr (!OPT) |
| 137 | { | 121 | { |
| 138 | luaL_argcheck(L_, linda != nullptr, idx_, "expecting a linda object"); // doesn't return if linda is nullptr | 122 | luaL_argcheck(L_, linda != nullptr, idx_, "expecting a linda object"); // doesn't return if linda is nullptr |
| @@ -856,124 +840,26 @@ LUAG_FUNC(linda_towatch) | |||
| 856 | 840 | ||
| 857 | // ################################################################################################# | 841 | // ################################################################################################# |
| 858 | 842 | ||
| 859 | DeepPrelude* LindaFactory::newDeepObjectInternal(lua_State* L) const | 843 | namespace global { |
| 860 | { | 844 | static luaL_Reg const sLindaMT[] = { |
| 861 | size_t name_len = 0; | 845 | { "__concat", LG_linda_concat }, |
| 862 | char const* linda_name = nullptr; | 846 | { "__tostring", LG_linda_tostring }, |
| 863 | LindaGroup linda_group{ 0 }; | 847 | { "__towatch", LG_linda_towatch }, // Decoda __towatch support |
| 864 | // should have a string and/or a number of the stack as parameters (name and group) | 848 | { "cancel", LG_linda_cancel }, |
| 865 | switch (lua_gettop(L)) | 849 | { "count", LG_linda_count }, |
| 866 | { | 850 | { "deep", LG_linda_deep }, |
| 867 | default: // 0 | 851 | { "dump", LG_linda_dump }, |
| 868 | break; | 852 | { "get", LG_linda_get }, |
| 869 | 853 | { "limit", LG_linda_limit }, | |
| 870 | case 1: // 1 parameter, either a name or a group | 854 | { "receive", LG_linda_receive }, |
| 871 | if (lua_type(L, -1) == LUA_TSTRING) | 855 | { "send", LG_linda_send }, |
| 872 | { | 856 | { "set", LG_linda_set }, |
| 873 | linda_name = lua_tolstring(L, -1, &name_len); | 857 | { nullptr, nullptr } |
| 874 | } | 858 | }; |
| 875 | else | 859 | } // namespace global |
| 876 | { | 860 | // it's somewhat awkward to instanciate the LindaFactory here instead of lindafactory.cpp, |
| 877 | linda_group = LindaGroup{ static_cast<int>(lua_tointeger(L, -1)) }; | 861 | // but that's necessary to provide s_LindaMT without exposing it outside linda.cpp. |
| 878 | } | 862 | /*static*/ LindaFactory LindaFactory::Instance{ global::sLindaMT }; |
| 879 | break; | ||
| 880 | |||
| 881 | case 2: // 2 parameters, a name and group, in that order | ||
| 882 | linda_name = lua_tolstring(L, -2, &name_len); | ||
| 883 | linda_group = LindaGroup{ static_cast<int>(lua_tointeger(L, -1)) }; | ||
| 884 | break; | ||
| 885 | } | ||
| 886 | |||
| 887 | /* The deep data is allocated separately of Lua stack; we might no | ||
| 888 | * longer be around when last reference to it is being released. | ||
| 889 | * One can use any memory allocation scheme. | ||
| 890 | * just don't use L's allocF because we don't know which state will get the honor of GCing the linda | ||
| 891 | */ | ||
| 892 | Universe* const U{ universe_get(L) }; | ||
| 893 | Linda* linda{ new (U) Linda{ U, linda_group, linda_name, name_len } }; | ||
| 894 | return linda; | ||
| 895 | } | ||
| 896 | |||
| 897 | // ################################################################################################# | ||
| 898 | |||
| 899 | void LindaFactory::deleteDeepObjectInternal(lua_State* L, DeepPrelude* o_) const | ||
| 900 | { | ||
| 901 | Linda* const linda{ static_cast<Linda*>(o_) }; | ||
| 902 | LUA_ASSERT(L, linda); | ||
| 903 | Keeper* const myK{ linda->whichKeeper() }; | ||
| 904 | // if collected after the universe, keepers are already destroyed, and there is nothing to clear | ||
| 905 | if (myK) | ||
| 906 | { | ||
| 907 | // if collected from my own keeper, we can't acquire/release it | ||
| 908 | // because we are already inside a protected area, and trying to do so would deadlock! | ||
| 909 | bool const need_acquire_release{ myK->L != L }; | ||
| 910 | // Clean associated structures in the keeper state. | ||
| 911 | Keeper* const K{ need_acquire_release ? linda->acquireKeeper() : myK }; | ||
| 912 | // hopefully this won't ever raise an error as we would jump to the closest pcall site while forgetting to release the keeper mutex... | ||
| 913 | [[maybe_unused]] KeeperCallResult const result{ keeper_call(linda->U, K->L, KEEPER_API(clear), L, linda, 0) }; | ||
| 914 | LUA_ASSERT(L, result.has_value() && result.value() == 0); | ||
| 915 | if (need_acquire_release) | ||
| 916 | { | ||
| 917 | linda->releaseKeeper(K); | ||
| 918 | } | ||
| 919 | } | ||
| 920 | |||
| 921 | delete linda; // operator delete overload ensures things go as expected | ||
| 922 | } | ||
| 923 | |||
| 924 | // ################################################################################################# | ||
| 925 | |||
| 926 | static luaL_Reg const s_LindaMT[] = | ||
| 927 | { | ||
| 928 | { "__concat", LG_linda_concat }, | ||
| 929 | { "__tostring", LG_linda_tostring }, | ||
| 930 | { "__towatch", LG_linda_towatch }, // Decoda __towatch support | ||
| 931 | { "cancel", LG_linda_cancel }, | ||
| 932 | { "count", LG_linda_count }, | ||
| 933 | { "deep", LG_linda_deep }, | ||
| 934 | { "dump", LG_linda_dump }, | ||
| 935 | { "get", LG_linda_get }, | ||
| 936 | { "limit", LG_linda_limit }, | ||
| 937 | { "receive", LG_linda_receive }, | ||
| 938 | { "send", LG_linda_send }, | ||
| 939 | { "set", LG_linda_set }, | ||
| 940 | { nullptr, nullptr } | ||
| 941 | }; | ||
| 942 | |||
| 943 | void LindaFactory::createMetatable(lua_State* L) const | ||
| 944 | { | ||
| 945 | STACK_CHECK_START_REL(L, 0); | ||
| 946 | lua_newtable(L); | ||
| 947 | // metatable is its own index | ||
| 948 | lua_pushvalue(L, -1); | ||
| 949 | lua_setfield(L, -2, "__index"); | ||
| 950 | |||
| 951 | // protect metatable from external access | ||
| 952 | lua_pushliteral(L, "Linda"); | ||
| 953 | lua_setfield(L, -2, "__metatable"); | ||
| 954 | |||
| 955 | // the linda functions | ||
| 956 | luaL_setfuncs(L, s_LindaMT, 0); | ||
| 957 | |||
| 958 | // some constants | ||
| 959 | kLindaBatched.pushKey(L); | ||
| 960 | lua_setfield(L, -2, "batched"); | ||
| 961 | |||
| 962 | kNilSentinel.pushKey(L); | ||
| 963 | lua_setfield(L, -2, "null"); | ||
| 964 | |||
| 965 | STACK_CHECK(L, 1); | ||
| 966 | } | ||
| 967 | |||
| 968 | // ################################################################################################# | ||
| 969 | |||
| 970 | char const* LindaFactory::moduleName() const | ||
| 971 | { | ||
| 972 | // linda is a special case because we know lanes must be loaded from the main lua state | ||
| 973 | // to be able to ever get here, so we know it will remain loaded as long a the main state is around | ||
| 974 | // in other words, forever. | ||
| 975 | return nullptr; | ||
| 976 | } | ||
| 977 | 863 | ||
| 978 | // ################################################################################################# | 864 | // ################################################################################################# |
| 979 | 865 | ||
| @@ -996,5 +882,5 @@ LUAG_FUNC(linda) | |||
| 996 | luaL_checktype(L, 1, LUA_TSTRING); | 882 | luaL_checktype(L, 1, LUA_TSTRING); |
| 997 | luaL_checktype(L, 2, LUA_TNUMBER); | 883 | luaL_checktype(L, 2, LUA_TNUMBER); |
| 998 | } | 884 | } |
| 999 | return g_LindaFactory.pushDeepUserdata(DestState{ L }, 0); | 885 | return LindaFactory::Instance.pushDeepUserdata(DestState{ L }, 0); |
| 1000 | } | 886 | } |
diff --git a/src/linda.h b/src/linda.h index f3b1844..21b6ecc 100644 --- a/src/linda.h +++ b/src/linda.h | |||
| @@ -13,6 +13,11 @@ struct Keeper; | |||
| 13 | 13 | ||
| 14 | // ################################################################################################# | 14 | // ################################################################################################# |
| 15 | 15 | ||
| 16 | // xxh64 of string "kLindaBatched" generated at https://www.pelock.com/products/hash-calculator | ||
| 17 | static constexpr UniqueKey kLindaBatched{ 0xB8234DF772646567ull, "linda.batched" }; | ||
| 18 | |||
| 19 | // ################################################################################################# | ||
| 20 | |||
| 16 | using LindaGroup = Unique<int>; | 21 | using LindaGroup = Unique<int>; |
| 17 | 22 | ||
| 18 | class Linda : public DeepPrelude // Deep userdata MUST start with this header | 23 | class Linda : public DeepPrelude // Deep userdata MUST start with this header |
diff --git a/src/lindafactory.cpp b/src/lindafactory.cpp new file mode 100644 index 0000000..81e472d --- /dev/null +++ b/src/lindafactory.cpp | |||
| @@ -0,0 +1,136 @@ | |||
| 1 | /* | ||
| 2 | * LINDAFACTORY.CPP Copyright (c) 2024-, Benoit Germain | ||
| 3 | * | ||
| 4 | * Linda deep userdata factory | ||
| 5 | */ | ||
| 6 | |||
| 7 | /* | ||
| 8 | =============================================================================== | ||
| 9 | |||
| 10 | Copyright (C) 2024- benoit Germain <bnt.germain@gmail.com> | ||
| 11 | |||
| 12 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 13 | of this software and associated documentation files (the "Software"), to deal | ||
| 14 | in the Software without restriction, including without limitation the rights | ||
| 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 16 | copies of the Software, and to permit persons to whom the Software is | ||
| 17 | furnished to do so, subject to the following conditions: | ||
| 18 | |||
| 19 | The above copyright notice and this permission notice shall be included in | ||
| 20 | all copies or substantial portions of the Software. | ||
| 21 | |||
| 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 28 | THE SOFTWARE. | ||
| 29 | |||
| 30 | =============================================================================== | ||
| 31 | */ | ||
| 32 | |||
| 33 | #include "lindafactory.h" | ||
| 34 | |||
| 35 | #include "linda.h" | ||
| 36 | |||
| 37 | // ################################################################################################# | ||
| 38 | |||
| 39 | void LindaFactory::createMetatable(lua_State* L_) const | ||
| 40 | { | ||
| 41 | STACK_CHECK_START_REL(L_, 0); | ||
| 42 | lua_newtable(L_); | ||
| 43 | // metatable is its own index | ||
| 44 | lua_pushvalue(L_, -1); | ||
| 45 | lua_setfield(L_, -2, "__index"); | ||
| 46 | |||
| 47 | // protect metatable from external access | ||
| 48 | lua_pushliteral(L_, "Linda"); | ||
| 49 | lua_setfield(L_, -2, "__metatable"); | ||
| 50 | |||
| 51 | // the linda functions | ||
| 52 | luaL_setfuncs(L_, mLindaMT, 0); | ||
| 53 | |||
| 54 | // some constants | ||
| 55 | kLindaBatched.pushKey(L_); | ||
| 56 | lua_setfield(L_, -2, "batched"); | ||
| 57 | |||
| 58 | kNilSentinel.pushKey(L_); | ||
| 59 | lua_setfield(L_, -2, "null"); | ||
| 60 | |||
| 61 | STACK_CHECK(L_, 1); | ||
| 62 | } | ||
| 63 | |||
| 64 | // ################################################################################################# | ||
| 65 | |||
| 66 | void LindaFactory::deleteDeepObjectInternal(lua_State* L_, DeepPrelude* o_) const | ||
| 67 | { | ||
| 68 | Linda* const linda{ static_cast<Linda*>(o_) }; | ||
| 69 | LUA_ASSERT(L_, linda); | ||
| 70 | Keeper* const myK{ linda->whichKeeper() }; | ||
| 71 | // if collected after the universe, keepers are already destroyed, and there is nothing to clear | ||
| 72 | if (myK) | ||
| 73 | { | ||
| 74 | // if collected from my own keeper, we can't acquire/release it | ||
| 75 | // because we are already inside a protected area, and trying to do so would deadlock! | ||
| 76 | bool const need_acquire_release{ myK->L != L_ }; | ||
| 77 | // Clean associated structures in the keeper state. | ||
| 78 | Keeper* const K{ need_acquire_release ? linda->acquireKeeper() : myK }; | ||
| 79 | // hopefully this won't ever raise an error as we would jump to the closest pcall site while forgetting to release the keeper mutex... | ||
| 80 | [[maybe_unused]] KeeperCallResult const result{ keeper_call(linda->U, K->L, KEEPER_API(clear), L_, linda, 0) }; | ||
| 81 | LUA_ASSERT(L_, result.has_value() && result.value() == 0); | ||
| 82 | if (need_acquire_release) | ||
| 83 | { | ||
| 84 | linda->releaseKeeper(K); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | delete linda; // operator delete overload ensures things go as expected | ||
| 89 | } | ||
| 90 | |||
| 91 | // ################################################################################################# | ||
| 92 | |||
| 93 | char const* LindaFactory::moduleName() const | ||
| 94 | { | ||
| 95 | // linda is a special case because we know lanes must be loaded from the main lua state | ||
| 96 | // to be able to ever get here, so we know it will remain loaded as long a the main state is around | ||
| 97 | // in other words, forever. | ||
| 98 | return nullptr; | ||
| 99 | } | ||
| 100 | |||
| 101 | // ################################################################################################# | ||
| 102 | |||
| 103 | DeepPrelude* LindaFactory::newDeepObjectInternal(lua_State* L_) const | ||
| 104 | { | ||
| 105 | size_t name_len{ 0 }; | ||
| 106 | char const* linda_name{ nullptr }; | ||
| 107 | LindaGroup linda_group{ 0 }; | ||
| 108 | // should have a string and/or a number of the stack as parameters (name and group) | ||
| 109 | switch (lua_gettop(L_)) | ||
| 110 | { | ||
| 111 | default: // 0 | ||
| 112 | break; | ||
| 113 | |||
| 114 | case 1: // 1 parameter, either a name or a group | ||
| 115 | if (lua_type(L_, -1) == LUA_TSTRING) | ||
| 116 | { | ||
| 117 | linda_name = lua_tolstring(L_, -1, &name_len); | ||
| 118 | } | ||
| 119 | else | ||
| 120 | { | ||
| 121 | linda_group = LindaGroup{ static_cast<int>(lua_tointeger(L_, -1)) }; | ||
| 122 | } | ||
| 123 | break; | ||
| 124 | |||
| 125 | case 2: // 2 parameters, a name and group, in that order | ||
| 126 | linda_name = lua_tolstring(L_, -2, &name_len); | ||
| 127 | linda_group = LindaGroup{ static_cast<int>(lua_tointeger(L_, -1)) }; | ||
| 128 | break; | ||
| 129 | } | ||
| 130 | |||
| 131 | // The deep data is allocated separately of Lua stack; we might no longer be around when last reference to it is being released. | ||
| 132 | // One can use any memory allocation scheme. Just don't use L's allocF because we don't know which state will get the honor of GCing the linda | ||
| 133 | Universe* const U{ universe_get(L_) }; | ||
| 134 | Linda* const linda{ new (U) Linda{ U, linda_group, linda_name, name_len } }; | ||
| 135 | return linda; | ||
| 136 | } | ||
diff --git a/src/lindafactory.h b/src/lindafactory.h new file mode 100644 index 0000000..d31af1f --- /dev/null +++ b/src/lindafactory.h | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include "deep.h" | ||
| 4 | |||
| 5 | // ################################################################################################# | ||
| 6 | |||
| 7 | class LindaFactory | ||
| 8 | : public DeepFactory | ||
| 9 | { | ||
| 10 | public: | ||
| 11 | |||
| 12 | // I'm not totally happy with having a 'global' variable. Maybe it should be dynamically created and stored somewhere in the universe? | ||
| 13 | static LindaFactory Instance; | ||
| 14 | |||
| 15 | LindaFactory(luaL_Reg const lindaMT_[]) | ||
| 16 | : mLindaMT{ lindaMT_ } | ||
| 17 | { | ||
| 18 | } | ||
| 19 | |||
| 20 | private: | ||
| 21 | |||
| 22 | luaL_Reg const* const mLindaMT{ nullptr }; | ||
| 23 | |||
| 24 | void createMetatable(lua_State* L_) const override; | ||
| 25 | void deleteDeepObjectInternal(lua_State* L_, DeepPrelude* o_) const override; | ||
| 26 | char const* moduleName() const override; | ||
| 27 | DeepPrelude* newDeepObjectInternal(lua_State* L_) const override; | ||
| 28 | }; | ||
