diff options
Diffstat (limited to 'src/lanes.c')
-rw-r--r-- | src/lanes.c | 102 |
1 files changed, 56 insertions, 46 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 | ||
67 | const char *VERSION= "2.0.10"; | 67 | const 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 | ||
452 | static int LG_linda_id( lua_State* ); | 453 | static 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 | */ |
465 | LUAG_FUNC( linda_send ) { | 466 | LUAG_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 | */ |
758 | LUAG_FUNC( linda_id ) { | 765 | static 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 | |||
843 | LUAG_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 | ||
1857 | static const struct luaL_reg lanes_functions [] = { | 1868 | static 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 | */ |
1872 | static void init_once_LOCKED( lua_State *L, volatile DEEP_PRELUDE ** timer_deep_ref ) { | 1882 | static 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 | ||
1956 | int | 1966 | int |
@@ -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); |