diff options
Diffstat (limited to 'src/lanes.cpp')
-rw-r--r-- | src/lanes.cpp | 81 |
1 files changed, 80 insertions, 1 deletions
diff --git a/src/lanes.cpp b/src/lanes.cpp index d211b6a..ee40ffa 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -81,7 +81,8 @@ THE SOFTWARE. | |||
81 | 81 | ||
82 | #include "lanes.h" | 82 | #include "lanes.h" |
83 | 83 | ||
84 | #include "compat.h" | 84 | #include "deep.h" |
85 | #include "intercopycontext.h" | ||
85 | #include "keeper.h" | 86 | #include "keeper.h" |
86 | #include "lanes_private.h" | 87 | #include "lanes_private.h" |
87 | #include "state.h" | 88 | #include "state.h" |
@@ -1522,6 +1523,84 @@ LUAG_FUNC(wakeup_conv) | |||
1522 | } | 1523 | } |
1523 | 1524 | ||
1524 | // ################################################################################################# | 1525 | // ################################################################################################# |
1526 | // ################################### custom allocator support #################################### | ||
1527 | // ################################################################################################# | ||
1528 | |||
1529 | // same as PUC-Lua l_alloc | ||
1530 | extern "C" [[nodiscard]] static void* libc_lua_Alloc([[maybe_unused]] void* ud, [[maybe_unused]] void* ptr_, [[maybe_unused]] size_t osize_, size_t nsize_) | ||
1531 | { | ||
1532 | if (nsize_ == 0) { | ||
1533 | free(ptr_); | ||
1534 | return nullptr; | ||
1535 | } else { | ||
1536 | return realloc(ptr_, nsize_); | ||
1537 | } | ||
1538 | } | ||
1539 | |||
1540 | // ################################################################################################# | ||
1541 | |||
1542 | [[nodiscard]] static int luaG_provide_protected_allocator(lua_State* L_) | ||
1543 | { | ||
1544 | Universe* const U{ universe_get(L_) }; | ||
1545 | // push a new full userdata on the stack, giving access to the universe's protected allocator | ||
1546 | [[maybe_unused]] AllocatorDefinition* const def{ new (L_) AllocatorDefinition{ U->protectedAllocator.makeDefinition() } }; | ||
1547 | return 1; | ||
1548 | } | ||
1549 | |||
1550 | // ################################################################################################# | ||
1551 | |||
1552 | // called once at the creation of the universe (therefore L is the master Lua state everything originates from) | ||
1553 | // Do I need to disable this when compiling for LuaJIT to prevent issues? | ||
1554 | static void initialize_allocator_function(Universe* U_, lua_State* L_) | ||
1555 | { | ||
1556 | STACK_CHECK_START_REL(L_, 1); // L_: settings | ||
1557 | lua_getfield(L_, -1, "allocator"); // L_: settings allocator|nil|"protected" | ||
1558 | if (!lua_isnil(L_, -1)) { | ||
1559 | // store C function pointer in an internal variable | ||
1560 | U_->provideAllocator = lua_tocfunction(L_, -1); // L_: settings allocator | ||
1561 | if (U_->provideAllocator != nullptr) { | ||
1562 | // make sure the function doesn't have upvalues | ||
1563 | char const* upname = lua_getupvalue(L_, -1, 1); // L_: settings allocator upval? | ||
1564 | if (upname != nullptr) { // should be "" for C functions with upvalues if any | ||
1565 | raise_luaL_error(L_, "config.allocator() shouldn't have upvalues"); | ||
1566 | } | ||
1567 | // remove this C function from the config table so that it doesn't cause problems | ||
1568 | // when we transfer the config table in newly created Lua states | ||
1569 | lua_pushnil(L_); // L_: settings allocator nil | ||
1570 | lua_setfield(L_, -3, "allocator"); // L_: settings allocator | ||
1571 | } else if (lua_type(L_, -1) == LUA_TSTRING) { // should be "protected" | ||
1572 | LUA_ASSERT(L_, strcmp(lua_tostring(L_, -1), "protected") == 0); | ||
1573 | // set the original allocator to call from inside protection by the mutex | ||
1574 | U_->protectedAllocator.initFrom(L_); | ||
1575 | U_->protectedAllocator.installIn(L_); | ||
1576 | // before a state is created, this function will be called to obtain the allocator | ||
1577 | U_->provideAllocator = luaG_provide_protected_allocator; | ||
1578 | } | ||
1579 | } else { | ||
1580 | // just grab whatever allocator was provided to lua_newstate | ||
1581 | U_->protectedAllocator.initFrom(L_); | ||
1582 | } | ||
1583 | lua_pop(L_, 1); // L_: settings | ||
1584 | STACK_CHECK(L_, 1); | ||
1585 | |||
1586 | lua_getfield(L_, -1, "internal_allocator"); // L_: settings "libc"|"allocator" | ||
1587 | { | ||
1588 | char const* allocator = lua_tostring(L_, -1); | ||
1589 | if (strcmp(allocator, "libc") == 0) { | ||
1590 | U_->internalAllocator = AllocatorDefinition{ libc_lua_Alloc, nullptr }; | ||
1591 | } else if (U_->provideAllocator == luaG_provide_protected_allocator) { | ||
1592 | // user wants mutex protection on the state's allocator. Use protection for our own allocations too, just in case. | ||
1593 | U_->internalAllocator = U_->protectedAllocator.makeDefinition(); | ||
1594 | } else { | ||
1595 | // no protection required, just use whatever we have as-is. | ||
1596 | U_->internalAllocator = U_->protectedAllocator; | ||
1597 | } | ||
1598 | } | ||
1599 | lua_pop(L_, 1); // L_: settings | ||
1600 | STACK_CHECK(L_, 1); | ||
1601 | } | ||
1602 | |||
1603 | // ################################################################################################# | ||
1525 | // ######################################## Module linkage ######################################### | 1604 | // ######################################## Module linkage ######################################### |
1526 | // ################################################################################################# | 1605 | // ################################################################################################# |
1527 | 1606 | ||