diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lanes.c | 405 |
1 files changed, 245 insertions, 160 deletions
diff --git a/src/lanes.c b/src/lanes.c index 64c144c..cf88171 100644 --- a/src/lanes.c +++ b/src/lanes.c | |||
@@ -52,7 +52,7 @@ | |||
52 | * ... | 52 | * ... |
53 | */ | 53 | */ |
54 | 54 | ||
55 | char const* VERSION = "3.8.3"; | 55 | char const* VERSION = "3.8.4"; |
56 | 56 | ||
57 | /* | 57 | /* |
58 | =============================================================================== | 58 | =============================================================================== |
@@ -147,7 +147,7 @@ struct s_lane | |||
147 | // M: sets to PENDING (before launching) | 147 | // M: sets to PENDING (before launching) |
148 | // S: updates -> RUNNING/WAITING -> DONE/ERROR_ST/CANCELLED | 148 | // S: updates -> RUNNING/WAITING -> DONE/ERROR_ST/CANCELLED |
149 | 149 | ||
150 | SIGNAL_T * volatile waiting_on; | 150 | SIGNAL_T* volatile waiting_on; |
151 | // | 151 | // |
152 | // When status is WAITING, points on the linda's signal the thread waits on, else NULL | 152 | // When status is WAITING, points on the linda's signal the thread waits on, else NULL |
153 | 153 | ||
@@ -414,10 +414,12 @@ static void lane_cleanup( struct s_lane* s) | |||
414 | * Actual data is kept within a keeper state, which is hashed by the 's_Linda' | 414 | * Actual data is kept within a keeper state, which is hashed by the 's_Linda' |
415 | * pointer (which is same to all userdatas pointing to it). | 415 | * pointer (which is same to all userdatas pointing to it). |
416 | */ | 416 | */ |
417 | struct s_Linda { | 417 | struct s_Linda |
418 | SIGNAL_T read_happened; | 418 | { |
419 | SIGNAL_T write_happened; | 419 | SIGNAL_T read_happened; |
420 | char name[1]; | 420 | SIGNAL_T write_happened; |
421 | enum e_cancel_request simulate_cancel; | ||
422 | char name[1]; | ||
421 | }; | 423 | }; |
422 | 424 | ||
423 | static void linda_id( lua_State*, char const * const which); | 425 | static void linda_id( lua_State*, char const * const which); |
@@ -450,11 +452,11 @@ static void check_key_types( lua_State*L, int _start, int _end) | |||
450 | */ | 452 | */ |
451 | LUAG_FUNC( linda_send) | 453 | LUAG_FUNC( linda_send) |
452 | { | 454 | { |
453 | struct s_Linda *linda = lua_toLinda( L, 1); | 455 | struct s_Linda* linda = lua_toLinda( L, 1); |
454 | bool_t ret; | 456 | bool_t ret; |
455 | enum e_cancel_request cancel = CANCEL_NONE; | 457 | enum e_cancel_request cancel = CANCEL_NONE; |
456 | int pushed; | 458 | int pushed; |
457 | time_d timeout= -1.0; | 459 | time_d timeout = -1.0; |
458 | uint_t key_i = 2; // index of first key, if timeout not there | 460 | uint_t key_i = 2; // index of first key, if timeout not there |
459 | 461 | ||
460 | luaL_argcheck( L, linda, 1, "expected a linda object!"); | 462 | luaL_argcheck( L, linda, 1, "expected a linda object!"); |
@@ -507,7 +509,6 @@ LUAG_FUNC( linda_send) | |||
507 | // | 509 | // |
508 | SIGNAL_ALL( &linda->write_happened); | 510 | SIGNAL_ALL( &linda->write_happened); |
509 | break; | 511 | break; |
510 | |||
511 | } | 512 | } |
512 | if( timeout == 0.0) | 513 | if( timeout == 0.0) |
513 | { | 514 | { |
@@ -520,11 +521,15 @@ LUAG_FUNC( linda_send) | |||
520 | struct s_lane* const s = get_lane_from_registry( L); | 521 | struct s_lane* const s = get_lane_from_registry( L); |
521 | if( s != NULL) | 522 | if( s != NULL) |
522 | { | 523 | { |
523 | cancel = s->cancel_request; // testing here causes no delays | 524 | cancel = s->cancel_request; |
524 | if( cancel != CANCEL_NONE) // if user wants to cancel, the call returns without sending anything | 525 | } |
525 | { | 526 | cancel = (cancel != CANCEL_NONE) ? cancel : linda->simulate_cancel; |
526 | break; | 527 | if( cancel != CANCEL_NONE) // if user wants to cancel, the call returns without sending anything |
527 | } | 528 | { |
529 | break; | ||
530 | } | ||
531 | if( s != NULL) | ||
532 | { | ||
528 | // change status of lane to "waiting" | 533 | // change status of lane to "waiting" |
529 | prev_status = s->status; // RUNNING, most likely | 534 | prev_status = s->status; // RUNNING, most likely |
530 | ASSERT_L( prev_status == RUNNING); // but check, just in case | 535 | ASSERT_L( prev_status == RUNNING); // but check, just in case |
@@ -532,22 +537,22 @@ LUAG_FUNC( linda_send) | |||
532 | ASSERT_L( s->waiting_on == NULL); | 537 | ASSERT_L( s->waiting_on == NULL); |
533 | s->waiting_on = &linda->read_happened; | 538 | s->waiting_on = &linda->read_happened; |
534 | } | 539 | } |
535 | // could not send because no room: wait until some data was read before trying again, or until timeout is reached | ||
536 | if( !SIGNAL_WAIT( &linda->read_happened, &K->lock_, timeout)) | ||
537 | { | 540 | { |
541 | // could not send because no room: wait until some data was read before trying again, or until timeout is reached | ||
542 | bool_t const signalled = SIGNAL_WAIT( &linda->read_happened, &K->lock_, timeout); | ||
538 | if( s != NULL) | 543 | if( s != NULL) |
539 | { | 544 | { |
540 | s->waiting_on = NULL; | 545 | s->waiting_on = NULL; |
541 | s->status = prev_status; | 546 | s->status = prev_status; |
542 | // if woken by a cancel request, be sure to handle it properly | 547 | // if a cancel request is pending, be sure to handle it as soon as possible |
543 | cancel = s->cancel_request; | 548 | cancel = s->cancel_request; |
544 | } | 549 | } |
545 | break; | 550 | cancel = (cancel != CANCEL_NONE) ? cancel : linda->simulate_cancel; |
546 | } | 551 | if( !signalled || cancel != CANCEL_NONE) |
547 | if( s != NULL) | 552 | { |
548 | { | 553 | // waiting returned after a timeout, or pending cancel: we are done |
549 | s->waiting_on = NULL; | 554 | break; |
550 | s->status = prev_status; | 555 | } |
551 | } | 556 | } |
552 | } | 557 | } |
553 | } | 558 | } |
@@ -593,7 +598,7 @@ LUAG_FUNC( linda_send) | |||
593 | #define BATCH_SENTINEL "270e6c9d-280f-4983-8fee-a7ecdda01475" | 598 | #define BATCH_SENTINEL "270e6c9d-280f-4983-8fee-a7ecdda01475" |
594 | LUAG_FUNC( linda_receive) | 599 | LUAG_FUNC( linda_receive) |
595 | { | 600 | { |
596 | struct s_Linda *linda = lua_toLinda( L, 1); | 601 | struct s_Linda* linda = lua_toLinda( L, 1); |
597 | int pushed, expected_pushed_min, expected_pushed_max; | 602 | int pushed, expected_pushed_min, expected_pushed_max; |
598 | enum e_cancel_request cancel = CANCEL_NONE; | 603 | enum e_cancel_request cancel = CANCEL_NONE; |
599 | keeper_api_t keeper_receive; | 604 | keeper_api_t keeper_receive; |
@@ -650,7 +655,7 @@ LUAG_FUNC( linda_receive) | |||
650 | } | 655 | } |
651 | 656 | ||
652 | { | 657 | { |
653 | struct s_Keeper *K = keeper_acquire( linda); | 658 | struct s_Keeper* K = keeper_acquire( linda); |
654 | if( K == NULL) return 0; | 659 | if( K == NULL) return 0; |
655 | for( ;;) | 660 | for( ;;) |
656 | { | 661 | { |
@@ -682,11 +687,15 @@ LUAG_FUNC( linda_receive) | |||
682 | struct s_lane* const s = get_lane_from_registry( L); | 687 | struct s_lane* const s = get_lane_from_registry( L); |
683 | if( s != NULL) | 688 | if( s != NULL) |
684 | { | 689 | { |
685 | cancel = s->cancel_request; // testing here causes no delays | 690 | cancel = s->cancel_request; |
686 | if( cancel != CANCEL_NONE) // if user wants to cancel, the call returns without providing anything | 691 | } |
687 | { | 692 | cancel = (cancel != CANCEL_NONE) ? cancel : linda->simulate_cancel; |
688 | break; | 693 | if( cancel != CANCEL_NONE) // if user wants to cancel, the call returns without providing anything |
689 | } | 694 | { |
695 | break; | ||
696 | } | ||
697 | if( s != NULL) | ||
698 | { | ||
690 | // change status of lane to "waiting" | 699 | // change status of lane to "waiting" |
691 | prev_status = s->status; // RUNNING, most likely | 700 | prev_status = s->status; // RUNNING, most likely |
692 | ASSERT_L( prev_status == RUNNING); // but check, just in case | 701 | ASSERT_L( prev_status == RUNNING); // but check, just in case |
@@ -694,22 +703,22 @@ LUAG_FUNC( linda_receive) | |||
694 | ASSERT_L( s->waiting_on == NULL); | 703 | ASSERT_L( s->waiting_on == NULL); |
695 | s->waiting_on = &linda->write_happened; | 704 | s->waiting_on = &linda->write_happened; |
696 | } | 705 | } |
697 | // not enough data to read: wakeup when data was sent, or when timeout is reached | ||
698 | if( !SIGNAL_WAIT( &linda->write_happened, &K->lock_, timeout)) | ||
699 | { | 706 | { |
707 | // not enough data to read: wakeup when data was sent, or when timeout is reached | ||
708 | bool_t const signalled = SIGNAL_WAIT( &linda->write_happened, &K->lock_, timeout); | ||
700 | if( s != NULL) | 709 | if( s != NULL) |
701 | { | 710 | { |
702 | s->waiting_on = NULL; | 711 | s->waiting_on = NULL; |
703 | s->status = prev_status; | 712 | s->status = prev_status; |
704 | // if woken by a cancel request, be sure to handle it properly | 713 | // if a cancel request is pending, be sure to handle it as soon as possible |
705 | cancel = s->cancel_request; | 714 | cancel = s->cancel_request; |
706 | } | 715 | } |
707 | break; | 716 | cancel = (cancel != CANCEL_NONE) ? cancel : linda->simulate_cancel; |
708 | } | 717 | if( !signalled || cancel != CANCEL_NONE) |
709 | if( s != NULL) | 718 | { |
710 | { | 719 | // waiting returned after a timeout, or pending cancel: we are done |
711 | s->waiting_on = NULL; | 720 | break; |
712 | s->status = prev_status; | 721 | } |
713 | } | 722 | } |
714 | } | 723 | } |
715 | } | 724 | } |
@@ -740,7 +749,7 @@ LUAG_FUNC( linda_receive) | |||
740 | 749 | ||
741 | 750 | ||
742 | /* | 751 | /* |
743 | * [true] = linda_set( linda_ud, key_num|str|bool|lightuserdata [, value [, ...]]) | 752 | * [true|lanes.cancel_error] = linda_set( linda_ud, key_num|str|bool|lightuserdata [, value [, ...]]) |
744 | * | 753 | * |
745 | * Set one or more value to Linda. | 754 | * Set one or more value to Linda. |
746 | * TODO: what do we do if we set to non-nil and limit is 0? | 755 | * TODO: what do we do if we set to non-nil and limit is 0? |
@@ -760,28 +769,38 @@ LUAG_FUNC( linda_set) | |||
760 | { | 769 | { |
761 | struct s_Keeper* K = keeper_acquire( linda); | 770 | struct s_Keeper* K = keeper_acquire( linda); |
762 | if( K == NULL) return 0; | 771 | if( K == NULL) return 0; |
763 | if( has_value) | ||
764 | { | ||
765 | // convert nils to some special non-nil sentinel in sent values | ||
766 | keeper_toggle_nil_sentinels( L, 3, eLM_ToKeeper); | ||
767 | } | ||
768 | pushed = keeper_call( K->L, KEEPER_API( set), L, linda, 2); | ||
769 | if( pushed >= 0) // no error? | ||
770 | { | ||
771 | ASSERT_L( pushed == 0 || pushed == 1); | ||
772 | 772 | ||
773 | if( linda->simulate_cancel == CANCEL_NONE) | ||
774 | { | ||
773 | if( has_value) | 775 | if( has_value) |
774 | { | 776 | { |
775 | // we put some data in the slot, tell readers that they should wake | 777 | // convert nils to some special non-nil sentinel in sent values |
776 | SIGNAL_ALL( &linda->write_happened); // To be done from within the 'K' locking area | 778 | keeper_toggle_nil_sentinels( L, 3, eLM_ToKeeper); |
777 | } | 779 | } |
778 | if( pushed == 1) | 780 | pushed = keeper_call( K->L, KEEPER_API( set), L, linda, 2); |
781 | if( pushed >= 0) // no error? | ||
779 | { | 782 | { |
780 | // the key was full, but it is no longer the case, tell writers they should wake | 783 | ASSERT_L( pushed == 0 || pushed == 1); |
781 | ASSERT_L( lua_type( L, -1) == LUA_TBOOLEAN && lua_toboolean( L, -1) == 1); | 784 | |
782 | SIGNAL_ALL( &linda->read_happened); // To be done from within the 'K' locking area | 785 | if( has_value) |
786 | { | ||
787 | // we put some data in the slot, tell readers that they should wake | ||
788 | SIGNAL_ALL( &linda->write_happened); // To be done from within the 'K' locking area | ||
789 | } | ||
790 | if( pushed == 1) | ||
791 | { | ||
792 | // the key was full, but it is no longer the case, tell writers they should wake | ||
793 | ASSERT_L( lua_type( L, -1) == LUA_TBOOLEAN && lua_toboolean( L, -1) == 1); | ||
794 | SIGNAL_ALL( &linda->read_happened); // To be done from within the 'K' locking area | ||
795 | } | ||
783 | } | 796 | } |
784 | } | 797 | } |
798 | else // linda is cancelled | ||
799 | { | ||
800 | // do nothing and return lanes.cancel_error | ||
801 | lua_pushlightuserdata( L, CANCEL_ERROR); | ||
802 | pushed = 1; | ||
803 | } | ||
785 | keeper_release( K); | 804 | keeper_release( K); |
786 | } | 805 | } |
787 | 806 | ||
@@ -837,10 +856,20 @@ LUAG_FUNC( linda_get) | |||
837 | { | 856 | { |
838 | struct s_Keeper* K = keeper_acquire( linda); | 857 | struct s_Keeper* K = keeper_acquire( linda); |
839 | if( K == NULL) return 0; | 858 | if( K == NULL) return 0; |
840 | pushed = keeper_call( K->L, KEEPER_API( get), L, linda, 2); | 859 | |
841 | if( pushed > 0) | 860 | if( linda->simulate_cancel == CANCEL_NONE) |
861 | { | ||
862 | pushed = keeper_call( K->L, KEEPER_API( get), L, linda, 2); | ||
863 | if( pushed > 0) | ||
864 | { | ||
865 | keeper_toggle_nil_sentinels( L, lua_gettop( L) - pushed, eLM_FromKeeper); | ||
866 | } | ||
867 | } | ||
868 | else // linda is cancelled | ||
842 | { | 869 | { |
843 | keeper_toggle_nil_sentinels( L, lua_gettop( L) - pushed, eLM_FromKeeper); | 870 | // do nothing and return lanes.cancel_error |
871 | lua_pushlightuserdata( L, CANCEL_ERROR); | ||
872 | pushed = 1; | ||
844 | } | 873 | } |
845 | keeper_release( K); | 874 | keeper_release( K); |
846 | // must trigger error after keeper state has been released | 875 | // must trigger error after keeper state has been released |
@@ -893,6 +922,59 @@ LUAG_FUNC( linda_limit) | |||
893 | 922 | ||
894 | 923 | ||
895 | /* | 924 | /* |
925 | * (void) = linda_cancel( linda_ud, "read"|"write"|"both"|"none") | ||
926 | * | ||
927 | * Signal linda so that waiting threads wake up as if their own lane was cancelled | ||
928 | */ | ||
929 | LUAG_FUNC( linda_cancel) | ||
930 | { | ||
931 | struct s_Linda* linda = lua_toLinda( L, 1); | ||
932 | char const* who = luaL_checkstring( L, 2); | ||
933 | struct s_Keeper* K; | ||
934 | |||
935 | // make sure we got 3 arguments: the linda, a key and a limit | ||
936 | luaL_argcheck( L, linda, 1, "expected a linda object!"); | ||
937 | luaL_argcheck( L, lua_gettop( L) == 2, 2, "wrong number of arguments"); | ||
938 | |||
939 | // signalling must be done from inside the K locking area | ||
940 | K = keeper_acquire( linda); | ||
941 | if( K == NULL) return 0; | ||
942 | |||
943 | linda->simulate_cancel = CANCEL_SOFT; | ||
944 | if( strcmp( who, "both") == 0) // tell everyone writers to wake up | ||
945 | { | ||
946 | SIGNAL_ALL( &linda->write_happened); | ||
947 | SIGNAL_ALL( &linda->read_happened); | ||
948 | } | ||
949 | else if( strcmp( who, "none") == 0) // reset flag | ||
950 | { | ||
951 | linda->simulate_cancel = CANCEL_NONE; | ||
952 | } | ||
953 | else if( strcmp( who, "read") == 0) // tell blocked readers to wake up | ||
954 | { | ||
955 | SIGNAL_ALL( &linda->write_happened); | ||
956 | } | ||
957 | else if( strcmp( who, "write") == 0) // tell blocked writers to wake up | ||
958 | { | ||
959 | SIGNAL_ALL( &linda->read_happened); | ||
960 | } | ||
961 | else | ||
962 | { | ||
963 | // error ... | ||
964 | linda = NULL; | ||
965 | } | ||
966 | keeper_release( K); | ||
967 | |||
968 | // ... but we must raise it outside the lock | ||
969 | if( !linda) | ||
970 | { | ||
971 | return luaL_error( L, "unknown wake hint '%s'", who); | ||
972 | } | ||
973 | return 0; | ||
974 | } | ||
975 | |||
976 | |||
977 | /* | ||
896 | * lightuserdata= linda_deep( linda_ud ) | 978 | * lightuserdata= linda_deep( linda_ud ) |
897 | * | 979 | * |
898 | * Return the 'deep' userdata pointer, identifying the Linda. | 980 | * Return the 'deep' userdata pointer, identifying the Linda. |
@@ -918,16 +1000,16 @@ LUAG_FUNC( linda_deep ) { | |||
918 | * Useful for concatenation or debugging purposes | 1000 | * Useful for concatenation or debugging purposes |
919 | */ | 1001 | */ |
920 | 1002 | ||
921 | static int linda_tostring( lua_State* L, int _idx, bool_t _opt) | 1003 | static int linda_tostring( lua_State* L, int idx_, bool_t opt_) |
922 | { | 1004 | { |
923 | struct s_Linda* linda = lua_toLinda( L, _idx); | 1005 | struct s_Linda* linda = lua_toLinda( L, idx_); |
924 | if( !_opt) | 1006 | if( !opt_) |
925 | { | 1007 | { |
926 | luaL_argcheck( L, linda, _idx, "expected a linda object!"); | 1008 | luaL_argcheck( L, linda, idx_, "expected a linda object!"); |
927 | } | 1009 | } |
928 | if( linda != NULL) | 1010 | if( linda != NULL) |
929 | { | 1011 | { |
930 | char text[32]; | 1012 | char text[128]; |
931 | int len; | 1013 | int len; |
932 | if( linda->name[0]) | 1014 | if( linda->name[0]) |
933 | len = sprintf( text, "Linda: %.*s", (int)sizeof(text) - 8, linda->name); | 1015 | len = sprintf( text, "Linda: %.*s", (int)sizeof(text) - 8, linda->name); |
@@ -1008,120 +1090,123 @@ LUAG_FUNC( linda_dump) | |||
1008 | * For any other strings, the ID function must not react at all. This allows | 1090 | * For any other strings, the ID function must not react at all. This allows |
1009 | * future extensions of the system. | 1091 | * future extensions of the system. |
1010 | */ | 1092 | */ |
1011 | static void linda_id( lua_State*L, char const * const which) | 1093 | static void linda_id( lua_State* L, char const* const which) |
1012 | { | 1094 | { |
1013 | if (strcmp( which, "new" )==0) | 1095 | if( strcmp( which, "new" ) == 0) |
1014 | { | 1096 | { |
1015 | struct s_Linda *s; | 1097 | struct s_Linda* s; |
1016 | size_t name_len = 0; | 1098 | size_t name_len = 0; |
1017 | char const* linda_name = NULL; | 1099 | char const* linda_name = NULL; |
1018 | int const top = lua_gettop( L); | 1100 | int const top = lua_gettop( L); |
1019 | 1101 | ||
1020 | if( top > 0 && lua_type( L, top) == LUA_TSTRING) | 1102 | if( top > 0 && lua_type( L, top) == LUA_TSTRING) |
1021 | { | 1103 | { |
1022 | linda_name = lua_tostring( L, top); | 1104 | linda_name = lua_tostring( L, top); |
1023 | name_len = strlen( linda_name); | 1105 | name_len = strlen( linda_name); |
1024 | } | 1106 | } |
1025 | 1107 | ||
1026 | /* The deep data is allocated separately of Lua stack; we might no | 1108 | /* The deep data is allocated separately of Lua stack; we might no |
1027 | * longer be around when last reference to it is being released. | 1109 | * longer be around when last reference to it is being released. |
1028 | * One can use any memory allocation scheme. | 1110 | * One can use any memory allocation scheme. |
1029 | */ | 1111 | */ |
1030 | s= (struct s_Linda *) malloc( sizeof(struct s_Linda) + name_len); // terminating 0 is already included | 1112 | s = (struct s_Linda*) malloc( sizeof(struct s_Linda) + name_len); // terminating 0 is already included |
1031 | ASSERT_L(s); | 1113 | ASSERT_L( s); |
1032 | 1114 | ||
1033 | SIGNAL_INIT( &s->read_happened ); | 1115 | SIGNAL_INIT( &s->read_happened); |
1034 | SIGNAL_INIT( &s->write_happened ); | 1116 | SIGNAL_INIT( &s->write_happened); |
1035 | s->name[0] = 0; | 1117 | s->simulate_cancel = CANCEL_NONE; |
1036 | memcpy( s->name, linda_name, name_len ? name_len + 1 : 0); | 1118 | s->name[0] = 0; |
1119 | memcpy( s->name, linda_name, name_len ? name_len + 1 : 0); | ||
1037 | 1120 | ||
1038 | lua_pushlightuserdata( L, s ); | 1121 | lua_pushlightuserdata( L, s); |
1039 | } | 1122 | } |
1040 | else if( strcmp( which, "delete" ) == 0) | 1123 | else if( strcmp( which, "delete") == 0) |
1041 | { | 1124 | { |
1042 | struct s_Keeper* K; | 1125 | struct s_Keeper* K; |
1043 | struct s_Linda* l= lua_touserdata( L, 1); | 1126 | struct s_Linda* l = lua_touserdata( L, 1); |
1044 | ASSERT_L( l); | 1127 | ASSERT_L( l); |
1045 | |||
1046 | /* Clean associated structures in the keeper state. | ||
1047 | */ | ||
1048 | K = keeper_acquire( l); | ||
1049 | if( K && K->L) // can be NULL if this happens during main state shutdown (lanes is GC'ed -> no keepers -> no need to cleanup) | ||
1050 | { | ||
1051 | keeper_call( K->L, KEEPER_API( clear), L, l, 0); | ||
1052 | } | ||
1053 | keeper_release( K); | ||
1054 | |||
1055 | /* There aren't any lanes waiting on these lindas, since all proxies | ||
1056 | * have been gc'ed. Right? | ||
1057 | */ | ||
1058 | SIGNAL_FREE( &l->read_happened); | ||
1059 | SIGNAL_FREE( &l->write_happened); | ||
1060 | free( l); | ||
1061 | } | ||
1062 | else if (strcmp( which, "metatable" )==0) | ||
1063 | { | ||
1064 | 1128 | ||
1065 | STACK_CHECK( L); | 1129 | /* Clean associated structures in the keeper state. |
1066 | lua_newtable(L); | 1130 | */ |
1067 | // metatable is its own index | 1131 | K = keeper_acquire( l); |
1068 | lua_pushvalue( L, -1); | 1132 | if( K && K->L) // can be NULL if this happens during main state shutdown (lanes is GC'ed -> no keepers -> no need to cleanup) |
1069 | lua_setfield( L, -2, "__index"); | 1133 | { |
1134 | keeper_call( K->L, KEEPER_API( clear), L, l, 0); | ||
1135 | } | ||
1136 | keeper_release( K); | ||
1070 | 1137 | ||
1071 | // protect metatable from external access | 1138 | /* There aren't any lanes waiting on these lindas, since all proxies |
1072 | lua_pushliteral( L, "Linda"); | 1139 | * have been gc'ed. Right? |
1073 | lua_setfield( L, -2, "__metatable"); | 1140 | */ |
1141 | SIGNAL_FREE( &l->read_happened); | ||
1142 | SIGNAL_FREE( &l->write_happened); | ||
1143 | free( l); | ||
1144 | } | ||
1145 | else if( strcmp( which, "metatable" ) == 0) | ||
1146 | { | ||
1074 | 1147 | ||
1075 | lua_pushcfunction( L, LG_linda_tostring); | 1148 | STACK_CHECK( L); |
1076 | lua_setfield( L, -2, "__tostring"); | 1149 | lua_newtable( L); |
1150 | // metatable is its own index | ||
1151 | lua_pushvalue( L, -1); | ||
1152 | lua_setfield( L, -2, "__index"); | ||
1077 | 1153 | ||
1078 | // Decoda __towatch support | 1154 | // protect metatable from external access |
1079 | lua_pushcfunction( L, LG_linda_dump); | 1155 | lua_pushliteral( L, "Linda"); |
1080 | lua_setfield( L, -2, "__towatch"); | 1156 | lua_setfield( L, -2, "__metatable"); |
1081 | 1157 | ||
1082 | lua_pushcfunction( L, LG_linda_concat); | 1158 | lua_pushcfunction( L, LG_linda_tostring); |
1083 | lua_setfield( L, -2, "__concat"); | 1159 | lua_setfield( L, -2, "__tostring"); |
1084 | 1160 | ||
1085 | // | 1161 | // Decoda __towatch support |
1086 | // [-1]: linda metatable | 1162 | lua_pushcfunction( L, LG_linda_dump); |
1087 | lua_pushcfunction( L, LG_linda_send ); | 1163 | lua_setfield( L, -2, "__towatch"); |
1088 | lua_setfield( L, -2, "send" ); | ||
1089 | 1164 | ||
1090 | lua_pushcfunction( L, LG_linda_receive ); | 1165 | lua_pushcfunction( L, LG_linda_concat); |
1091 | lua_setfield( L, -2, "receive" ); | 1166 | lua_setfield( L, -2, "__concat"); |
1092 | 1167 | ||
1093 | lua_pushcfunction( L, LG_linda_limit ); | 1168 | // [-1]: linda metatable |
1094 | lua_setfield( L, -2, "limit" ); | 1169 | lua_pushcfunction( L, LG_linda_send); |
1170 | lua_setfield( L, -2, "send"); | ||
1095 | 1171 | ||
1096 | lua_pushcfunction( L, LG_linda_set ); | 1172 | lua_pushcfunction( L, LG_linda_receive); |
1097 | lua_setfield( L, -2, "set" ); | 1173 | lua_setfield( L, -2, "receive"); |
1098 | |||
1099 | lua_pushcfunction( L, LG_linda_count ); | ||
1100 | lua_setfield( L, -2, "count" ); | ||
1101 | |||
1102 | lua_pushcfunction( L, LG_linda_get ); | ||
1103 | lua_setfield( L, -2, "get" ); | ||
1104 | 1174 | ||
1105 | lua_pushcfunction( L, LG_linda_deep ); | 1175 | lua_pushcfunction( L, LG_linda_limit); |
1106 | lua_setfield( L, -2, "deep" ); | 1176 | lua_setfield( L, -2, "limit"); |
1107 | 1177 | ||
1108 | lua_pushcfunction( L, LG_linda_dump); | 1178 | lua_pushcfunction( L, LG_linda_set); |
1109 | lua_setfield( L, -2, "dump" ); | 1179 | lua_setfield( L, -2, "set"); |
1110 | |||
1111 | lua_pushliteral( L, BATCH_SENTINEL); | ||
1112 | lua_setfield(L, -2, "batched"); | ||
1113 | 1180 | ||
1114 | STACK_END( L, 1); | 1181 | lua_pushcfunction( L, LG_linda_count); |
1115 | } | 1182 | lua_setfield( L, -2, "count"); |
1116 | else if( strcmp( which, "module") == 0) | 1183 | |
1117 | { | 1184 | lua_pushcfunction( L, LG_linda_get); |
1118 | // linda is a special case because we know lanes must be loaded from the main lua state | 1185 | lua_setfield( L, -2, "get"); |
1119 | // to be able to ever get here, so we know it will remain loaded as long a the main state is around | 1186 | |
1120 | // in other words, forever. | 1187 | lua_pushcfunction( L, LG_linda_cancel); |
1121 | lua_pushnil( L); | 1188 | lua_setfield( L, -2, "cancel"); |
1122 | // other idfuncs must push a string naming the module they come from | 1189 | |
1123 | //lua_pushliteral( L, "lanes.core"); | 1190 | lua_pushcfunction( L, LG_linda_deep); |
1124 | } | 1191 | lua_setfield( L, -2, "deep"); |
1192 | |||
1193 | lua_pushcfunction( L, LG_linda_dump); | ||
1194 | lua_setfield( L, -2, "dump"); | ||
1195 | |||
1196 | lua_pushliteral( L, BATCH_SENTINEL); | ||
1197 | lua_setfield(L, -2, "batched"); | ||
1198 | |||
1199 | STACK_END( L, 1); | ||
1200 | } | ||
1201 | else if( strcmp( which, "module") == 0) | ||
1202 | { | ||
1203 | // linda is a special case because we know lanes must be loaded from the main lua state | ||
1204 | // to be able to ever get here, so we know it will remain loaded as long a the main state is around | ||
1205 | // in other words, forever. | ||
1206 | lua_pushnil( L); | ||
1207 | // other idfuncs must push a string naming the module they come from | ||
1208 | //lua_pushliteral( L, "lanes.core"); | ||
1209 | } | ||
1125 | } | 1210 | } |
1126 | 1211 | ||
1127 | /* | 1212 | /* |