aboutsummaryrefslogtreecommitdiff
path: root/src/tools.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools.cpp')
-rw-r--r--src/tools.cpp87
1 files changed, 37 insertions, 50 deletions
diff --git a/src/tools.cpp b/src/tools.cpp
index 68846ba..89e5499 100644
--- a/src/tools.cpp
+++ b/src/tools.cpp
@@ -156,105 +156,92 @@ void luaG_dump( lua_State* L)
156// ################################################################################################ 156// ################################################################################################
157 157
158// same as PUC-Lua l_alloc 158// same as PUC-Lua l_alloc
159static void* libc_lua_Alloc(void* ud, void* ptr, size_t osize, size_t nsize) 159extern "C" static void* libc_lua_Alloc([[maybe_unused]] void* ud, [[maybe_unused]] void* ptr_, size_t osize_, size_t nsize_)
160{ 160{
161 (void)ud; (void)osize; /* not used */ 161 if (nsize_ == 0)
162 if (nsize == 0)
163 { 162 {
164 free(ptr); 163 free(ptr_);
165 return nullptr; 164 return nullptr;
166 } 165 }
167 else 166 else
168 { 167 {
169 return realloc(ptr, nsize); 168 return realloc(ptr_, nsize_);
170 } 169 }
171} 170}
172 171
173static void* protected_lua_Alloc( void *ud, void *ptr, size_t osize, size_t nsize) 172// #################################################################################################
174{
175 void* p;
176 ProtectedAllocator* s = (ProtectedAllocator*) ud;
177 s->lock.lock();
178 p = s->definition.allocF( s->definition.allocUD, ptr, osize, nsize);
179 s->lock.unlock();
180 return p;
181}
182 173
183static int luaG_provide_protected_allocator( lua_State* L) 174static int luaG_provide_protected_allocator(lua_State* L)
184{ 175{
185 Universe* U = universe_get( L); 176 Universe* const U{ universe_get(L) };
186 AllocatorDefinition* const def = (AllocatorDefinition*) lua_newuserdatauv( L, sizeof(AllocatorDefinition), 0); 177 // push a new full userdata on the stack, giving access to the universe's protected allocator
187 def->allocF = protected_lua_Alloc; 178 AllocatorDefinition* const def{ new (L) AllocatorDefinition{ U->protected_allocator.makeDefinition() } };
188 def->allocUD = &U->protected_allocator;
189 return 1; 179 return 1;
190} 180}
191 181
182// #################################################################################################
183
192// called once at the creation of the universe (therefore L is the master Lua state everything originates from) 184// called once at the creation of the universe (therefore L is the master Lua state everything originates from)
193// Do I need to disable this when compiling for LuaJIT to prevent issues? 185// Do I need to disable this when compiling for LuaJIT to prevent issues?
194void initialize_allocator_function( Universe* U, lua_State* L) 186void initialize_allocator_function(Universe* U, lua_State* L)
195{ 187{
196 STACK_CHECK_START_REL(L, 1); // settings 188 STACK_CHECK_START_REL(L, 1); // settings
197 lua_getfield( L, -1, "allocator"); // settings allocator|nil|"protected" 189 lua_getfield(L, -1, "allocator"); // settings allocator|nil|"protected"
198 if( !lua_isnil( L, -1)) 190 if (!lua_isnil(L, -1))
199 { 191 {
200 // store C function pointer in an internal variable 192 // store C function pointer in an internal variable
201 U->provide_allocator = lua_tocfunction( L, -1); // settings allocator 193 U->provide_allocator = lua_tocfunction(L, -1); // settings allocator
202 if (U->provide_allocator != nullptr) 194 if (U->provide_allocator != nullptr)
203 { 195 {
204 // make sure the function doesn't have upvalues 196 // make sure the function doesn't have upvalues
205 char const* upname = lua_getupvalue( L, -1, 1); // settings allocator upval? 197 char const* upname = lua_getupvalue(L, -1, 1); // settings allocator upval?
206 if (upname != nullptr) // should be "" for C functions with upvalues if any 198 if (upname != nullptr) // should be "" for C functions with upvalues if any
207 { 199 {
208 (void) luaL_error( L, "config.allocator() shouldn't have upvalues"); 200 (void) luaL_error(L, "config.allocator() shouldn't have upvalues");
209 } 201 }
210 // remove this C function from the config table so that it doesn't cause problems 202 // remove this C function from the config table so that it doesn't cause problems
211 // when we transfer the config table in newly created Lua states 203 // when we transfer the config table in newly created Lua states
212 lua_pushnil( L); // settings allocator nil 204 lua_pushnil(L); // settings allocator nil
213 lua_setfield( L, -3, "allocator"); // settings allocator 205 lua_setfield(L, -3, "allocator"); // settings allocator
214 } 206 }
215 else if( lua_type( L, -1) == LUA_TSTRING) // should be "protected" 207 else if (lua_type(L, -1) == LUA_TSTRING) // should be "protected"
216 { 208 {
209 ASSERT_L(strcmp(lua_tostring(L, -1), "protected") == 0);
217 // set the original allocator to call from inside protection by the mutex 210 // set the original allocator to call from inside protection by the mutex
218 U->protected_allocator.definition.allocF = lua_getallocf( L, &U->protected_allocator.definition.allocUD); 211 U->protected_allocator.initFrom(L);
212 U->protected_allocator.installIn(L);
219 // before a state is created, this function will be called to obtain the allocator 213 // before a state is created, this function will be called to obtain the allocator
220 U->provide_allocator = luaG_provide_protected_allocator; 214 U->provide_allocator = luaG_provide_protected_allocator;
221
222 lua_setallocf( L, protected_lua_Alloc, &U->protected_allocator);
223 } 215 }
224 } 216 }
225 else 217 else
226 { 218 {
227 // just grab whatever allocator was provided to lua_newstate 219 // just grab whatever allocator was provided to lua_newstate
228 U->protected_allocator.definition.allocF = lua_getallocf( L, &U->protected_allocator.definition.allocUD); 220 U->protected_allocator.initFrom(L);
229 } 221 }
230 lua_pop( L, 1); // settings 222 lua_pop(L, 1); // settings
231 STACK_CHECK(L, 1); 223 STACK_CHECK(L, 1);
232 224
233 lua_getfield( L, -1, "internal_allocator"); // settings "libc"|"allocator" 225 lua_getfield(L, -1, "internal_allocator"); // settings "libc"|"allocator"
234 { 226 {
235 char const* allocator = lua_tostring( L, -1); 227 char const* allocator = lua_tostring(L, -1);
236 if (strcmp(allocator, "libc") == 0) 228 if (strcmp(allocator, "libc") == 0)
237 { 229 {
238 U->internal_allocator.allocF = libc_lua_Alloc; 230 U->internal_allocator = AllocatorDefinition{ libc_lua_Alloc, nullptr };
239 U->internal_allocator.allocUD = nullptr; 231 }
232 else if (U->provide_allocator = luaG_provide_protected_allocator)
233 {
234 // user wants mutex protection on the state's allocator. Use protection for our own allocations too, just in case.
235 U->internal_allocator = U->protected_allocator.makeDefinition();
240 } 236 }
241 else 237 else
242 { 238 {
243 U->internal_allocator = U->protected_allocator.definition; 239 // no protection required, just use whatever we have as-is.
240 U->internal_allocator = U->protected_allocator;
244 } 241 }
245 } 242 }
246 lua_pop( L, 1); // settings 243 lua_pop(L, 1); // settings
247 STACK_CHECK( L, 1); 244 STACK_CHECK(L, 1);
248}
249
250void cleanup_allocator_function( Universe* U, lua_State* L)
251{
252 // remove the protected allocator, if any
253 if (U->protected_allocator.definition.allocF != nullptr)
254 {
255 // install the non-protected allocator
256 lua_setallocf( L, U->protected_allocator.definition.allocF, U->protected_allocator.definition.allocUD);
257 }
258} 245}
259 246
260// ################################################################################################ 247// ################################################################################################