diff options
author | Benoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m> | 2018-11-25 12:45:11 +0100 |
---|---|---|
committer | Benoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m> | 2018-11-25 12:45:11 +0100 |
commit | 8d6500fe389624be422ee546f71a1efd4456eabe (patch) | |
tree | b9462a142180b8edb01e1eb284a42fea9f0156bc /src/tools.c | |
parent | 60e5d94af372471c2a3bab91963588ca650bff7b (diff) | |
download | lanes-8d6500fe389624be422ee546f71a1efd4456eabe.tar.gz lanes-8d6500fe389624be422ee546f71a1efd4456eabe.tar.bz2 lanes-8d6500fe389624be422ee546f71a1efd4456eabe.zip |
protect_allocator configure option is gone, long live allocator (more embedders-friendly)
Diffstat (limited to 'src/tools.c')
-rw-r--r-- | src/tools.c | 109 |
1 files changed, 99 insertions, 10 deletions
diff --git a/src/tools.c b/src/tools.c index f8fc342..8885dea 100644 --- a/src/tools.c +++ b/src/tools.c | |||
@@ -105,6 +105,79 @@ void luaG_dump( lua_State* L) | |||
105 | } | 105 | } |
106 | #endif // _DEBUG | 106 | #endif // _DEBUG |
107 | 107 | ||
108 | // ################################################################################################ | ||
109 | |||
110 | static void* protected_lua_Alloc( void *ud, void *ptr, size_t osize, size_t nsize) | ||
111 | { | ||
112 | void* p; | ||
113 | ProtectedAllocator* s = (ProtectedAllocator*) ud; | ||
114 | MUTEX_LOCK( &s->lock); | ||
115 | p = s->definition.allocF( s->definition.allocUD, ptr, osize, nsize); | ||
116 | MUTEX_UNLOCK( &s->lock); | ||
117 | return p; | ||
118 | } | ||
119 | |||
120 | static int luaG_provide_protected_allocator( lua_State* L) | ||
121 | { | ||
122 | Universe* U = universe_get( L); | ||
123 | AllocatorDefinition* def = lua_newuserdata( L, sizeof(AllocatorDefinition)); | ||
124 | def->allocF = protected_lua_Alloc; | ||
125 | def->allocUD = &U->protected_allocator; | ||
126 | return 1; | ||
127 | } | ||
128 | |||
129 | // Do I need to disable this when compiling for LuaJIT to prevent issues? | ||
130 | void initialize_allocator_function( Universe* U, lua_State* L) | ||
131 | { | ||
132 | STACK_CHECK( L, 0); | ||
133 | lua_getfield( L, -1, "allocator"); // settings allocator|nil|"protected" | ||
134 | if( !lua_isnil( L, -1)) | ||
135 | { | ||
136 | // store C function pointer in an internal variable | ||
137 | U->provide_allocator = lua_tocfunction( L, -1); // settings allocator | ||
138 | if( U->provide_allocator != NULL) | ||
139 | { | ||
140 | // make sure the function doesn't have upvalues | ||
141 | char const* upname = lua_getupvalue( L, -1, 1); // settings allocator upval? | ||
142 | if( upname != NULL) // should be "" for C functions with upvalues if any | ||
143 | { | ||
144 | (void) luaL_error( L, "config.allocator() shouldn't have upvalues"); | ||
145 | } | ||
146 | // remove this C function from the config table so that it doesn't cause problems | ||
147 | // when we transfer the config table in newly created Lua states | ||
148 | lua_pushnil( L); // settings allocator nil | ||
149 | lua_setfield( L, -3, "allocator"); // settings allocator | ||
150 | } | ||
151 | else if( lua_type( L, -1) == LUA_TSTRING) | ||
152 | { | ||
153 | // initialize all we need for the protected allocator | ||
154 | MUTEX_INIT( &U->protected_allocator.lock); // the mutex | ||
155 | // and the original allocator to call from inside protection by the mutex | ||
156 | U->protected_allocator.definition.allocF = lua_getallocf( L, &U->protected_allocator.definition.allocUD); | ||
157 | // before a state is created, this function will be called to obtain the allocator | ||
158 | U->provide_allocator = luaG_provide_protected_allocator; | ||
159 | |||
160 | lua_setallocf( L, protected_lua_Alloc, &U->protected_allocator); | ||
161 | } | ||
162 | } | ||
163 | lua_pop( L, 1); // settings | ||
164 | STACK_END( L, 0); | ||
165 | } | ||
166 | |||
167 | void cleanup_allocator_function( Universe* U, lua_State* L) | ||
168 | { | ||
169 | // remove the protected allocator, if any | ||
170 | if( U->protected_allocator.definition.allocF != NULL) | ||
171 | { | ||
172 | // install the non-protected allocator | ||
173 | lua_setallocf( L, U->protected_allocator.definition.allocF, U->protected_allocator.definition.allocUD); | ||
174 | // release the mutex | ||
175 | MUTEX_FREE( &U->protected_allocator.lock); | ||
176 | } | ||
177 | } | ||
178 | |||
179 | // ################################################################################################ | ||
180 | |||
108 | void initialize_on_state_create( Universe* U, lua_State* L) | 181 | void initialize_on_state_create( Universe* U, lua_State* L) |
109 | { | 182 | { |
110 | STACK_CHECK( L, 0); | 183 | STACK_CHECK( L, 0); |
@@ -629,6 +702,31 @@ void call_on_state_create( Universe* U, lua_State* L, lua_State* from_, LookupMo | |||
629 | } | 702 | } |
630 | } | 703 | } |
631 | 704 | ||
705 | lua_State* create_state( Universe* U, lua_State* from_) | ||
706 | { | ||
707 | lua_State* L; | ||
708 | if( U->provide_allocator != NULL) | ||
709 | { | ||
710 | lua_pushcclosure( from_, U->provide_allocator, 0); | ||
711 | lua_call( from_, 0, 1); | ||
712 | { | ||
713 | AllocatorDefinition* def = lua_touserdata( from_, -1); | ||
714 | L = lua_newstate( def->allocF, def->allocUD); | ||
715 | } | ||
716 | lua_pop( from_, 1); | ||
717 | } | ||
718 | else | ||
719 | { | ||
720 | L = luaL_newstate(); | ||
721 | } | ||
722 | |||
723 | if( L == NULL) | ||
724 | { | ||
725 | (void) luaL_error( from_, "luaG_newstate() failed while creating state; out of memory"); | ||
726 | } | ||
727 | return L; | ||
728 | } | ||
729 | |||
632 | /* | 730 | /* |
633 | * Like 'luaL_openlibs()' but allows the set of libraries be selected | 731 | * Like 'luaL_openlibs()' but allows the set of libraries be selected |
634 | * | 732 | * |
@@ -644,16 +742,7 @@ void call_on_state_create( Universe* U, lua_State* L, lua_State* from_, LookupMo | |||
644 | */ | 742 | */ |
645 | lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) | 743 | lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) |
646 | { | 744 | { |
647 | // re-use alloc function from the originating state | 745 | lua_State* L = create_state( U, from_); |
648 | #if PROPAGATE_ALLOCF | ||
649 | PROPAGATE_ALLOCF_PREP( from_); | ||
650 | #endif // PROPAGATE_ALLOCF | ||
651 | lua_State* L = PROPAGATE_ALLOCF_ALLOC(); | ||
652 | |||
653 | if( L == NULL) | ||
654 | { | ||
655 | (void) luaL_error( from_, "luaG_newstate() failed while creating state; out of memory"); | ||
656 | } | ||
657 | 746 | ||
658 | STACK_GROW( L, 2); | 747 | STACK_GROW( L, 2); |
659 | STACK_CHECK_ABS( L, 0); | 748 | STACK_CHECK_ABS( L, 0); |