diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-18 14:06:07 +0200 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-18 14:06:07 +0200 |
| commit | 271ce5cff2b5e9c1e4d4f236c731ceb263716681 (patch) | |
| tree | f26ae0570b0442938fbe08ca4542e8ca8f92504a /src | |
| parent | 6b6e7827362b3d56cd588a76ef9d3bd6baec52f1 (diff) | |
| download | lanes-271ce5cff2b5e9c1e4d4f236c731ceb263716681.tar.gz lanes-271ce5cff2b5e9c1e4d4f236c731ceb263716681.tar.bz2 lanes-271ce5cff2b5e9c1e4d4f236c731ceb263716681.zip | |
Give a chance to config.allocator to provide a specific allocator for internal stuff
Diffstat (limited to 'src')
| -rw-r--r-- | src/allocator.h | 2 | ||||
| -rw-r--r-- | src/state.cpp | 19 | ||||
| -rw-r--r-- | src/universe.cpp | 35 | ||||
| -rw-r--r-- | src/universe.h | 1 |
4 files changed, 33 insertions, 24 deletions
diff --git a/src/allocator.h b/src/allocator.h index e09ab38..0505251 100644 --- a/src/allocator.h +++ b/src/allocator.h | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | #pragma once | 1 | #pragma once |
| 2 | 2 | ||
| 3 | #include "compat.h" | ||
| 4 | |||
| 3 | // ################################################################################################# | 5 | // ################################################################################################# |
| 4 | 6 | ||
| 5 | namespace lanes { | 7 | namespace lanes { |
diff --git a/src/state.cpp b/src/state.cpp index 6d3910b..1975148 100644 --- a/src/state.cpp +++ b/src/state.cpp | |||
| @@ -204,23 +204,8 @@ namespace state { | |||
| 204 | // for some reason, LuaJIT 64 bits does not support creating a state with lua_newstate... | 204 | // for some reason, LuaJIT 64 bits does not support creating a state with lua_newstate... |
| 205 | return luaL_newstate(); | 205 | return luaL_newstate(); |
| 206 | } else { | 206 | } else { |
| 207 | if (U->provideAllocator != nullptr) { // we have a function we can call to obtain an allocator | 207 | lanes::AllocatorDefinition const _def{ U->resolveAllocator(from, hint) }; |
| 208 | STACK_CHECK_START_REL(from, 0); | 208 | return lua_newstate(_def.allocF, _def.allocUD); |
| 209 | lua_pushcclosure(from, U->provideAllocator, 0); // L: provideAllocator() | ||
| 210 | luaG_pushstring(from, hint); // L: provideAllocator() "<hint>" | ||
| 211 | lua_call(from, 1, 1); // L: result | ||
| 212 | lanes::AllocatorDefinition* const _def{ luaG_tofulluserdata<lanes::AllocatorDefinition>(from, -1) }; | ||
| 213 | if (!_def || _def->version != lanes::AllocatorDefinition::kAllocatorVersion) { | ||
| 214 | raise_luaL_error(from, "Bad config.allocator function, must provide a valid AllocatorDefinition"); | ||
| 215 | } | ||
| 216 | lua_State* const _L{ lua_newstate(_def->allocF, _def->allocUD) }; | ||
| 217 | lua_pop(from, 1); // L: | ||
| 218 | STACK_CHECK(from, 0); | ||
| 219 | return _L; | ||
| 220 | } else { | ||
| 221 | // reuse the allocator provided when the master state was created | ||
| 222 | return lua_newstate(U->protectedAllocator.allocF, U->protectedAllocator.allocUD); | ||
| 223 | } | ||
| 224 | } | 209 | } |
| 225 | } | 210 | } |
| 226 | ) | 211 | ) |
diff --git a/src/universe.cpp b/src/universe.cpp index 770fccf..097c642 100644 --- a/src/universe.cpp +++ b/src/universe.cpp | |||
| @@ -176,7 +176,7 @@ Universe::Universe() | |||
| 176 | // Do I need to disable this when compiling for LuaJIT to prevent issues? | 176 | // Do I need to disable this when compiling for LuaJIT to prevent issues? |
| 177 | void Universe::initializeAllocatorFunction(lua_State* const L_) | 177 | void Universe::initializeAllocatorFunction(lua_State* const L_) |
| 178 | { | 178 | { |
| 179 | // start by just grabbing whatever allocator was provided to lua_newstate | 179 | // start by just grabbing whatever allocator was provided to the master state |
| 180 | protectedAllocator.initFrom(L_); | 180 | protectedAllocator.initFrom(L_); |
| 181 | STACK_CHECK_START_REL(L_, 1); // L_: settings | 181 | STACK_CHECK_START_REL(L_, 1); // L_: settings |
| 182 | switch (luaG_getfield(L_, -1, "allocator")) { // L_: settings allocator|nil|"protected" | 182 | switch (luaG_getfield(L_, -1, "allocator")) { // L_: settings allocator|nil|"protected" |
| @@ -212,19 +212,17 @@ void Universe::initializeAllocatorFunction(lua_State* const L_) | |||
| 212 | default: // should be filtered out in lanes.lua | 212 | default: // should be filtered out in lanes.lua |
| 213 | raise_luaL_error(L_, "Bad config.allocator type %s", luaG_typename(L_, -1).data()); | 213 | raise_luaL_error(L_, "Bad config.allocator type %s", luaG_typename(L_, -1).data()); |
| 214 | } | 214 | } |
| 215 | lua_pop(L_, 1); // L_: settings | 215 | lua_pop(L_, 1); // L_: settings |
| 216 | STACK_CHECK(L_, 1); | 216 | STACK_CHECK(L_, 1); |
| 217 | 217 | ||
| 218 | std::ignore = luaG_getfield(L_, -1, "internal_allocator"); // L_: settings "libc"|"allocator" | 218 | std::ignore = luaG_getfield(L_, -1, "internal_allocator"); // L_: settings "libc"|"allocator" |
| 219 | LUA_ASSERT(L_, lua_isstring(L_, -1)); // should be the case due to lanes.lua parameter validation | ||
| 219 | std::string_view const _allocator{ luaG_tostring(L_, -1) }; | 220 | std::string_view const _allocator{ luaG_tostring(L_, -1) }; |
| 220 | if (_allocator == "libc") { | 221 | if (_allocator == "libc") { |
| 221 | internalAllocator = lanes::AllocatorDefinition{ lanes::AllocatorDefinition::kAllocatorVersion, libc_lua_Alloc, nullptr }; | 222 | internalAllocator = lanes::AllocatorDefinition{ lanes::AllocatorDefinition::kAllocatorVersion, libc_lua_Alloc, nullptr }; |
| 222 | } else if (provideAllocator == luaG_provide_protected_allocator) { | ||
| 223 | // user wants mutex protection on the state's allocator. Use protection for our own allocations too, just in case. | ||
| 224 | internalAllocator = protectedAllocator.makeDefinition(); | ||
| 225 | } else { | 223 | } else { |
| 226 | // no protection required, just use whatever we have as-is. | 224 | // use whatever the provider provides |
| 227 | internalAllocator = protectedAllocator; | 225 | internalAllocator = resolveAllocator(L_, "internal"); |
| 228 | } | 226 | } |
| 229 | lua_pop(L_, 1); // L_: settings | 227 | lua_pop(L_, 1); // L_: settings |
| 230 | STACK_CHECK(L_, 1); | 228 | STACK_CHECK(L_, 1); |
| @@ -254,6 +252,29 @@ int Universe::InitializeFinalizer(lua_State* const L_) | |||
| 254 | 252 | ||
| 255 | // ################################################################################################# | 253 | // ################################################################################################# |
| 256 | 254 | ||
| 255 | lanes::AllocatorDefinition Universe::resolveAllocator(lua_State* const L_, std::string_view const& hint_) const | ||
| 256 | { | ||
| 257 | lanes::AllocatorDefinition _ret{ protectedAllocator }; | ||
| 258 | if (provideAllocator == nullptr) { | ||
| 259 | return _ret; | ||
| 260 | } | ||
| 261 | |||
| 262 | STACK_CHECK_START_REL(L_, 0); // here, we have a function we can call to obtain an allocator | ||
| 263 | lua_pushcclosure(L_, provideAllocator, 0); // L_: provideAllocator() | ||
| 264 | luaG_pushstring(L_, hint_); // L_: provideAllocator() "<hint>" | ||
| 265 | lua_call(L_, 1, 1); // L_: result | ||
| 266 | lanes::AllocatorDefinition* const _def{ luaG_tofulluserdata<lanes::AllocatorDefinition>(L_, -1) }; | ||
| 267 | if (!_def || _def->version != lanes::AllocatorDefinition::kAllocatorVersion) { | ||
| 268 | raise_luaL_error(L_, "Bad config.allocator function, must provide a valid AllocatorDefinition"); | ||
| 269 | } | ||
| 270 | _ret = *_def; | ||
| 271 | lua_pop(L_, 1); // L_: | ||
| 272 | STACK_CHECK(L_, 0); | ||
| 273 | return _ret; | ||
| 274 | } | ||
| 275 | |||
| 276 | // ################################################################################################# | ||
| 277 | |||
| 257 | void Universe::terminateFreeRunningLanes(lua_State* const L_, lua_Duration const shutdownTimeout_, CancelOp const op_) | 278 | void Universe::terminateFreeRunningLanes(lua_State* const L_, lua_Duration const shutdownTimeout_, CancelOp const op_) |
| 258 | { | 279 | { |
| 259 | if (selfdestructFirst != SELFDESTRUCT_END) { | 280 | if (selfdestructFirst != SELFDESTRUCT_END) { |
diff --git a/src/universe.h b/src/universe.h index d890e5c..6ccdaca 100644 --- a/src/universe.h +++ b/src/universe.h | |||
| @@ -135,6 +135,7 @@ class Universe | |||
| 135 | [[nodiscard]] static inline Universe* Get(lua_State* L_); | 135 | [[nodiscard]] static inline Universe* Get(lua_State* L_); |
| 136 | void initializeAllocatorFunction(lua_State* L_); | 136 | void initializeAllocatorFunction(lua_State* L_); |
| 137 | static int InitializeFinalizer(lua_State* L_); | 137 | static int InitializeFinalizer(lua_State* L_); |
| 138 | lanes::AllocatorDefinition resolveAllocator(lua_State* const L_, std::string_view const& hint_) const; | ||
| 138 | static inline void Store(lua_State* L_, Universe* U_); | 139 | static inline void Store(lua_State* L_, Universe* U_); |
| 139 | void terminateFreeRunningLanes(lua_State* L_, lua_Duration shutdownTimeout_, CancelOp op_); | 140 | void terminateFreeRunningLanes(lua_State* L_, lua_Duration shutdownTimeout_, CancelOp op_); |
| 140 | }; | 141 | }; |
