diff options
Diffstat (limited to '')
-rw-r--r-- | src/universe.h | 86 |
1 files changed, 80 insertions, 6 deletions
diff --git a/src/universe.h b/src/universe.h index a6beb68..3aac20d 100644 --- a/src/universe.h +++ b/src/universe.h | |||
@@ -27,17 +27,91 @@ struct Lane; | |||
27 | // ################################################################################################ | 27 | // ################################################################################################ |
28 | 28 | ||
29 | // everything we need to provide to lua_newstate() | 29 | // everything we need to provide to lua_newstate() |
30 | struct AllocatorDefinition | 30 | class AllocatorDefinition |
31 | { | 31 | { |
32 | lua_Alloc allocF{ nullptr }; | 32 | public: |
33 | void* allocUD{ nullptr }; | 33 | |
34 | lua_Alloc m_allocF{ nullptr }; | ||
35 | void* m_allocUD{ nullptr }; | ||
36 | |||
37 | static void* operator new(size_t size_, lua_State* L) noexcept { return lua_newuserdatauv(L, size_, 0); } | ||
38 | // always embedded somewhere else or "in-place constructed" as a full userdata | ||
39 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception | ||
40 | static void operator delete(void* p_, lua_State* L) { ASSERT_L(!"should never be called") }; | ||
41 | |||
42 | AllocatorDefinition(lua_Alloc allocF_, void* allocUD_) noexcept | ||
43 | : m_allocF{ allocF_ } | ||
44 | , m_allocUD{ allocUD_ } | ||
45 | { | ||
46 | } | ||
47 | AllocatorDefinition() = default; | ||
48 | AllocatorDefinition(AllocatorDefinition const& rhs_) = default; | ||
49 | AllocatorDefinition(AllocatorDefinition&& rhs_) = default; | ||
50 | AllocatorDefinition& operator=(AllocatorDefinition const& rhs_) = default; | ||
51 | AllocatorDefinition& operator=(AllocatorDefinition&& rhs_) = default; | ||
52 | |||
53 | void initFrom(lua_State* L) | ||
54 | { | ||
55 | m_allocF = lua_getallocf(L, &m_allocUD); | ||
56 | } | ||
57 | |||
58 | void* lua_alloc(void* ptr_, size_t osize_, size_t nsize_) | ||
59 | { | ||
60 | m_allocF(m_allocUD, ptr_, osize_, nsize_); | ||
61 | } | ||
62 | |||
63 | void* alloc(size_t nsize_) | ||
64 | { | ||
65 | return m_allocF(m_allocUD, nullptr, 0, nsize_); | ||
66 | } | ||
67 | |||
68 | void free(void* ptr_, size_t osize_) | ||
69 | { | ||
70 | std::ignore = m_allocF(m_allocUD, ptr_, osize_, 0); | ||
71 | } | ||
34 | }; | 72 | }; |
35 | 73 | ||
74 | // ################################################################################################ | ||
75 | |||
36 | // mutex-protected allocator for use with Lua states that share a non-threadsafe allocator | 76 | // mutex-protected allocator for use with Lua states that share a non-threadsafe allocator |
37 | struct ProtectedAllocator | 77 | class ProtectedAllocator : public AllocatorDefinition |
38 | { | 78 | { |
39 | AllocatorDefinition definition; | 79 | private: |
40 | std::mutex lock; | 80 | |
81 | std::mutex m_lock; | ||
82 | |||
83 | static void* protected_lua_Alloc(void* ud_, void* ptr_, size_t osize_, size_t nsize_) | ||
84 | { | ||
85 | ProtectedAllocator* const s{ static_cast<ProtectedAllocator*>(ud_) }; | ||
86 | std::lock_guard<std::mutex> guard{ s->m_lock }; | ||
87 | return s->m_allocF(s->m_allocUD, ptr_, osize_, nsize_); | ||
88 | } | ||
89 | |||
90 | public: | ||
91 | |||
92 | // 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) | ||
93 | static void* operator new(size_t size_, lua_State* L) noexcept = delete; | ||
94 | static void operator delete(void* p_, lua_State* L) = delete; | ||
95 | |||
96 | AllocatorDefinition makeDefinition() | ||
97 | { | ||
98 | return AllocatorDefinition{ protected_lua_Alloc, this}; | ||
99 | } | ||
100 | |||
101 | void installIn(lua_State* L) | ||
102 | { | ||
103 | lua_setallocf(L, protected_lua_Alloc, this); | ||
104 | } | ||
105 | |||
106 | void removeFrom(lua_State* L) | ||
107 | { | ||
108 | // remove the protected allocator, if any | ||
109 | if (m_allocF != nullptr) | ||
110 | { | ||
111 | // install the non-protected allocator | ||
112 | lua_setallocf(L, m_allocF, m_allocUD); | ||
113 | } | ||
114 | } | ||
41 | }; | 115 | }; |
42 | 116 | ||
43 | // ################################################################################################ | 117 | // ################################################################################################ |