diff options
Diffstat (limited to 'src/deep.c')
-rw-r--r-- | src/deep.c | 66 |
1 files changed, 26 insertions, 40 deletions
@@ -105,16 +105,6 @@ void push_registry_subtable( lua_State* L, UniqueKey key_) | |||
105 | 105 | ||
106 | /*---=== Deep userdata ===---*/ | 106 | /*---=== Deep userdata ===---*/ |
107 | 107 | ||
108 | void luaG_pushdeepversion( lua_State* L) { (void) lua_pushliteral( L, "ab8743e5-84f8-485d-9c39-008e84656188");} | ||
109 | |||
110 | |||
111 | |||
112 | /* The deep portion must be allocated separately of any Lua state's; it's | ||
113 | * lifespan may be longer than that of the creating state. | ||
114 | */ | ||
115 | #define DEEP_MALLOC malloc | ||
116 | #define DEEP_FREE free | ||
117 | |||
118 | /* | 108 | /* |
119 | * 'registry[REGKEY]' is a two-way lookup table for 'idfunc's and those type's | 109 | * 'registry[REGKEY]' is a two-way lookup table for 'idfunc's and those type's |
120 | * metatables: | 110 | * metatables: |
@@ -211,10 +201,9 @@ static inline luaG_IdFunction get_idfunc( lua_State* L, int index, LookupMode mo | |||
211 | void free_deep_prelude( lua_State* L, DeepPrelude* prelude_) | 201 | void free_deep_prelude( lua_State* L, DeepPrelude* prelude_) |
212 | { | 202 | { |
213 | // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup | 203 | // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup |
214 | lua_pushlightuserdata( L, prelude_->deep); | 204 | lua_pushlightuserdata( L, prelude_); |
215 | ASSERT_L( prelude_->idfunc); | 205 | ASSERT_L( prelude_->idfunc); |
216 | prelude_->idfunc( L, eDO_delete); | 206 | prelude_->idfunc( L, eDO_delete); |
217 | DEEP_FREE( (void*) prelude_); | ||
218 | } | 207 | } |
219 | 208 | ||
220 | 209 | ||
@@ -276,7 +265,7 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, Lo | |||
276 | 265 | ||
277 | // Check if a proxy already exists | 266 | // Check if a proxy already exists |
278 | push_registry_subtable_mode( L, DEEP_PROXY_CACHE_KEY, "v"); // DPC | 267 | push_registry_subtable_mode( L, DEEP_PROXY_CACHE_KEY, "v"); // DPC |
279 | lua_pushlightuserdata( L, prelude->deep); // DPC deep | 268 | lua_pushlightuserdata( L, prelude); // DPC deep |
280 | lua_rawget( L, -2); // DPC proxy | 269 | lua_rawget( L, -2); // DPC proxy |
281 | if ( !lua_isnil( L, -1)) | 270 | if ( !lua_isnil( L, -1)) |
282 | { | 271 | { |
@@ -313,20 +302,13 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, Lo | |||
313 | // 1 - make one and register it | 302 | // 1 - make one and register it |
314 | if( mode_ != eLM_ToKeeper) | 303 | if( mode_ != eLM_ToKeeper) |
315 | { | 304 | { |
316 | (void) prelude->idfunc( L, eDO_metatable); // DPC proxy metatable deepversion | 305 | (void) prelude->idfunc( L, eDO_metatable); // DPC proxy metatable |
317 | if( lua_gettop( L) - oldtop != 1 || !lua_istable( L, -2) || !lua_isstring( L, -1)) | 306 | if( lua_gettop( L) - oldtop != 0 || !lua_istable( L, -1)) |
318 | { | 307 | { |
319 | lua_settop( L, oldtop); // DPC proxy X | 308 | lua_settop( L, oldtop); // DPC proxy X |
320 | lua_pop( L, 3); // | 309 | lua_pop( L, 3); // |
321 | return "Bad idfunc(eOP_metatable): unexpected pushed value"; | 310 | return "Bad idfunc(eOP_metatable): unexpected pushed value"; |
322 | } | 311 | } |
323 | luaG_pushdeepversion( L); // DPC proxy metatable deepversion deepversion | ||
324 | if( !lua501_equal( L, -1, -2)) | ||
325 | { | ||
326 | lua_pop( L, 5); // | ||
327 | return "Bad idfunc(eOP_metatable): mismatched deep version"; | ||
328 | } | ||
329 | lua_pop( L, 2); // DPC proxy metatable | ||
330 | // if the metatable contains a __gc, we will call it from our own | 312 | // if the metatable contains a __gc, we will call it from our own |
331 | lua_getfield( L, -1, "__gc"); // DPC proxy metatable __gc | 313 | lua_getfield( L, -1, "__gc"); // DPC proxy metatable __gc |
332 | } | 314 | } |
@@ -420,7 +402,7 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, Lo | |||
420 | lua_setmetatable( L, -2); // DPC proxy | 402 | lua_setmetatable( L, -2); // DPC proxy |
421 | 403 | ||
422 | // If we're here, we obviously had to create a new proxy, so cache it. | 404 | // If we're here, we obviously had to create a new proxy, so cache it. |
423 | lua_pushlightuserdata( L, (*proxy)->deep); // DPC proxy deep | 405 | lua_pushlightuserdata( L, prelude); // DPC proxy deep |
424 | lua_pushvalue( L, -2); // DPC proxy deep proxy | 406 | lua_pushvalue( L, -2); // DPC proxy deep proxy |
425 | lua_rawset( L, -4); // DPC proxy | 407 | lua_rawset( L, -4); // DPC proxy |
426 | lua_remove( L, -2); // proxy | 408 | lua_remove( L, -2); // proxy |
@@ -454,34 +436,38 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, Lo | |||
454 | int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc) | 436 | int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc) |
455 | { | 437 | { |
456 | char const* errmsg; | 438 | char const* errmsg; |
457 | DeepPrelude* prelude = DEEP_MALLOC( sizeof( DeepPrelude)); | ||
458 | if( prelude == NULL) | ||
459 | { | ||
460 | return luaL_error( L, "couldn't not allocate deep prelude: out of memory"); | ||
461 | } | ||
462 | |||
463 | prelude->refcount = 0; // 'push_deep_proxy' will lift it to 1 | ||
464 | prelude->idfunc = idfunc; | ||
465 | 439 | ||
466 | STACK_GROW( L, 1); | 440 | STACK_GROW( L, 1); |
467 | STACK_CHECK( L); | 441 | STACK_CHECK( L); |
468 | { | 442 | { |
469 | int oldtop = lua_gettop( L); | 443 | int oldtop = lua_gettop( L); |
470 | prelude->deep = idfunc( L, eDO_new); | 444 | DeepPrelude* prelude = idfunc( L, eDO_new); |
471 | if( prelude->deep == NULL) | 445 | if( prelude == NULL) |
472 | { | 446 | { |
473 | luaL_error( L, "idfunc(eDO_new) failed to create deep userdata (out of memory)"); | 447 | luaL_error( L, "idfunc(eDO_new) failed to create deep userdata (out of memory)"); |
474 | } | 448 | } |
449 | if( prelude->magic.value != DEEP_VERSION.value) | ||
450 | { | ||
451 | // just in case, don't leak the newly allocated deep userdata object | ||
452 | lua_pushlightuserdata( L, prelude); | ||
453 | idfunc( L, eDO_delete); | ||
454 | return luaL_error( L, "Bad idfunc(eDO_new): DEEP_VERSION is incorrect, rebuild your implementation with the latest deep implementation"); | ||
455 | } | ||
456 | prelude->refcount = 0; // 'push_deep_proxy' will lift it to 1 | ||
457 | prelude->idfunc = idfunc; | ||
475 | 458 | ||
476 | if( lua_gettop( L) - oldtop != 0) | 459 | if( lua_gettop( L) - oldtop != 0) |
477 | { | 460 | { |
478 | luaL_error( L, "Bad idfunc(eDO_new): should not push anything on the stack"); | 461 | // just in case, don't leak the newly allocated deep userdata object |
462 | lua_pushlightuserdata( L, prelude); | ||
463 | idfunc( L, eDO_delete); | ||
464 | return luaL_error( L, "Bad idfunc(eDO_new): should not push anything on the stack"); | ||
465 | } | ||
466 | errmsg = push_deep_proxy( universe_get( L), L, prelude, eLM_LaneBody); // proxy | ||
467 | if( errmsg != NULL) | ||
468 | { | ||
469 | return luaL_error( L, errmsg); | ||
479 | } | 470 | } |
480 | } | ||
481 | errmsg = push_deep_proxy( universe_get( L), L, prelude, eLM_LaneBody); // proxy | ||
482 | if( errmsg != NULL) | ||
483 | { | ||
484 | luaL_error( L, errmsg); | ||
485 | } | 471 | } |
486 | STACK_END( L, 1); | 472 | STACK_END( L, 1); |
487 | return 1; | 473 | return 1; |
@@ -508,7 +494,7 @@ void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index) | |||
508 | proxy = (DeepPrelude**) lua_touserdata( L, index); | 494 | proxy = (DeepPrelude**) lua_touserdata( L, index); |
509 | STACK_END( L, 0); | 495 | STACK_END( L, 0); |
510 | 496 | ||
511 | return (*proxy)->deep; | 497 | return *proxy; |
512 | } | 498 | } |
513 | 499 | ||
514 | 500 | ||