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> | 2017-08-02 14:39:44 +0200 |
---|---|---|
committer | Benoit 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 |
commit | c5d772fd0dd9120885be96255d5dd4a3ed6b8aac (patch) | |
tree | 4f92866eddac0788ad3c060af041c6945ffe7797 /src | |
parent | 00fa87f8460f32259737d0285d7855e68b55ab31 (diff) | |
download | lanes-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.c | 46 | ||||
-rw-r--r-- | src/tools.c | 2 |
2 files changed, 29 insertions, 19 deletions
@@ -104,7 +104,7 @@ void push_registry_subtable( lua_State* L, void* key_) | |||
104 | 104 | ||
105 | /*---=== Deep userdata ===---*/ | 105 | /*---=== Deep userdata ===---*/ |
106 | 106 | ||
107 | void luaG_pushdeepversion( lua_State* L) { (void) lua_pushliteral( L, "f248e77a-a84d-44b5-9ad0-96c05679b885");} | 107 | void 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 | */ |
227 | static int deep_userdata_gc( lua_State* L) | 227 | static 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 |
823 | static int table_lookup_sentinel( lua_State* L) | 823 | static 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 | /* |