mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Ractor#close_outgoping cancel Ractor.yield
Ractor#close_outgoing should cancel waiting Ractor.yield. However, yield a value by the Ractor's block should not cancel (to recognize terminating Ractor, introduce rb_ractor_t::yield_atexit flag).
This commit is contained in:
parent
757e185cee
commit
7ad3aff48d
Notes:
git
2020-09-25 00:26:16 +09:00
3 changed files with 22 additions and 9 deletions
|
@ -257,6 +257,7 @@ assert_equal 'ok', %q{
|
||||||
Ractor.recv
|
Ractor.recv
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sleep 0.01 # wait for Ractor.yield in r
|
||||||
r.close_outgoing
|
r.close_outgoing
|
||||||
begin
|
begin
|
||||||
r.take
|
r.take
|
||||||
|
|
29
ractor.c
29
ractor.c
|
@ -1138,6 +1138,7 @@ ractor_close_incoming(rb_execution_context_t *ec, rb_ractor_t *r)
|
||||||
r->incoming_port_closed = true;
|
r->incoming_port_closed = true;
|
||||||
if (ractor_wakeup(r, wait_recving, wakeup_by_close)) {
|
if (ractor_wakeup(r, wait_recving, wakeup_by_close)) {
|
||||||
VM_ASSERT(r->incoming_queue.cnt == 0);
|
VM_ASSERT(r->incoming_queue.cnt == 0);
|
||||||
|
RUBY_DEBUG_LOG("cancel receiving", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1149,15 +1150,15 @@ ractor_close_incoming(rb_execution_context_t *ec, rb_ractor_t *r)
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
ractor_close_outgoing(rb_execution_context_t *ec, rb_ractor_t *cr)
|
ractor_close_outgoing(rb_execution_context_t *ec, rb_ractor_t *r)
|
||||||
{
|
{
|
||||||
VALUE prev;
|
VALUE prev;
|
||||||
|
|
||||||
RACTOR_LOCK(cr);
|
RACTOR_LOCK(r);
|
||||||
{
|
{
|
||||||
if (!cr->outgoing_port_closed) {
|
if (!r->outgoing_port_closed) {
|
||||||
prev = Qfalse;
|
prev = Qfalse;
|
||||||
cr->outgoing_port_closed = true;
|
r->outgoing_port_closed = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
prev = Qtrue;
|
prev = Qtrue;
|
||||||
|
@ -1165,13 +1166,21 @@ ractor_close_outgoing(rb_execution_context_t *ec, rb_ractor_t *cr)
|
||||||
|
|
||||||
// wakeup all taking ractors
|
// wakeup all taking ractors
|
||||||
rb_ractor_t *taking_ractor;
|
rb_ractor_t *taking_ractor;
|
||||||
while ((taking_ractor = ractor_waiting_list_shift(cr, &cr->taking_ractors)) != NULL) {
|
bp();
|
||||||
|
while ((taking_ractor = ractor_waiting_list_shift(r, &r->taking_ractors)) != NULL) {
|
||||||
|
rp(taking_ractor->self);
|
||||||
RACTOR_LOCK(taking_ractor);
|
RACTOR_LOCK(taking_ractor);
|
||||||
ractor_wakeup(taking_ractor, wait_taking, wakeup_by_close);
|
ractor_wakeup(taking_ractor, wait_taking, wakeup_by_close);
|
||||||
RACTOR_UNLOCK(taking_ractor);
|
RACTOR_UNLOCK(taking_ractor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// raising yielding Ractor
|
||||||
|
if (!r->yield_atexit &&
|
||||||
|
ractor_wakeup(r, wait_yielding, wakeup_by_close)) {
|
||||||
|
RUBY_DEBUG_LOG("cancel yielding", 0);
|
||||||
}
|
}
|
||||||
RACTOR_UNLOCK(cr);
|
}
|
||||||
|
RACTOR_UNLOCK(r);
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1362,7 +1371,7 @@ ractor_create(rb_execution_context_t *ec, VALUE self, VALUE loc, VALUE name, VAL
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ractor_atexit_yield(rb_execution_context_t *ec, rb_ractor_t *cr, VALUE v, bool exc)
|
ractor_yield_atexit(rb_execution_context_t *ec, rb_ractor_t *cr, VALUE v, bool exc)
|
||||||
{
|
{
|
||||||
ASSERT_ractor_unlocking(cr);
|
ASSERT_ractor_unlocking(cr);
|
||||||
|
|
||||||
|
@ -1382,6 +1391,8 @@ ractor_atexit_yield(rb_execution_context_t *ec, rb_ractor_t *cr, VALUE v, bool e
|
||||||
|
|
||||||
VM_ASSERT(cr->wait.status == wait_none);
|
VM_ASSERT(cr->wait.status == wait_none);
|
||||||
cr->wait.status = wait_yielding;
|
cr->wait.status = wait_yielding;
|
||||||
|
VM_ASSERT(cr->yield_atexit == false);
|
||||||
|
cr->yield_atexit = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
retry = true; // another ractor is waiting for the yield.
|
retry = true; // another ractor is waiting for the yield.
|
||||||
|
@ -1413,14 +1424,14 @@ void
|
||||||
rb_ractor_atexit(rb_execution_context_t *ec, VALUE result)
|
rb_ractor_atexit(rb_execution_context_t *ec, VALUE result)
|
||||||
{
|
{
|
||||||
rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
|
rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
|
||||||
ractor_atexit_yield(ec, cr, result, false);
|
ractor_yield_atexit(ec, cr, result, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_ractor_atexit_exception(rb_execution_context_t *ec)
|
rb_ractor_atexit_exception(rb_execution_context_t *ec)
|
||||||
{
|
{
|
||||||
rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
|
rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
|
||||||
ractor_atexit_yield(ec, cr, ec->errinfo, true);
|
ractor_yield_atexit(ec, cr, ec->errinfo, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
1
ractor.h
1
ractor.h
|
@ -47,6 +47,7 @@ struct rb_ractor_struct {
|
||||||
|
|
||||||
bool incoming_port_closed;
|
bool incoming_port_closed;
|
||||||
bool outgoing_port_closed;
|
bool outgoing_port_closed;
|
||||||
|
bool yield_atexit;
|
||||||
|
|
||||||
struct rb_ractor_waiting_list taking_ractors;
|
struct rb_ractor_waiting_list taking_ractors;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue