aboutsummaryrefslogtreecommitdiff
path: root/src/tools.c
diff options
context:
space:
mode:
authorBenoit 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
committerBenoit 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
commit8d6500fe389624be422ee546f71a1efd4456eabe (patch)
treeb9462a142180b8edb01e1eb284a42fea9f0156bc /src/tools.c
parent60e5d94af372471c2a3bab91963588ca650bff7b (diff)
downloadlanes-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.c109
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
110static 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
120static 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?
130void 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
167void 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
108void initialize_on_state_create( Universe* U, lua_State* L) 181void 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
705lua_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 */
645lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) 743lua_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);