@@ -916,7 +916,7 @@ static VALUE ractor_move(VALUE obj); // in this file
916
916
static VALUE ractor_copy (VALUE obj ); // in this file
917
917
918
918
static void
919
- ractor_basket_setup (rb_execution_context_t * ec , struct rb_ractor_basket * basket , VALUE obj , VALUE move , bool exc , bool is_will )
919
+ ractor_basket_setup (rb_execution_context_t * ec , struct rb_ractor_basket * basket , VALUE obj , VALUE move , bool exc , bool is_will , bool is_yield )
920
920
{
921
921
basket -> sender = rb_ec_ractor_ptr (ec )-> pub .self ;
922
922
basket -> exception = exc ;
@@ -935,15 +935,21 @@ ractor_basket_setup(rb_execution_context_t *ec, struct rb_ractor_basket *basket,
935
935
}
936
936
else {
937
937
basket -> type = basket_type_move ;
938
- basket -> v = ractor_move (obj );
938
+
939
+ if (is_yield ) {
940
+ basket -> v = obj ; // call ractor_move() when yielding timing.
941
+ }
942
+ else {
943
+ basket -> v = ractor_move (obj );
944
+ }
939
945
}
940
946
}
941
947
942
948
static VALUE
943
949
ractor_send (rb_execution_context_t * ec , rb_ractor_t * r , VALUE obj , VALUE move )
944
950
{
945
951
struct rb_ractor_basket basket ;
946
- ractor_basket_setup (ec , & basket , obj , move , false, false);
952
+ ractor_basket_setup (ec , & basket , obj , move , false, false, false );
947
953
ractor_send_basket (ec , r , & basket );
948
954
return r -> pub .self ;
949
955
}
@@ -958,17 +964,23 @@ ractor_try_take(rb_execution_context_t *ec, rb_ractor_t *r)
958
964
959
965
RACTOR_LOCK (r );
960
966
{
961
- if (ractor_wakeup (r , wait_yielding , wakeup_by_take )) {
967
+ if (ractor_sleeping_by (r , wait_yielding )) {
968
+ MAYBE_UNUSED (bool ) wakeup_result ;
962
969
VM_ASSERT (r -> sync .wait .yielded_basket .type != basket_type_none );
963
- basket = r -> sync .wait .yielded_basket ;
964
- ractor_basket_clear (& r -> sync .wait .yielded_basket );
970
+
971
+ if (r -> sync .wait .yielded_basket .type == basket_type_move ) {
972
+ wakeup_result = ractor_wakeup (r , wait_yielding , wakeup_by_retry );
973
+ }
974
+ else {
975
+ wakeup_result = ractor_wakeup (r , wait_yielding , wakeup_by_take );
976
+ basket = r -> sync .wait .yielded_basket ;
977
+ ractor_basket_clear (& r -> sync .wait .yielded_basket );
978
+ }
979
+ VM_ASSERT (wakeup_result );
965
980
}
966
981
else if (r -> sync .outgoing_port_closed ) {
967
982
closed = true;
968
983
}
969
- else {
970
- // not reached.
971
- }
972
984
}
973
985
RACTOR_UNLOCK (r );
974
986
@@ -985,6 +997,12 @@ ractor_try_take(rb_execution_context_t *ec, rb_ractor_t *r)
985
997
}
986
998
}
987
999
1000
+ static VALUE
1001
+ ractor_yield_move_body (VALUE v )
1002
+ {
1003
+ return ractor_move (v );
1004
+ }
1005
+
988
1006
static bool
989
1007
ractor_try_yield (rb_execution_context_t * ec , rb_ractor_t * cr , struct rb_ractor_basket * basket )
990
1008
{
@@ -1009,8 +1027,34 @@ ractor_try_yield(rb_execution_context_t *ec, rb_ractor_t *cr, struct rb_ractor_b
1009
1027
1010
1028
RACTOR_LOCK (r );
1011
1029
{
1012
- if (ractor_wakeup (r , wait_taking , wakeup_by_yield )) {
1030
+ if (ractor_sleeping_by (r , wait_taking )) {
1013
1031
VM_ASSERT (r -> sync .wait .taken_basket .type == basket_type_none );
1032
+
1033
+ if (basket -> type == basket_type_move ) {
1034
+ enum ractor_wait_status prev_wait_status = r -> sync .wait .status ;
1035
+ r -> sync .wait .status = wait_moving ;
1036
+
1037
+ RACTOR_UNLOCK (r );
1038
+ {
1039
+ int state ;
1040
+ VALUE moved_value = rb_protect (ractor_yield_move_body , basket -> v , & state );
1041
+ if (state ) {
1042
+ r -> sync .wait .status = prev_wait_status ;
1043
+ rb_jump_tag (state );
1044
+ }
1045
+ else {
1046
+ basket -> v = moved_value ;
1047
+ }
1048
+ }
1049
+ RACTOR_LOCK (r );
1050
+
1051
+ if (!ractor_wakeup (r , wait_moving , wakeup_by_yield )) {
1052
+ // terminating?
1053
+ }
1054
+ }
1055
+ else {
1056
+ ractor_wakeup (r , wait_taking , wakeup_by_yield );
1057
+ }
1014
1058
r -> sync .wait .taken_basket = * basket ;
1015
1059
}
1016
1060
else {
@@ -1080,16 +1124,15 @@ ractor_select(rb_execution_context_t *ec, const VALUE *rs, const int rs_len, VAL
1080
1124
}
1081
1125
rs = NULL ;
1082
1126
1127
+ restart :
1128
+
1083
1129
if (yield_p ) {
1084
1130
actions [rs_len ].type = ractor_select_action_yield ;
1085
1131
actions [rs_len ].v = Qundef ;
1086
1132
wait_status |= wait_yielding ;
1087
-
1088
- ractor_basket_setup (ec , & cr -> sync .wait .yielded_basket , yielded_value , move , false, false);
1133
+ ractor_basket_setup (ec , & cr -> sync .wait .yielded_basket , yielded_value , move , false, false, true);
1089
1134
}
1090
1135
1091
- restart :
1092
-
1093
1136
// TODO: shuffle actions
1094
1137
1095
1138
while (1 ) {
@@ -1580,7 +1623,7 @@ ractor_yield_atexit(rb_execution_context_t *ec, rb_ractor_t *cr, VALUE v, bool e
1580
1623
ASSERT_ractor_unlocking (cr );
1581
1624
1582
1625
struct rb_ractor_basket basket ;
1583
- ractor_basket_setup (ec , & basket , v , Qfalse , exc , true);
1626
+ ractor_basket_setup (ec , & basket , v , Qfalse , exc , true, true /* this flag is ignored because move is Qfalse */ );
1584
1627
1585
1628
retry :
1586
1629
if (ractor_try_yield (ec , cr , & basket )) {
0 commit comments