From df60f71fe943686deed8ca0f85c6d597570ab030 Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Mon, 28 Oct 2024 18:03:24 +0100 Subject: Renamed universe.h → universe.hpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/debugspew.h | 2 +- src/intercopycontext.cpp | 2 +- src/lane.h | 2 +- src/linda.h | 2 +- src/state.cpp | 2 +- src/tools.cpp | 2 +- src/universe.cpp | 2 +- src/universe.h | 168 ----------------------------------------------- src/universe.hpp | 168 +++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 175 insertions(+), 175 deletions(-) delete mode 100644 src/universe.h create mode 100644 src/universe.hpp (limited to 'src') diff --git a/src/debugspew.h b/src/debugspew.h index 051742e..1eb5556 100644 --- a/src/debugspew.h +++ b/src/debugspew.h @@ -1,7 +1,7 @@ #pragma once #include "lanesconf.h" -#include "universe.h" +#include "universe.hpp" // ################################################################################################# diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp index 3f2e840..bd09a3c 100644 --- a/src/intercopycontext.cpp +++ b/src/intercopycontext.cpp @@ -32,7 +32,7 @@ THE SOFTWARE. #include "lane.h" #include "linda.h" #include "nameof.hpp" -#include "universe.h" +#include "universe.hpp" // ################################################################################################# diff --git a/src/lane.h b/src/lane.h index f30a756..7821112 100644 --- a/src/lane.h +++ b/src/lane.h @@ -2,7 +2,7 @@ #include "cancel.hpp" #include "uniquekey.hpp" -#include "universe.h" +#include "universe.hpp" // ################################################################################################# diff --git a/src/linda.h b/src/linda.h index 88ee639..5b5f683 100644 --- a/src/linda.h +++ b/src/linda.h @@ -2,7 +2,7 @@ #include "cancel.hpp" #include "deep.hpp" -#include "universe.h" +#include "universe.hpp" struct Keeper; diff --git a/src/state.cpp b/src/state.cpp index dabdd6f..deea1fa 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -38,7 +38,7 @@ THE SOFTWARE. #include "lane.h" #include "lanes.hpp" #include "tools.hpp" -#include "universe.h" +#include "universe.hpp" // ################################################################################################# // ################################################################################################# diff --git a/src/tools.cpp b/src/tools.cpp index 35a46e9..923d323 100644 --- a/src/tools.cpp +++ b/src/tools.cpp @@ -36,7 +36,7 @@ THE SOFTWARE. #include "tools.hpp" #include "debugspew.h" -#include "universe.h" +#include "universe.hpp" DEBUGSPEW_CODE(std::string_view const DebugSpewIndentScope::debugspew_indent{ "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+" }); diff --git a/src/universe.cpp b/src/universe.cpp index 3f2878f..5cce9a5 100644 --- a/src/universe.cpp +++ b/src/universe.cpp @@ -29,7 +29,7 @@ THE SOFTWARE. */ #include "_pch.hpp" -#include "universe.h" +#include "universe.hpp" #include "deep.hpp" #include "intercopycontext.h" diff --git a/src/universe.h b/src/universe.h deleted file mode 100644 index 18e125f..0000000 --- a/src/universe.h +++ /dev/null @@ -1,168 +0,0 @@ -#pragma once - -#include "allocator.hpp" -#include "keeper.hpp" -#include "lanesconf.h" -#include "tracker.hpp" -#include "uniquekey.hpp" - -// ################################################################################################# - -// forwards -enum class CancelOp; -struct DeepPrelude; -class Lane; - -// ################################################################################################# - -// mutex-protected allocator for use with Lua states that share a non-threadsafe allocator -class ProtectedAllocator -: public lanes::AllocatorDefinition -{ - private: - std::mutex mutex; - - [[nodiscard]] static void* protected_lua_Alloc(void* ud_, void* ptr_, size_t osize_, size_t nsize_) - { - ProtectedAllocator* const allocator{ static_cast(ud_) }; - std::lock_guard guard{ allocator->mutex }; - return allocator->allocF(allocator->allocUD, ptr_, osize_, nsize_); - } - - public: - // we are not like our base class: we can't be created inside a full userdata (or we would have to install a metatable and __gc handler to destroy ourselves properly) - [[nodiscard]] static void* operator new(size_t size_, lua_State* L_) noexcept = delete; - static void operator delete(void* p_, lua_State* L_) = delete; - - AllocatorDefinition makeDefinition() - { - return AllocatorDefinition{ version, protected_lua_Alloc, this }; - } - - void installIn(lua_State* L_) - { - lua_setallocf(L_, protected_lua_Alloc, this); - } - - void removeFrom(lua_State* L_) - { - // remove the protected allocator, if any - if (allocF != nullptr) { - // install the non-protected allocator - lua_setallocf(L_, allocF, allocUD); - } - } -}; - -// ################################################################################################# - -// xxh64 of string "kUniverseLightRegKey" generated at https://www.pelock.com/products/hash-calculator -static constexpr RegistryUniqueKey kUniverseLightRegKey{ 0x48BBE9CEAB0BA04Full }; - -// ################################################################################################# - -// everything regarding the Lanes universe is stored in that global structure -// held as a full userdata in the master Lua state that required it for the first time -class Universe -{ - public: - static constexpr char const* kFinally{ "finally" }; // update lanes.lua if the name changes! - -#ifdef PLATFORM_LINUX - // Linux needs to check, whether it's been run as root - bool const sudo{ geteuid() == 0 }; -#else - bool const sudo{ false }; -#endif // PLATFORM_LINUX - - // for verbose errors - bool verboseErrors{ false }; - - bool stripFunctions{ true }; - - // before a state is created, this function will be called to obtain the allocator - lua_CFunction provideAllocator{ nullptr }; - - // after a state is created, this function will be called right after the bases libraries are loaded - std::variant onStateCreateFunc; - - // if allocator="protected" is found in the configuration settings, a wrapper allocator will protect all allocator calls with a mutex - // contains a mutex and the original allocator definition - ProtectedAllocator protectedAllocator; - - lanes::AllocatorDefinition internalAllocator; - - Keepers keepers; - - // Initialized by 'init_once_LOCKED()': the deep userdata Linda object - // used for timers (each lane will get a proxy to this) - DeepPrelude* timerLinda{ nullptr }; - - LaneTracker tracker; - - // Protects modifying the selfdestruct chain - std::mutex selfdestructMutex; - - // require() serialization - std::recursive_mutex requireMutex; - - // metatable unique identifiers - std::atomic nextMetatableId{ 1 }; - -#if USE_DEBUG_SPEW() - std::atomic debugspewIndentDepth{ 0 }; -#endif // USE_DEBUG_SPEW() - - Lane* volatile selfdestructFirst{ nullptr }; - // After a lane has removed itself from the chain, it still performs some processing. - // The terminal desinit sequence should wait for all such processing to terminate before force-killing threads - std::atomic selfdestructingCount{ 0 }; - - public: - [[nodiscard]] static void* operator new([[maybe_unused]] size_t size_, lua_State* L_) noexcept { return luaG_newuserdatauv(L_, UserValueCount{ 0 }); }; - // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception - static void operator delete([[maybe_unused]] void* p_, [[maybe_unused]] lua_State* L_) {} // nothing to do, as nothing is allocated independently - - Universe(); - ~Universe() = default; - // non-copyable, non-movable - Universe(Universe const&) = delete; - Universe(Universe&&) = delete; - Universe& operator=(Universe const&) = delete; - Universe& operator=(Universe&&) = delete; - - void callOnStateCreate(lua_State* const L_, lua_State* const from_, LookupMode const mode_); - [[nodiscard]] static Universe* Create(lua_State* L_); - [[nodiscard]] static inline Universe* Get(lua_State* L_); - void initializeAllocatorFunction(lua_State* L_); - static int InitializeFinalizer(lua_State* L_); - void initializeOnStateCreate(lua_State* const L_); - lanes::AllocatorDefinition resolveAllocator(lua_State* const L_, std::string_view const& hint_) const; - static inline void Store(lua_State* L_, Universe* U_); - [[nodiscard]] bool terminateFreeRunningLanes(lua_Duration shutdownTimeout_, CancelOp op_); -}; - -// ################################################################################################# - -inline Universe* Universe::Get(lua_State* L_) -{ - STACK_CHECK_START_REL(L_, 0); - Universe* const _universe{ kUniverseLightRegKey.readLightUserDataValue(L_) }; - STACK_CHECK(L_, 0); - return _universe; -} - -// ################################################################################################# - -inline void Universe::Store(lua_State* L_, Universe* U_) -{ - // TODO: check if we actually ever call Store with a null universe - LUA_ASSERT(L_, !U_ || Universe::Get(L_) == nullptr); - STACK_CHECK_START_REL(L_, 0); - kUniverseLightRegKey.setValue(L_, [U = U_](lua_State* L_) { U ? lua_pushlightuserdata(L_, U) : lua_pushnil(L_); }); - STACK_CHECK(L_, 0); -} - -// ################################################################################################# - -LUAG_FUNC(universe_gc); diff --git a/src/universe.hpp b/src/universe.hpp new file mode 100644 index 0000000..18e125f --- /dev/null +++ b/src/universe.hpp @@ -0,0 +1,168 @@ +#pragma once + +#include "allocator.hpp" +#include "keeper.hpp" +#include "lanesconf.h" +#include "tracker.hpp" +#include "uniquekey.hpp" + +// ################################################################################################# + +// forwards +enum class CancelOp; +struct DeepPrelude; +class Lane; + +// ################################################################################################# + +// mutex-protected allocator for use with Lua states that share a non-threadsafe allocator +class ProtectedAllocator +: public lanes::AllocatorDefinition +{ + private: + std::mutex mutex; + + [[nodiscard]] static void* protected_lua_Alloc(void* ud_, void* ptr_, size_t osize_, size_t nsize_) + { + ProtectedAllocator* const allocator{ static_cast(ud_) }; + std::lock_guard guard{ allocator->mutex }; + return allocator->allocF(allocator->allocUD, ptr_, osize_, nsize_); + } + + public: + // we are not like our base class: we can't be created inside a full userdata (or we would have to install a metatable and __gc handler to destroy ourselves properly) + [[nodiscard]] static void* operator new(size_t size_, lua_State* L_) noexcept = delete; + static void operator delete(void* p_, lua_State* L_) = delete; + + AllocatorDefinition makeDefinition() + { + return AllocatorDefinition{ version, protected_lua_Alloc, this }; + } + + void installIn(lua_State* L_) + { + lua_setallocf(L_, protected_lua_Alloc, this); + } + + void removeFrom(lua_State* L_) + { + // remove the protected allocator, if any + if (allocF != nullptr) { + // install the non-protected allocator + lua_setallocf(L_, allocF, allocUD); + } + } +}; + +// ################################################################################################# + +// xxh64 of string "kUniverseLightRegKey" generated at https://www.pelock.com/products/hash-calculator +static constexpr RegistryUniqueKey kUniverseLightRegKey{ 0x48BBE9CEAB0BA04Full }; + +// ################################################################################################# + +// everything regarding the Lanes universe is stored in that global structure +// held as a full userdata in the master Lua state that required it for the first time +class Universe +{ + public: + static constexpr char const* kFinally{ "finally" }; // update lanes.lua if the name changes! + +#ifdef PLATFORM_LINUX + // Linux needs to check, whether it's been run as root + bool const sudo{ geteuid() == 0 }; +#else + bool const sudo{ false }; +#endif // PLATFORM_LINUX + + // for verbose errors + bool verboseErrors{ false }; + + bool stripFunctions{ true }; + + // before a state is created, this function will be called to obtain the allocator + lua_CFunction provideAllocator{ nullptr }; + + // after a state is created, this function will be called right after the bases libraries are loaded + std::variant onStateCreateFunc; + + // if allocator="protected" is found in the configuration settings, a wrapper allocator will protect all allocator calls with a mutex + // contains a mutex and the original allocator definition + ProtectedAllocator protectedAllocator; + + lanes::AllocatorDefinition internalAllocator; + + Keepers keepers; + + // Initialized by 'init_once_LOCKED()': the deep userdata Linda object + // used for timers (each lane will get a proxy to this) + DeepPrelude* timerLinda{ nullptr }; + + LaneTracker tracker; + + // Protects modifying the selfdestruct chain + std::mutex selfdestructMutex; + + // require() serialization + std::recursive_mutex requireMutex; + + // metatable unique identifiers + std::atomic nextMetatableId{ 1 }; + +#if USE_DEBUG_SPEW() + std::atomic debugspewIndentDepth{ 0 }; +#endif // USE_DEBUG_SPEW() + + Lane* volatile selfdestructFirst{ nullptr }; + // After a lane has removed itself from the chain, it still performs some processing. + // The terminal desinit sequence should wait for all such processing to terminate before force-killing threads + std::atomic selfdestructingCount{ 0 }; + + public: + [[nodiscard]] static void* operator new([[maybe_unused]] size_t size_, lua_State* L_) noexcept { return luaG_newuserdatauv(L_, UserValueCount{ 0 }); }; + // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception + static void operator delete([[maybe_unused]] void* p_, [[maybe_unused]] lua_State* L_) {} // nothing to do, as nothing is allocated independently + + Universe(); + ~Universe() = default; + // non-copyable, non-movable + Universe(Universe const&) = delete; + Universe(Universe&&) = delete; + Universe& operator=(Universe const&) = delete; + Universe& operator=(Universe&&) = delete; + + void callOnStateCreate(lua_State* const L_, lua_State* const from_, LookupMode const mode_); + [[nodiscard]] static Universe* Create(lua_State* L_); + [[nodiscard]] static inline Universe* Get(lua_State* L_); + void initializeAllocatorFunction(lua_State* L_); + static int InitializeFinalizer(lua_State* L_); + void initializeOnStateCreate(lua_State* const L_); + lanes::AllocatorDefinition resolveAllocator(lua_State* const L_, std::string_view const& hint_) const; + static inline void Store(lua_State* L_, Universe* U_); + [[nodiscard]] bool terminateFreeRunningLanes(lua_Duration shutdownTimeout_, CancelOp op_); +}; + +// ################################################################################################# + +inline Universe* Universe::Get(lua_State* L_) +{ + STACK_CHECK_START_REL(L_, 0); + Universe* const _universe{ kUniverseLightRegKey.readLightUserDataValue(L_) }; + STACK_CHECK(L_, 0); + return _universe; +} + +// ################################################################################################# + +inline void Universe::Store(lua_State* L_, Universe* U_) +{ + // TODO: check if we actually ever call Store with a null universe + LUA_ASSERT(L_, !U_ || Universe::Get(L_) == nullptr); + STACK_CHECK_START_REL(L_, 0); + kUniverseLightRegKey.setValue(L_, [U = U_](lua_State* L_) { U ? lua_pushlightuserdata(L_, U) : lua_pushnil(L_); }); + STACK_CHECK(L_, 0); +} + +// ################################################################################################# + +LUAG_FUNC(universe_gc); -- cgit v1.2.3-55-g6feb