aboutsummaryrefslogtreecommitdiff
path: root/src
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>2017-08-02 14:39:44 +0200
committerBenoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m>2017-08-02 14:39:44 +0200
commitc5d772fd0dd9120885be96255d5dd4a3ed6b8aac (patch)
tree4f92866eddac0788ad3c060af041c6945ffe7797 /src
parent00fa87f8460f32259737d0285d7855e68b55ab31 (diff)
downloadlanes-c5d772fd0dd9120885be96255d5dd4a3ed6b8aac.tar.gz
lanes-c5d772fd0dd9120885be96255d5dd4a3ed6b8aac.tar.bz2
lanes-c5d772fd0dd9120885be96255d5dd4a3ed6b8aac.zip
Deep userdata improvements
Support for user-provided __gc Improved example
Diffstat (limited to 'src')
-rw-r--r--src/deep.c46
-rw-r--r--src/tools.c2
2 files changed, 29 insertions, 19 deletions
diff --git a/src/deep.c b/src/deep.c
index 71a798c..737ebe9 100644
--- a/src/deep.c
+++ b/src/deep.c
@@ -104,7 +104,7 @@ void push_registry_subtable( lua_State* L, void* key_)
104 104
105/*---=== Deep userdata ===---*/ 105/*---=== Deep userdata ===---*/
106 106
107void luaG_pushdeepversion( lua_State* L) { (void) lua_pushliteral( L, "f248e77a-a84d-44b5-9ad0-96c05679b885");} 107void luaG_pushdeepversion( lua_State* L) { (void) lua_pushliteral( L, "ab8743e5-84f8-485d-9c39-008e84656188");}
108 108
109 109
110 110
@@ -219,11 +219,11 @@ void free_deep_prelude( lua_State* L, struct DEEP_PRELUDE* prelude_)
219 219
220 220
221/* 221/*
222* void= mt.__gc( proxy_ud ) 222 * void= mt.__gc( proxy_ud )
223* 223 *
224* End of life for a proxy object; reduce the deep reference count and clean 224 * End of life for a proxy object; reduce the deep reference count and clean it up if reaches 0.
225* it up if reaches 0. 225 *
226*/ 226 */
227static int deep_userdata_gc( lua_State* L) 227static int deep_userdata_gc( lua_State* L)
228{ 228{
229 struct DEEP_PRELUDE** proxy = (struct DEEP_PRELUDE**) lua_touserdata( L, 1); 229 struct DEEP_PRELUDE** proxy = (struct DEEP_PRELUDE**) lua_touserdata( L, 1);
@@ -231,8 +231,6 @@ static int deep_userdata_gc( lua_State* L)
231 struct s_Universe* U = universe_get( L); 231 struct s_Universe* U = universe_get( L);
232 int v; 232 int v;
233 233
234 *proxy = 0; // make sure we don't use it any more
235
236 // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded 234 // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded
237 // in that case, we are not multithreaded and locking isn't necessary anyway 235 // in that case, we are not multithreaded and locking isn't necessary anyway
238 if( U) MUTEX_LOCK( &U->deep_lock); 236 if( U) MUTEX_LOCK( &U->deep_lock);
@@ -241,6 +239,13 @@ static int deep_userdata_gc( lua_State* L)
241 239
242 if( v == 0) 240 if( v == 0)
243 { 241 {
242 // retrieve wrapped __gc
243 lua_pushvalue( L, lua_upvalueindex( 1)); // self __gc?
244 if( !lua_isnil( L, -1))
245 {
246 lua_insert( L, -2); // __gc self
247 lua_call( L, 1, 0); //
248 }
244 // 'idfunc' expects a clean stack to work on 249 // 'idfunc' expects a clean stack to work on
245 lua_settop( L, 0); 250 lua_settop( L, 0);
246 free_deep_prelude( L, p); 251 free_deep_prelude( L, p);
@@ -251,6 +256,7 @@ static int deep_userdata_gc( lua_State* L)
251 luaL_error( L, "Bad idfunc(eDO_delete): should not push anything"); 256 luaL_error( L, "Bad idfunc(eDO_delete): should not push anything");
252 } 257 }
253 } 258 }
259 *proxy = NULL; // make sure we don't use it any more, just in case
254 return 0; 260 return 0;
255} 261}
256 262
@@ -321,22 +327,26 @@ char const* push_deep_proxy( struct s_Universe* U, lua_State* L, struct DEEP_PRE
321 return "Bad idfunc(eOP_metatable): mismatched deep version"; 327 return "Bad idfunc(eOP_metatable): mismatched deep version";
322 } 328 }
323 lua_pop( L, 2); // DPC proxy metatable 329 lua_pop( L, 2); // DPC proxy metatable
324 // make sure the idfunc didn't export __gc, as we will store our own 330 // if the metatable contains a __gc, we will call it from our own
325 lua_getfield( L, -1, "__gc"); // DPC proxy metatable __gc 331 lua_getfield( L, -1, "__gc"); // DPC proxy metatable __gc
326 if( !lua_isnil( L, -1))
327 {
328 lua_pop( L, 4); //
329 return "idfunc-created metatable shouldn't contain __gc";
330 }
331 lua_pop( L, 1); // DPC proxy metatable
332 } 332 }
333 else 333 else
334 { 334 {
335 // keepers need a minimal metatable that only contains __gc 335 // keepers need a minimal metatable that only contains our own __gc
336 lua_newtable( L); // DPC proxy metatable 336 lua_newtable( L); // DPC proxy metatable
337 lua_pushnil( L); // DPC proxy metatable nil
338 }
339 if (lua_isnil(L, -1))
340 {
341 // Add our own '__gc' method
342 lua_pop( L, 1); // DPC proxy metatable
343 lua_pushcfunction( L, deep_userdata_gc); // DPC proxy metatable deep_userdata_gc
344 }
345 else
346 {
347 // Add our own '__gc' method wrapping the original
348 lua_pushcclosure( L, deep_userdata_gc, 1); // DPC proxy metatable deep_userdata_gc
337 } 349 }
338 // Add our own '__gc' method
339 lua_pushcfunction( L, deep_userdata_gc); // DPC proxy metatable __gc
340 lua_setfield( L, -2, "__gc"); // DPC proxy metatable 350 lua_setfield( L, -2, "__gc"); // DPC proxy metatable
341 351
342 // Memorize for later rounds 352 // Memorize for later rounds
diff --git a/src/tools.c b/src/tools.c
index f935c26..9403fd6 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -822,7 +822,7 @@ static int func_lookup_sentinel( lua_State* L)
822// function sentinel used to transfer native table from/to keeper states 822// function sentinel used to transfer native table from/to keeper states
823static int table_lookup_sentinel( lua_State* L) 823static int table_lookup_sentinel( lua_State* L)
824{ 824{
825 return luaL_error( L, "table lookup sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex(1))); 825 return luaL_error( L, "table lookup sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1)));
826} 826}
827 827
828/* 828/*