void ChannelObject::send(gc<Fiber> sender, gc<Object> value) { // TODO(bob): What if the channel is closed? // If we have a receiver, give it the value. if (receivers_.count() > 0) { gc<Fiber> receiver = receivers_.removeAt(0); receiver->storeReturn(value); receiver->ready(); // Add the sender back to the scheduler too since it isn't blocked. sender->ready(); return; } // Otherwise, stuff the value and suspend. sender->waitToSend(value); senders_.add(sender); return; }
bool ChannelObject::close(VM& vm, gc<Fiber> sender) { if (!isOpen_) return false; isOpen_ = false; // If nothing is going to receive the "done". Just ignore it and close // immediately. if (receivers_.count() == 0) return false; // Send "done" to all of the receivers. for (int i = 0; i < receivers_.count(); i++) { receivers_[i]->storeReturn(vm.getAtom(ATOM_DONE)); receivers_[i]->ready(); } receivers_.clear(); // Add the sender back to the scheduler after the receiver so it can // continue. sender->ready(); return true; }