diff options
Diffstat (limited to 'ractor.c')
-rw-r--r-- | ractor.c | 78 |
1 files changed, 60 insertions, 18 deletions
@@ -917,7 +917,7 @@ static VALUE ractor_move(VALUE obj); // in this file static VALUE ractor_copy(VALUE obj); // in this file static void -ractor_basket_setup(rb_execution_context_t *ec, struct rb_ractor_basket *basket, VALUE obj, VALUE move, bool exc, bool is_will) +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) { basket->sender = rb_ec_ractor_ptr(ec)->pub.self; basket->exception = exc; @@ -936,7 +936,13 @@ ractor_basket_setup(rb_execution_context_t *ec, struct rb_ractor_basket *basket, } else { basket->type = basket_type_move; - basket->v = ractor_move(obj); + + if (is_yield) { + basket->v = obj; // call ractor_move() when yielding timing. + } + else { + basket->v = ractor_move(obj); + } } } @@ -944,7 +950,7 @@ static VALUE ractor_send(rb_execution_context_t *ec, rb_ractor_t *r, VALUE obj, VALUE move) { struct rb_ractor_basket basket; - ractor_basket_setup(ec, &basket, obj, move, false, false); + ractor_basket_setup(ec, &basket, obj, move, false, false, false); ractor_send_basket(ec, r, &basket); return r->pub.self; } @@ -959,17 +965,23 @@ ractor_try_take(rb_execution_context_t *ec, rb_ractor_t *r) RACTOR_LOCK(r); { - if (ractor_wakeup(r, wait_yielding, wakeup_by_take)) { + if (ractor_sleeping_by(r, wait_yielding)) { + MAYBE_UNUSED(bool) wakeup_result; VM_ASSERT(r->sync.wait.yielded_basket.type != basket_type_none); - basket = r->sync.wait.yielded_basket; - ractor_basket_clear(&r->sync.wait.yielded_basket); + + if (r->sync.wait.yielded_basket.type == basket_type_move) { + wakeup_result = ractor_wakeup(r, wait_yielding, wakeup_by_retry); + } + else { + wakeup_result = ractor_wakeup(r, wait_yielding, wakeup_by_take); + basket = r->sync.wait.yielded_basket; + ractor_basket_clear(&r->sync.wait.yielded_basket); + } + VM_ASSERT(wakeup_result); } else if (r->sync.outgoing_port_closed) { closed = true; } - else { - // not reached. - } } RACTOR_UNLOCK(r); @@ -986,6 +998,12 @@ ractor_try_take(rb_execution_context_t *ec, rb_ractor_t *r) } } +static VALUE +ractor_yield_move_body(VALUE v) +{ + return ractor_move(v); +} + static bool ractor_try_yield(rb_execution_context_t *ec, rb_ractor_t *cr, struct rb_ractor_basket *basket) { @@ -1010,8 +1028,34 @@ ractor_try_yield(rb_execution_context_t *ec, rb_ractor_t *cr, struct rb_ractor_b RACTOR_LOCK(r); { - if (ractor_wakeup(r, wait_taking, wakeup_by_yield)) { + if (ractor_sleeping_by(r, wait_taking)) { VM_ASSERT(r->sync.wait.taken_basket.type == basket_type_none); + + if (basket->type == basket_type_move) { + enum ractor_wait_status prev_wait_status = r->sync.wait.status; + r->sync.wait.status = wait_moving; + + RACTOR_UNLOCK(r); + { + int state; + VALUE moved_value = rb_protect(ractor_yield_move_body, basket->v, &state); + if (state) { + r->sync.wait.status = prev_wait_status; + rb_jump_tag(state); + } + else { + basket->v = moved_value; + } + } + RACTOR_LOCK(r); + + if (!ractor_wakeup(r, wait_moving, wakeup_by_yield)) { + // terminating? + } + } + else { + ractor_wakeup(r, wait_taking, wakeup_by_yield); + } r->sync.wait.taken_basket = *basket; } else { @@ -1036,7 +1080,7 @@ ractor_try_yield(rb_execution_context_t *ec, rb_ractor_t *cr, struct rb_ractor_b // select(r1, r2, r3, receive: true, yield: obj) static VALUE -ractor_select(rb_execution_context_t *ec, const VALUE *rs, int alen, VALUE yielded_value, bool move, VALUE *ret_r) +ractor_select(rb_execution_context_t *ec, const VALUE *rs, const int rs_len, VALUE yielded_value, bool move, VALUE *ret_r) { rb_ractor_t *cr = rb_ec_ractor_ptr(ec); VALUE crv = cr->pub.self; @@ -1045,7 +1089,7 @@ ractor_select(rb_execution_context_t *ec, const VALUE *rs, int alen, VALUE yield bool interrupted = false; enum ractor_wait_status wait_status = 0; bool yield_p = (yielded_value != Qundef) ? true : false; - const int rs_len = alen; + const int alen = rs_len + (yield_p ? 1 : 0); struct ractor_select_action { enum ractor_select_action_type { @@ -1054,7 +1098,7 @@ ractor_select(rb_execution_context_t *ec, const VALUE *rs, int alen, VALUE yield ractor_select_action_yield, } type; VALUE v; - } *actions = ALLOCA_N(struct ractor_select_action, alen + (yield_p ? 1 : 0)); + } *actions = ALLOCA_N(struct ractor_select_action, alen); VM_ASSERT(cr->sync.wait.status == wait_none); VM_ASSERT(cr->sync.wait.wakeup_status == wakeup_none); @@ -1062,7 +1106,7 @@ ractor_select(rb_execution_context_t *ec, const VALUE *rs, int alen, VALUE yield VM_ASSERT(cr->sync.wait.yielded_basket.type == basket_type_none); // setup actions - for (i=0; i<alen; i++) { + for (i=0; i<rs_len; i++) { VALUE v = rs[i]; if (v == crv) { @@ -1087,9 +1131,7 @@ ractor_select(rb_execution_context_t *ec, const VALUE *rs, int alen, VALUE yield actions[rs_len].type = ractor_select_action_yield; actions[rs_len].v = Qundef; wait_status |= wait_yielding; - alen++; - - ractor_basket_setup(ec, &cr->sync.wait.yielded_basket, yielded_value, move, false, false); + ractor_basket_setup(ec, &cr->sync.wait.yielded_basket, yielded_value, move, false, false, true); } // TODO: shuffle actions @@ -1576,7 +1618,7 @@ ractor_yield_atexit(rb_execution_context_t *ec, rb_ractor_t *cr, VALUE v, bool e ASSERT_ractor_unlocking(cr); struct rb_ractor_basket basket; - ractor_basket_setup(ec, &basket, v, Qfalse, exc, true); + ractor_basket_setup(ec, &basket, v, Qfalse, exc, true, true /* this flag is ignored because move is Qfalse */); retry: if (ractor_try_yield(ec, cr, &basket)) { |