aboutsummaryrefslogtreecommitdiff
path: root/src/deep.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/deep.c')
-rw-r--r--src/deep.c66
1 files changed, 26 insertions, 40 deletions
diff --git a/src/deep.c b/src/deep.c
index af7f580..c351bf7 100644
--- a/src/deep.c
+++ b/src/deep.c
@@ -105,16 +105,6 @@ void push_registry_subtable( lua_State* L, UniqueKey key_)
105 105
106/*---=== Deep userdata ===---*/ 106/*---=== Deep userdata ===---*/
107 107
108void 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
211void free_deep_prelude( lua_State* L, DeepPrelude* prelude_) 201void 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
454int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc) 436int 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