diff options
Diffstat (limited to 'src/tools.cpp')
-rw-r--r-- | src/tools.cpp | 87 |
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 |
159 | static void* libc_lua_Alloc(void* ud, void* ptr, size_t osize, size_t nsize) | 159 | extern "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 | ||
173 | static 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 | ||
183 | static int luaG_provide_protected_allocator( lua_State* L) | 174 | static 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? |
194 | void initialize_allocator_function( Universe* U, lua_State* L) | 186 | void 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 | |||
250 | void 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 | // ################################################################################################ |