aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2011-02-12 17:06:03 +0100
committerBenoit Germain <bnt.germain@gmail.com>2011-02-12 17:06:03 +0100
commita661736f7984292a41d71847de68590f6b8ca08a (patch)
tree43e0799c20e835f1cc2d8c5fa1324b64301763e0 /src
parentc91a03bd956bf19848253bded8217687ccd2ad81 (diff)
downloadlanes-a661736f7984292a41d71847de68590f6b8ca08a.tar.gz
lanes-a661736f7984292a41d71847de68590f6b8ca08a.tar.bz2
lanes-a661736f7984292a41d71847de68590f6b8ca08a.zip
Changed idfunc signature and contract to clarify that fact it is not lua-callable and to be able to require the module it was exported from in the target lanes.
Diffstat (limited to 'src')
-rw-r--r--src/lanes.c102
-rw-r--r--src/lanes.lua12
-rw-r--r--src/tools.c170
-rw-r--r--src/tools.h8
4 files changed, 163 insertions, 129 deletions
diff --git a/src/lanes.c b/src/lanes.c
index f4bef7b..16a8edc 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -64,7 +64,7 @@
64 * ... 64 * ...
65 */ 65 */
66 66
67const char *VERSION= "2.0.10"; 67const char *VERSION= "2.0.11";
68 68
69/* 69/*
70=============================================================================== 70===============================================================================
@@ -359,7 +359,8 @@ static const char *init_keepers(void) {
359 lua_State *L= luaL_newstate(); 359 lua_State *L= luaL_newstate();
360 if (!L) return "out of memory"; 360 if (!L) return "out of memory";
361 361
362 luaG_openlibs( L, "io,table" ); // 'io' for debugging messages 362 luaG_openlibs( L, "io,table,package" ); // 'io' for debugging messages, package because we need to require modules exporting idfuncs
363 serialize_require( L);
363 364
364 lua_pushlightuserdata( L, &nil_sentinel ); 365 lua_pushlightuserdata( L, &nil_sentinel );
365 lua_setglobal( L, "nil_sentinel" ); 366 lua_setglobal( L, "nil_sentinel" );
@@ -449,9 +450,9 @@ struct s_Linda {
449 SIGNAL_T write_happened; 450 SIGNAL_T write_happened;
450}; 451};
451 452
452static int LG_linda_id( lua_State* ); 453static void linda_id( lua_State*, char const * const which);
453 454
454#define lua_toLinda(L,n) ((struct s_Linda *)luaG_todeep( L, LG_linda_id, n )) 455#define lua_toLinda(L,n) ((struct s_Linda *)luaG_todeep( L, linda_id, n ))
455 456
456 457
457/* 458/*
@@ -462,7 +463,8 @@ static int LG_linda_id( lua_State* );
462* Returns: 'true' if the value was queued 463* Returns: 'true' if the value was queued
463* 'false' for timeout (only happens when the queue size is limited) 464* 'false' for timeout (only happens when the queue size is limited)
464*/ 465*/
465LUAG_FUNC( linda_send ) { 466LUAG_FUNC( linda_send )
467{
466 struct s_Linda *linda= lua_toLinda( L, 1 ); 468 struct s_Linda *linda= lua_toLinda( L, 1 );
467 bool_t ret; 469 bool_t ret;
468 bool_t cancel= FALSE; 470 bool_t cancel= FALSE;
@@ -750,21 +752,22 @@ LUAG_FUNC( linda_deep ) {
750* Returns a metatable for the proxy objects ('__gc' method not needed; will 752* Returns a metatable for the proxy objects ('__gc' method not needed; will
751* be added by 'luaG_...') 753* be added by 'luaG_...')
752* 754*
755* string= linda_id( "module")
756*
757* Returns the name of the module that a state should require
758* in order to keep a handle on the shared library that exported the idfunc
759*
753* = linda_id( str, ... ) 760* = linda_id( str, ... )
754* 761*
755* For any other strings, the ID function must not react at all. This allows 762* For any other strings, the ID function must not react at all. This allows
756* future extensions of the system. 763* future extensions of the system.
757*/ 764*/
758LUAG_FUNC( linda_id ) { 765static void linda_id( lua_State *L, char const * const which)
759 const char *which= lua_tostring(L,1); 766{
760 767 if (strcmp( which, "new" )==0)
761 if (strcmp( which, "new" )==0) { 768 {
762 struct s_Linda *s; 769 struct s_Linda *s;
763 770
764 /* We don't use any parameters, but one could (they're at [2..TOS])
765 */
766 ASSERT_L( lua_gettop(L)==1 );
767
768 /* The deep data is allocated separately of Lua stack; we might no 771 /* The deep data is allocated separately of Lua stack; we might no
769 * longer be around when last reference to it is being released. 772 * longer be around when last reference to it is being released.
770 * One can use any memory allocation scheme. 773 * One can use any memory allocation scheme.
@@ -776,11 +779,11 @@ LUAG_FUNC( linda_id ) {
776 SIGNAL_INIT( &s->write_happened ); 779 SIGNAL_INIT( &s->write_happened );
777 780
778 lua_pushlightuserdata( L, s ); 781 lua_pushlightuserdata( L, s );
779 return 1; 782 }
780 783 else if (strcmp( which, "delete" )==0)
781 } else if (strcmp( which, "delete" )==0) { 784 {
782 struct s_Keeper *K; 785 struct s_Keeper *K;
783 struct s_Linda *s= lua_touserdata(L,2); 786 struct s_Linda *s= lua_touserdata(L,1);
784 ASSERT_L(s); 787 ASSERT_L(s);
785 788
786 /* Clean associated structures in the keeper state. 789 /* Clean associated structures in the keeper state.
@@ -797,18 +800,20 @@ LUAG_FUNC( linda_id ) {
797 SIGNAL_FREE( &s->read_happened ); 800 SIGNAL_FREE( &s->read_happened );
798 SIGNAL_FREE( &s->write_happened ); 801 SIGNAL_FREE( &s->write_happened );
799 free(s); 802 free(s);
803 }
804 else if (strcmp( which, "metatable" )==0)
805 {
800 806
801 return 0; 807 STACK_CHECK(L)
802
803 } else if (strcmp( which, "metatable" )==0) {
804
805 STACK_CHECK(L)
806 lua_newtable(L); 808 lua_newtable(L);
807 lua_newtable(L); 809 // metatable is its own index
808 // 810 lua_pushvalue( L, -1);
809 // [-2]: linda metatable 811 lua_setfield( L, -2, "__index");
810 // [-1]: metatable's to-be .__index table 812 // protect metatable from external access
811 813 lua_pushboolean( L, 0);
814 lua_setfield( L, -2, "__metatable");
815 //
816 // [-1]: linda metatable
812 lua_pushcfunction( L, LG_linda_send ); 817 lua_pushcfunction( L, LG_linda_send );
813 lua_setfield( L, -2, "send" ); 818 lua_setfield( L, -2, "send" );
814 819
@@ -827,13 +832,17 @@ LUAG_FUNC( linda_id ) {
827 lua_pushcfunction( L, LG_linda_deep ); 832 lua_pushcfunction( L, LG_linda_deep );
828 lua_setfield( L, -2, "deep" ); 833 lua_setfield( L, -2, "deep" );
829 834
830 lua_setfield( L, -2, "__index" ); 835 STACK_END(L,1)
831 STACK_END(L,1)
832
833 return 1;
834 } 836 }
835 837 else if( strcmp( which, "module") == 0)
836 return 0; // unknown request, be quiet 838 {
839 lua_pushliteral( L, "lua51-lanes");
840 }
841}
842
843LUAG_FUNC( linda)
844{
845 return luaG_deep_userdata( L, linda_id);
837} 846}
838 847
839 848
@@ -1014,8 +1023,10 @@ static void selfdestruct_atexit( void ) {
1014 MUTEX_UNLOCK( &selfdestruct_cs ); 1023 MUTEX_UNLOCK( &selfdestruct_cs );
1015 1024
1016 // Tell the timer thread to check it's cancel request 1025 // Tell the timer thread to check it's cancel request
1017 struct s_Linda *td = timer_deep->deep; 1026 {
1018 SIGNAL_ALL( &td->write_happened); 1027 struct s_Linda *td = timer_deep->deep;
1028 SIGNAL_ALL( &td->write_happened);
1029 }
1019 1030
1020 // When noticing their cancel, the lanes will remove themselves from 1031 // When noticing their cancel, the lanes will remove themselves from
1021 // the selfdestruct chain. 1032 // the selfdestruct chain.
@@ -1855,21 +1866,21 @@ LUAG_FUNC( wakeup_conv )
1855*/ 1866*/
1856 1867
1857static const struct luaL_reg lanes_functions [] = { 1868static const struct luaL_reg lanes_functions [] = {
1858 {"linda_id", LG_linda_id}, 1869 {"linda", LG_linda},
1859 {"thread_status", LG_thread_status}, 1870 {"thread_status", LG_thread_status},
1860 {"thread_join", LG_thread_join}, 1871 {"thread_join", LG_thread_join},
1861 {"thread_cancel", LG_thread_cancel}, 1872 {"thread_cancel", LG_thread_cancel},
1862 {"now_secs", LG_now_secs}, 1873 {"now_secs", LG_now_secs},
1863 {"wakeup_conv", LG_wakeup_conv}, 1874 {"wakeup_conv", LG_wakeup_conv},
1864 {"_single", LG__single}, 1875 {"_single", LG__single},
1865 {"_deep_userdata", luaG_deep_userdata},
1866 {NULL, NULL} 1876 {NULL, NULL}
1867}; 1877};
1868 1878
1869/* 1879/*
1870* One-time initializations 1880* One-time initializations
1871*/ 1881*/
1872static void init_once_LOCKED( lua_State *L, volatile DEEP_PRELUDE ** timer_deep_ref ) { 1882static void init_once_LOCKED( lua_State *L, volatile DEEP_PRELUDE ** timer_deep_ref )
1883{
1873 const char *err; 1884 const char *err;
1874 1885
1875#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) 1886#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
@@ -1919,8 +1930,9 @@ static void init_once_LOCKED( lua_State *L, volatile DEEP_PRELUDE ** timer_deep_
1919 } 1930 }
1920 #endif 1931 #endif
1921#endif 1932#endif
1922 err= init_keepers(); 1933 err= init_keepers();
1923 if (err) { 1934 if (err)
1935 {
1924 luaL_error( L, "Unable to initialize: %s", err ); 1936 luaL_error( L, "Unable to initialize: %s", err );
1925 } 1937 }
1926 1938
@@ -1928,13 +1940,11 @@ static void init_once_LOCKED( lua_State *L, volatile DEEP_PRELUDE ** timer_deep_
1928 // 1940 //
1929 ASSERT_L( timer_deep_ref && (!(*timer_deep_ref)) ); 1941 ASSERT_L( timer_deep_ref && (!(*timer_deep_ref)) );
1930 1942
1931 STACK_CHECK(L) 1943 STACK_CHECK(L)
1932 { 1944 {
1933 // proxy_ud= deep_userdata( idfunc ) 1945 // proxy_ud= deep_userdata( idfunc )
1934 // 1946 //
1935 lua_pushcfunction( L, luaG_deep_userdata ); 1947 luaG_deep_userdata( L, linda_id);
1936 lua_pushcfunction( L, LG_linda_id );
1937 lua_call( L, 1 /*args*/, 1 /*retvals*/ );
1938 1948
1939 ASSERT_L( lua_isuserdata(L,-1) ); 1949 ASSERT_L( lua_isuserdata(L,-1) );
1940 1950
@@ -1950,7 +1960,7 @@ static void init_once_LOCKED( lua_State *L, volatile DEEP_PRELUDE ** timer_deep_
1950 lua_rawset(L, LUA_REGISTRYINDEX); 1960 lua_rawset(L, LUA_REGISTRYINDEX);
1951 1961
1952 } 1962 }
1953 STACK_END(L,0) 1963 STACK_END(L,0)
1954} 1964}
1955 1965
1956int 1966int
@@ -2014,7 +2024,7 @@ __declspec(dllexport)
2014 lua_pushcclosure( L, LG_thread_new, 1 ); // metatable as closure param 2024 lua_pushcclosure( L, LG_thread_new, 1 ); // metatable as closure param
2015 lua_setfield(L, -2, "thread_new"); 2025 lua_setfield(L, -2, "thread_new");
2016 2026
2017 luaG_push_proxy( L, LG_linda_id, (DEEP_PRELUDE *) timer_deep ); 2027 luaG_push_proxy( L, linda_id, (DEEP_PRELUDE *) timer_deep );
2018 lua_setfield(L, -2, "timer_gateway"); 2028 lua_setfield(L, -2, "timer_gateway");
2019 2029
2020 lua_pushstring(L, VERSION); 2030 lua_pushstring(L, VERSION);
diff --git a/src/lanes.lua b/src/lanes.lua
index 42e946b..b6fbc08 100644
--- a/src/lanes.lua
+++ b/src/lanes.lua
@@ -45,8 +45,6 @@ local mm = require "lua51-lanes"
45assert( type(mm)=="table" ) 45assert( type(mm)=="table" )
46 46
47 47
48local linda_id= assert( mm.linda_id )
49
50local thread_new= assert(mm.thread_new) 48local thread_new= assert(mm.thread_new)
51local thread_status= assert(mm.thread_status) 49local thread_status= assert(mm.thread_status)
52local thread_join= assert(mm.thread_join) 50local thread_join= assert(mm.thread_join)
@@ -55,8 +53,6 @@ local thread_cancel= assert(mm.thread_cancel)
55local _single= assert(mm._single) 53local _single= assert(mm._single)
56local _version= assert(mm._version) 54local _version= assert(mm._version)
57 55
58local _deep_userdata= assert(mm._deep_userdata)
59
60local now_secs= assert( mm.now_secs ) 56local now_secs= assert( mm.now_secs )
61local wakeup_conv= assert( mm.wakeup_conv ) 57local wakeup_conv= assert( mm.wakeup_conv )
62local timer_gateway= assert( mm.timer_gateway ) 58local timer_gateway= assert( mm.timer_gateway )
@@ -336,11 +332,7 @@ end
336----- 332-----
337-- linda_ud= lanes.linda() 333-- linda_ud= lanes.linda()
338-- 334--
339function linda() 335linda = mm.linda
340 local proxy= _deep_userdata( linda_id )
341 assert( (type(proxy) == "userdata") and getmetatable(proxy) )
342 return proxy
343end
344 336
345 337
346---=== Timers ===--- 338---=== Timers ===---
@@ -505,7 +497,7 @@ if first_time then
505 -- We let the timer lane be a "free running" thread; no handle to it 497 -- We let the timer lane be a "free running" thread; no handle to it
506 -- remains. 498 -- remains.
507 -- 499 --
508 gen( "io", { priority=max_prio, globals={threadName="LanesTimer"} }, function() 500 gen( "io,package", { priority=max_prio, globals={threadName="LanesTimer"} }, function()
509 501
510 while true do 502 while true do
511 local next_wakeup= check_timers() 503 local next_wakeup= check_timers()
diff --git a/src/tools.c b/src/tools.c
index 6692890..d09b11e 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -280,26 +280,27 @@ void get_deep_lookup( lua_State *L ) {
280* or NULL if 'index' is not a deep userdata proxy. 280* or NULL if 'index' is not a deep userdata proxy.
281*/ 281*/
282static 282static
283lua_CFunction get_idfunc( lua_State *L, int index ) { 283luaG_IdFunction get_idfunc( lua_State *L, int index )
284 lua_CFunction ret; 284{
285 luaG_IdFunction ret;
285 286
286 index= STACK_ABS(L,index); 287 index= STACK_ABS(L,index);
287 288
288 STACK_GROW(L,1); 289 STACK_GROW(L,1);
289 290
290 STACK_CHECK(L) 291 STACK_CHECK(L)
291 if (!lua_getmetatable( L, index )) 292 if (!lua_getmetatable( L, index ))
292 return NULL; // no metatable 293 return NULL; // no metatable
293 294
294 // [-1]: metatable of [index] 295 // [-1]: metatable of [index]
295 296
296 get_deep_lookup(L); 297 get_deep_lookup(L);
297 // 298 //
298 // [-1]: idfunc/nil 299 // [-1]: idfunc/nil
299 300
300 ret= lua_tocfunction(L,-1); 301 ret= (luaG_IdFunction)lua_touserdata(L,-1);
301 lua_pop(L,1); 302 lua_pop(L,1);
302 STACK_END(L,0) 303 STACK_END(L,0)
303 return ret; 304 return ret;
304} 305}
305 306
@@ -311,7 +312,8 @@ lua_CFunction get_idfunc( lua_State *L, int index ) {
311* it up if reaches 0. 312* it up if reaches 0.
312*/ 313*/
313static 314static
314int deep_userdata_gc( lua_State *L ) { 315int deep_userdata_gc( lua_State *L )
316{
315 DEEP_PRELUDE **proxy= (DEEP_PRELUDE**)lua_touserdata( L, 1 ); 317 DEEP_PRELUDE **proxy= (DEEP_PRELUDE**)lua_touserdata( L, 1 );
316 DEEP_PRELUDE *p= *proxy; 318 DEEP_PRELUDE *p= *proxy;
317 int v; 319 int v;
@@ -319,27 +321,26 @@ int deep_userdata_gc( lua_State *L ) {
319 *proxy= 0; // make sure we don't use it any more 321 *proxy= 0; // make sure we don't use it any more
320 322
321 MUTEX_LOCK( &deep_lock ); 323 MUTEX_LOCK( &deep_lock );
322 v= --(p->refcount); 324 v= --(p->refcount);
323 MUTEX_UNLOCK( &deep_lock ); 325 MUTEX_UNLOCK( &deep_lock );
324 326
325 if (v==0) { 327 if (v==0)
326 int pushed; 328 {
327
328 // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup 329 // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup
329 // 330 //
330 lua_CFunction idfunc= get_idfunc(L,1); 331 luaG_IdFunction idfunc = get_idfunc(L,1);
331 ASSERT_L(idfunc); 332 ASSERT_L(idfunc);
332 333
333 lua_settop(L,0); // clean stack so we can call 'idfunc' directly 334 lua_settop( L, 0); // clean stack so we can call 'idfunc' directly
334 335
335 // void= idfunc( "delete", lightuserdata ) 336 // void= idfunc( "delete", lightuserdata )
336 // 337 //
337 lua_pushliteral( L, "delete" );
338 lua_pushlightuserdata( L, p->deep ); 338 lua_pushlightuserdata( L, p->deep );
339 pushed= idfunc(L); 339 idfunc( L, "delete");
340 340
341 if (pushed) 341 // top was set to 0, then userdata was pushed. "delete" might want to pop the userdata (we don't care), but should not push anything!
342 luaL_error( L, "Bad idfunc on \"delete\": returned something" ); 342 if ( lua_gettop( L) > 1)
343 luaL_error( L, "Bad idfunc on \"delete\": returned something");
343 344
344 DEEP_FREE( (void*)p ); 345 DEEP_FREE( (void*)p );
345 } 346 }
@@ -354,28 +355,31 @@ int deep_userdata_gc( lua_State *L ) {
354* used in this Lua state (metatable, registring it). Otherwise, increments the 355* used in this Lua state (metatable, registring it). Otherwise, increments the
355* reference count. 356* reference count.
356*/ 357*/
357void luaG_push_proxy( lua_State *L, lua_CFunction idfunc, DEEP_PRELUDE *prelude ) { 358void luaG_push_proxy( lua_State *L, luaG_IdFunction idfunc, DEEP_PRELUDE *prelude )
359{
358 DEEP_PRELUDE **proxy; 360 DEEP_PRELUDE **proxy;
359 361
360 // Check if a proxy already exists 362 // Check if a proxy already exists
361 push_registry_subtable_mode(L, DEEP_PROXY_CACHE_KEY, "v"); 363 push_registry_subtable_mode(L, DEEP_PROXY_CACHE_KEY, "v");
362 lua_pushlightuserdata(L, prelude->deep); 364 lua_pushlightuserdata(L, prelude->deep);
363 lua_rawget(L, -2); 365 lua_rawget(L, -2);
364 if (!lua_isnil(L, -1)) { 366 if (!lua_isnil(L, -1))
367 {
365 lua_remove(L, -2); // deep proxy cache table 368 lua_remove(L, -2); // deep proxy cache table
366 return; 369 return;
367 } else { 370 }
371 else
372 {
368 lua_pop(L, 2); // Pop the nil and proxy cache table 373 lua_pop(L, 2); // Pop the nil and proxy cache table
369 } 374 }
370 375
371
372 MUTEX_LOCK( &deep_lock ); 376 MUTEX_LOCK( &deep_lock );
373 ++(prelude->refcount); // one more proxy pointing to this deep data 377 ++(prelude->refcount); // one more proxy pointing to this deep data
374 MUTEX_UNLOCK( &deep_lock ); 378 MUTEX_UNLOCK( &deep_lock );
375 379
376 STACK_GROW(L,4); 380 STACK_GROW(L,4);
377 381
378 STACK_CHECK(L) 382 STACK_CHECK(L)
379 383
380 proxy= lua_newuserdata( L, sizeof( DEEP_PRELUDE* ) ); 384 proxy= lua_newuserdata( L, sizeof( DEEP_PRELUDE* ) );
381 ASSERT_L(proxy); 385 ASSERT_L(proxy);
@@ -383,28 +387,32 @@ void luaG_push_proxy( lua_State *L, lua_CFunction idfunc, DEEP_PRELUDE *prelude
383 387
384 // Get/create metatable for 'idfunc' (in this state) 388 // Get/create metatable for 'idfunc' (in this state)
385 // 389 //
386 lua_pushcfunction( L, idfunc ); // key 390 lua_pushlightuserdata( L, idfunc ); // key
387 get_deep_lookup(L); 391 get_deep_lookup(L);
388 // 392 //
389 // [-2]: proxy 393 // [-2]: proxy
390 // [-1]: metatable / nil 394 // [-1]: metatable / nil
391 395
392 if (lua_isnil(L,-1)) { 396 if (lua_isnil(L,-1))
393 // No metatable yet; make one and register it 397 {
394 // 398 int oldtop;
399 // No metatable yet. We have two things to do:
400
401 // 1 - make one and register it
395 lua_pop(L,1); 402 lua_pop(L,1);
396 403
397 // tbl= idfunc( "metatable" ) 404 // tbl= idfunc( "metatable" )
398 // 405 //
399 lua_pushcfunction( L, idfunc ); 406 oldtop = lua_gettop( L);
400 lua_pushliteral( L, "metatable" ); 407 idfunc( L, "metatable");
401 lua_call( L, 1 /*args*/, 1 /*results*/ ); 408 //
402 // 409 // [-2]: proxy
403 // [-2]: proxy 410 // [-1]: metatable (returned by 'idfunc')
404 // [-1]: metatable (returned by 'idfunc')
405 411
406 if (!lua_istable(L,-1)) 412 if (lua_gettop( L) - oldtop != 1 || !lua_istable(L, -1))
413 {
407 luaL_error( L, "Bad idfunc on \"metatable\": did not return one" ); 414 luaL_error( L, "Bad idfunc on \"metatable\": did not return one" );
415 }
408 416
409 // Add '__gc' method 417 // Add '__gc' method
410 // 418 //
@@ -414,16 +422,40 @@ void luaG_push_proxy( lua_State *L, lua_CFunction idfunc, DEEP_PRELUDE *prelude
414 // Memorize for later rounds 422 // Memorize for later rounds
415 // 423 //
416 lua_pushvalue( L,-1 ); 424 lua_pushvalue( L,-1 );
417 lua_pushcfunction( L, idfunc ); 425 lua_pushlightuserdata( L, idfunc );
418 // 426 //
419 // [-4]: proxy 427 // [-4]: proxy
420 // [-3]: metatable (2nd ref) 428 // [-3]: metatable (2nd ref)
421 // [-2]: metatable 429 // [-2]: metatable
422 // [-1]: idfunc 430 // [-1]: idfunc
423 431
424 set_deep_lookup(L); 432 set_deep_lookup(L);
425 } 433
426 STACK_MID(L,2) 434 // 2 - cause the target state to require the module that exported the idfunc
435 // this is needed because we must make sure the shared library is still loaded as long as we hold a pointer on the idfunc
436 lua_getglobal( L, "require");
437 if( lua_isfunction( L, -1)) // just in case...
438 {
439 // make sure the function pushed a single value on the stack!
440 int oldtop = lua_gettop( L);
441 idfunc( L, "module");
442 if( lua_gettop( L) - oldtop != 1 || !lua_isstring( L, -1))
443 {
444 luaL_error( L, "Bad idfunc on \"module\": should return a string");
445 }
446 // if we are inside a call to require, this will raise a "reentrency" error that we absorb silently (we don't care, this probably means the module is already being required, which is what we need)
447 if( lua_pcall( L, 1, 0, 0) != 0)
448 {
449 //char const * const errMsg = lua_tostring( L, -1); // just to see it in the debugger
450 lua_pop( L, 1);
451 }
452 }
453 else
454 {
455 lua_pop( L, 1);
456 }
457 }
458 STACK_MID(L,2)
427 ASSERT_L( lua_isuserdata(L,-2) ); 459 ASSERT_L( lua_isuserdata(L,-2) );
428 ASSERT_L( lua_istable(L,-1) ); 460 ASSERT_L( lua_istable(L,-1) );
429 461
@@ -439,7 +471,7 @@ void luaG_push_proxy( lua_State *L, lua_CFunction idfunc, DEEP_PRELUDE *prelude
439 lua_rawset(L, -3); 471 lua_rawset(L, -3);
440 lua_pop(L, 1); // Remove the cache proxy table 472 lua_pop(L, 1); // Remove the cache proxy table
441 473
442 STACK_END(L,1) 474 STACK_END(L,1)
443 // [-1]: proxy userdata 475 // [-1]: proxy userdata
444} 476}
445 477
@@ -466,9 +498,9 @@ void luaG_push_proxy( lua_State *L, lua_CFunction idfunc, DEEP_PRELUDE *prelude
466* 498*
467* Returns: 'proxy' userdata for accessing the deep data via 'luaG_todeep()' 499* Returns: 'proxy' userdata for accessing the deep data via 'luaG_todeep()'
468*/ 500*/
469int luaG_deep_userdata( lua_State *L ) { 501int luaG_deep_userdata( lua_State *L, luaG_IdFunction idfunc)
470 lua_CFunction idfunc= lua_tocfunction( L,1 ); 502{
471 int pushed; 503 int oldtop;
472 504
473 DEEP_PRELUDE *prelude= DEEP_MALLOC( sizeof(DEEP_PRELUDE) ); 505 DEEP_PRELUDE *prelude= DEEP_MALLOC( sizeof(DEEP_PRELUDE) );
474 ASSERT_L(prelude); 506 ASSERT_L(prelude);
@@ -476,20 +508,17 @@ int luaG_deep_userdata( lua_State *L ) {
476 prelude->refcount= 0; // 'luaG_push_proxy' will lift it to 1 508 prelude->refcount= 0; // 'luaG_push_proxy' will lift it to 1
477 509
478 STACK_GROW(L,1); 510 STACK_GROW(L,1);
479 STACK_CHECK(L) 511 STACK_CHECK(L)
480
481 // Replace 'idfunc' with "new" in the stack (keep possible other params)
482 //
483 lua_remove(L,1);
484 lua_pushliteral( L, "new" );
485 lua_insert(L,1);
486 512
487 // lightuserdata= idfunc( "new" [, ...] ) 513 // lightuserdata= idfunc( "new" [, ...] )
488 // 514 //
489 pushed= idfunc(L); 515 oldtop = lua_gettop( L);
516 idfunc(L, "new");
490 517
491 if ((pushed!=1) || lua_type(L,-1) != LUA_TLIGHTUSERDATA) 518 if( lua_gettop( L) - oldtop != 1 || lua_type( L, -1) != LUA_TLIGHTUSERDATA)
492 luaL_error( L, "Bad idfunc on \"new\": did not return light userdata" ); 519 {
520 luaL_error( L, "Bad idfunc on \"new\": did not return light userdata");
521 }
493 522
494 prelude->deep= lua_touserdata(L,-1); 523 prelude->deep= lua_touserdata(L,-1);
495 ASSERT_L(prelude->deep); 524 ASSERT_L(prelude->deep);
@@ -497,10 +526,10 @@ int luaG_deep_userdata( lua_State *L ) {
497 lua_pop(L,1); // pop deep data 526 lua_pop(L,1); // pop deep data
498 527
499 luaG_push_proxy( L, idfunc, prelude ); 528 luaG_push_proxy( L, idfunc, prelude );
500 // 529 //
501 // [-1]: proxy userdata 530 // [-1]: proxy userdata
502 531
503 STACK_END(L,1) 532 STACK_END(L,1)
504 return 1; 533 return 1;
505} 534}
506 535
@@ -511,15 +540,16 @@ int luaG_deep_userdata( lua_State *L ) {
511* Reference count is not changed, and access to the deep userdata is not 540* Reference count is not changed, and access to the deep userdata is not
512* serialized. It is the module's responsibility to prevent conflicting usage. 541* serialized. It is the module's responsibility to prevent conflicting usage.
513*/ 542*/
514void *luaG_todeep( lua_State *L, lua_CFunction idfunc, int index ) { 543void *luaG_todeep( lua_State *L, luaG_IdFunction idfunc, int index )
544{
515 DEEP_PRELUDE **proxy; 545 DEEP_PRELUDE **proxy;
516 546
517 STACK_CHECK(L) 547 STACK_CHECK(L)
518 if (get_idfunc(L,index) != idfunc) 548 if( get_idfunc(L,index) != idfunc)
519 return NULL; // no metatable, or wrong kind 549 return NULL; // no metatable, or wrong kind
520 550
521 proxy= (DEEP_PRELUDE**)lua_touserdata( L, index ); 551 proxy= (DEEP_PRELUDE**)lua_touserdata( L, index );
522 STACK_END(L,0) 552 STACK_END(L,0)
523 553
524 return (*proxy)->deep; 554 return (*proxy)->deep;
525} 555}
@@ -533,14 +563,14 @@ void *luaG_todeep( lua_State *L, lua_CFunction idfunc, int index ) {
533* (not copied) 563* (not copied)
534*/ 564*/
535static 565static
536lua_CFunction luaG_copydeep( lua_State *L, lua_State *L2, int index ) { 566luaG_IdFunction luaG_copydeep( lua_State *L, lua_State *L2, int index )
567{
537 DEEP_PRELUDE **proxy; 568 DEEP_PRELUDE **proxy;
538 DEEP_PRELUDE *p; 569 DEEP_PRELUDE *p;
539 570
540 lua_CFunction idfunc; 571 luaG_IdFunction idfunc = get_idfunc( L, index);
541 572 if (!idfunc)
542 idfunc= get_idfunc( L, index ); 573 return NULL; // not a deep userdata
543 if (!idfunc) return NULL; // not a deep userdata
544 574
545 // Increment reference count 575 // Increment reference count
546 // 576 //
diff --git a/src/tools.h b/src/tools.h
index aad26df..05bee59 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -48,19 +48,21 @@
48 48
49#define luaG_typename( L, index ) lua_typename( L, lua_type(L,index) ) 49#define luaG_typename( L, index ) lua_typename( L, lua_type(L,index) )
50 50
51typedef void (*luaG_IdFunction)( lua_State *L, char const * const which);
52
51void luaG_dump( lua_State* L ); 53void luaG_dump( lua_State* L );
52 54
53const char *luaG_openlibs( lua_State *L, const char *libs ); 55const char *luaG_openlibs( lua_State *L, const char *libs );
54 56
55int luaG_deep_userdata( lua_State *L ); 57int luaG_deep_userdata( lua_State *L, luaG_IdFunction idfunc);
56void *luaG_todeep( lua_State *L, lua_CFunction idfunc, int index ); 58void *luaG_todeep( lua_State *L, luaG_IdFunction idfunc, int index );
57 59
58typedef struct { 60typedef struct {
59 volatile int refcount; 61 volatile int refcount;
60 void *deep; 62 void *deep;
61} DEEP_PRELUDE; 63} DEEP_PRELUDE;
62 64
63void luaG_push_proxy( lua_State *L, lua_CFunction idfunc, DEEP_PRELUDE *deep_userdata ); 65void luaG_push_proxy( lua_State *L, luaG_IdFunction idfunc, DEEP_PRELUDE *deep_userdata );
64 66
65void luaG_inter_copy( lua_State *L, lua_State *L2, uint_t n ); 67void luaG_inter_copy( lua_State *L, lua_State *L2, uint_t n );
66void luaG_inter_move( lua_State *L, lua_State *L2, uint_t n ); 68void luaG_inter_move( lua_State *L, lua_State *L2, uint_t n );