aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-06-18 09:03:43 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2024-06-18 09:03:43 +0200
commite3818609b54c81a83aa73beb322ea9c282b7add8 (patch)
treeb165d7925206ceb10a851fc8c1eed8b8566e7727 /src
parent54b47307ce4b2e21bc12c1602c77fecf55380452 (diff)
downloadlanes-e3818609b54c81a83aa73beb322ea9c282b7add8.tar.gz
lanes-e3818609b54c81a83aa73beb322ea9c282b7add8.tar.bz2
lanes-e3818609b54c81a83aa73beb322ea9c282b7add8.zip
When it is a function, config.allocator is called with a string hint
Diffstat (limited to 'src')
-rw-r--r--src/allocator.h47
-rw-r--r--src/keeper.cpp2
-rw-r--r--src/state.cpp15
-rw-r--r--src/state.h2
-rw-r--r--src/universe.h47
5 files changed, 59 insertions, 54 deletions
diff --git a/src/allocator.h b/src/allocator.h
new file mode 100644
index 0000000..9a9c245
--- /dev/null
+++ b/src/allocator.h
@@ -0,0 +1,47 @@
1#pragma once
2
3// #################################################################################################
4
5// everything we need to provide to lua_newstate()
6class AllocatorDefinition
7{
8 public:
9 // xxh64 of string "kAllocatorVersion_1" generated at https://www.pelock.com/products/hash-calculator
10 static constexpr uintptr_t kAllocatorVersion{ static_cast<uintptr_t>(0xCF9D321B0DFB5715ull) };
11 uintptr_t version{ kAllocatorVersion };
12 lua_Alloc allocF{ nullptr };
13 void* allocUD{ nullptr };
14
15 [[nodiscard]] static void* operator new(size_t size_) noexcept = delete; // can't create one outside of a Lua state
16 [[nodiscard]] static void* operator new(size_t size_, lua_State* L_) noexcept { return lua_newuserdatauv(L_, size_, 0); }
17 // always embedded somewhere else or "in-place constructed" as a full userdata
18 // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception
19 static void operator delete([[maybe_unused]] void* p_, [[maybe_unused]] lua_State* L_) {}
20
21 AllocatorDefinition(uintptr_t const version_, lua_Alloc const allocF_, void* const allocUD_) noexcept
22 : version{ version_ }
23 , allocF{ allocF_ }
24 , allocUD{ allocUD_ }
25 {
26 }
27 AllocatorDefinition() = default;
28 AllocatorDefinition(AllocatorDefinition const& rhs_) = default;
29 AllocatorDefinition(AllocatorDefinition&& rhs_) = default;
30 AllocatorDefinition& operator=(AllocatorDefinition const& rhs_) = default;
31 AllocatorDefinition& operator=(AllocatorDefinition&& rhs_) = default;
32
33 void initFrom(lua_State* L_)
34 {
35 allocF = lua_getallocf(L_, &allocUD);
36 }
37
38 void* alloc(size_t nsize_)
39 {
40 return allocF(allocUD, nullptr, 0, nsize_);
41 }
42
43 void free(void* ptr_, size_t osize_)
44 {
45 std::ignore = allocF(allocUD, ptr_, osize_, 0);
46 }
47};
diff --git a/src/keeper.cpp b/src/keeper.cpp
index e058114..11f1797 100644
--- a/src/keeper.cpp
+++ b/src/keeper.cpp
@@ -830,7 +830,7 @@ void Keepers::initialize(Universe& U_, lua_State* L_, int const nbKeepers_, int
830 auto _initOneKeeper = [U = &U_, L = L_, gc_threshold = gc_threshold](Keeper& keeper_, int const i_) { 830 auto _initOneKeeper = [U = &U_, L = L_, gc_threshold = gc_threshold](Keeper& keeper_, int const i_) {
831 STACK_CHECK_START_REL(L, 0); 831 STACK_CHECK_START_REL(L, 0);
832 // note that we will leak K if we raise an error later 832 // note that we will leak K if we raise an error later
833 KeeperState const _K{ state::CreateState(U, L) }; // L_: settings _K: 833 KeeperState const _K{ state::CreateState(U, L, "keeper") }; // L_: settings _K:
834 if (_K == nullptr) { 834 if (_K == nullptr) {
835 raise_luaL_error(L, "out of memory while creating keeper states"); 835 raise_luaL_error(L, "out of memory while creating keeper states");
836 } 836 }
diff --git a/src/state.cpp b/src/state.cpp
index ee0b199..bae2ba5 100644
--- a/src/state.cpp
+++ b/src/state.cpp
@@ -195,24 +195,27 @@ namespace state {
195 195
196 // ############################################################################################# 196 // #############################################################################################
197 197
198 lua_State* CreateState([[maybe_unused]] Universe* const U_, lua_State* const from_) 198 lua_State* CreateState([[maybe_unused]] Universe* const U_, lua_State* const from_, std::string_view const& hint_)
199 { 199 {
200 lua_State* const _L { 200 lua_State* const _L {
201 std::invoke( 201 std::invoke(
202 [U = U_, from = from_]() { 202 [U = U_, from = from_, &hint = hint_]() {
203 if constexpr (LUAJIT_FLAVOR() == 64) { 203 if constexpr (LUAJIT_FLAVOR() == 64) {
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 if (U->provideAllocator != nullptr) { // we have a function we can call to obtain an allocator
208 lua_pushcclosure(from, U->provideAllocator, 0); 208 STACK_CHECK_START_REL(from, 0);
209 lua_call(from, 0, 1); 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
210 AllocatorDefinition* const _def{ luaG_tofulluserdata<AllocatorDefinition>(from, -1) }; 212 AllocatorDefinition* const _def{ luaG_tofulluserdata<AllocatorDefinition>(from, -1) };
211 if (!_def || _def->version != AllocatorDefinition::kAllocatorVersion) { 213 if (!_def || _def->version != AllocatorDefinition::kAllocatorVersion) {
212 raise_luaL_error(from, "Bad config.allocator function, must provide a valid AllocatorDefinition"); 214 raise_luaL_error(from, "Bad config.allocator function, must provide a valid AllocatorDefinition");
213 } 215 }
214 lua_State* const _L{ lua_newstate(_def->allocF, _def->allocUD) }; 216 lua_State* const _L{ lua_newstate(_def->allocF, _def->allocUD) };
215 lua_pop(from, 1); 217 lua_pop(from, 1); // L:
218 STACK_CHECK(from, 0);
216 return _L; 219 return _L;
217 } else { 220 } else {
218 // reuse the allocator provided when the master state was created 221 // reuse the allocator provided when the master state was created
@@ -271,7 +274,7 @@ namespace state {
271 */ 274 */
272 lua_State* NewLaneState(Universe* const U_, SourceState const from_, std::optional<std::string_view> const& libs_) 275 lua_State* NewLaneState(Universe* const U_, SourceState const from_, std::optional<std::string_view> const& libs_)
273 { 276 {
274 DestState const _L{ CreateState(U_, from_) }; 277 DestState const _L{ CreateState(U_, from_, "lane") };
275 278
276 STACK_GROW(_L, 2); 279 STACK_GROW(_L, 2);
277 STACK_CHECK_START_ABS(_L, 0); 280 STACK_CHECK_START_ABS(_L, 0);
diff --git a/src/state.h b/src/state.h
index 9b42786..98bb47b 100644
--- a/src/state.h
+++ b/src/state.h
@@ -10,7 +10,7 @@ class Universe;
10namespace state { 10namespace state {
11 11
12 void CallOnStateCreate(Universe* U_, lua_State* L_, lua_State* from_, LookupMode mode_); 12 void CallOnStateCreate(Universe* U_, lua_State* L_, lua_State* from_, LookupMode mode_);
13 [[nodiscard]] lua_State* CreateState(Universe* U_, lua_State* from_); 13 [[nodiscard]] lua_State* CreateState(Universe* U_, lua_State* from_, std::string_view const& hint_);
14 void InitializeOnStateCreate(Universe* U_, lua_State* L_); 14 void InitializeOnStateCreate(Universe* U_, lua_State* L_);
15 [[nodiscard]] lua_State* NewLaneState(Universe* U_, SourceState from_, std::optional<std::string_view> const& libs_); 15 [[nodiscard]] lua_State* NewLaneState(Universe* U_, SourceState from_, std::optional<std::string_view> const& libs_);
16 16
diff --git a/src/universe.h b/src/universe.h
index 3742ddd..2edd825 100644
--- a/src/universe.h
+++ b/src/universe.h
@@ -1,5 +1,6 @@
1#pragma once 1#pragma once
2 2
3#include "allocator.h"
3#include "keeper.h" 4#include "keeper.h"
4#include "lanesconf.h" 5#include "lanesconf.h"
5#include "tracker.h" 6#include "tracker.h"
@@ -14,52 +15,6 @@ class Lane;
14 15
15// ################################################################################################# 16// #################################################################################################
16 17
17// everything we need to provide to lua_newstate()
18class AllocatorDefinition
19{
20 public:
21 // xxh64 of string "kAllocatorVersion_1" generated at https://www.pelock.com/products/hash-calculator
22 static constexpr uintptr_t kAllocatorVersion{ static_cast<uintptr_t>(0xCF9D321B0DFB5715ull) };
23 uintptr_t version{ kAllocatorVersion };
24 lua_Alloc allocF{ nullptr };
25 void* allocUD{ nullptr };
26
27 [[nodiscard]] static void* operator new(size_t size_) noexcept = delete; // can't create one outside of a Lua state
28 [[nodiscard]] static void* operator new(size_t size_, lua_State* L_) noexcept { return lua_newuserdatauv(L_, size_, 0); }
29 // always embedded somewhere else or "in-place constructed" as a full userdata
30 // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception
31 static void operator delete([[maybe_unused]] void* p_, [[maybe_unused]] lua_State* L_) { LUA_ASSERT(L_, !"should never be called"); }
32
33 AllocatorDefinition(uintptr_t const version_, lua_Alloc const allocF_, void* const allocUD_) noexcept
34 : version{ version_ }
35 , allocF{ allocF_ }
36 , allocUD{ allocUD_ }
37 {
38 }
39 AllocatorDefinition() = default;
40 AllocatorDefinition(AllocatorDefinition const& rhs_) = default;
41 AllocatorDefinition(AllocatorDefinition&& rhs_) = default;
42 AllocatorDefinition& operator=(AllocatorDefinition const& rhs_) = default;
43 AllocatorDefinition& operator=(AllocatorDefinition&& rhs_) = default;
44
45 void initFrom(lua_State* L_)
46 {
47 allocF = lua_getallocf(L_, &allocUD);
48 }
49
50 void* alloc(size_t nsize_)
51 {
52 return allocF(allocUD, nullptr, 0, nsize_);
53 }
54
55 void free(void* ptr_, size_t osize_)
56 {
57 std::ignore = allocF(allocUD, ptr_, osize_, 0);
58 }
59};
60
61// #################################################################################################
62
63// mutex-protected allocator for use with Lua states that share a non-threadsafe allocator 18// mutex-protected allocator for use with Lua states that share a non-threadsafe allocator
64class ProtectedAllocator 19class ProtectedAllocator
65: public AllocatorDefinition 20: public AllocatorDefinition