void ChannelImpl::advanceSendOperation()

in tensorpipe/channel/cuda_gdr/channel_impl.cc [213:280]


void ChannelImpl::advanceSendOperation(
    SendOpIter opIter,
    SendOperation::State prevOpState) {
  TP_DCHECK(context_->inLoop());

  SendOperation& op = *opIter;

  sendOps_.attemptTransition(
      opIter,
      /*from=*/SendOperation::UNINITIALIZED,
      /*to=*/SendOperation::FINISHED,
      /*cond=*/error_ || op.length == 0,
      /*actions=*/{&ChannelImpl::callSendCallback});

  // Needs to go after previous op to ensure predictable and consistent ordering
  // of write calls on the descriptor control connection and read calls on the
  // completion control connection.
  sendOps_.attemptTransition(
      opIter,
      /*from=*/SendOperation::UNINITIALIZED,
      /*to=*/SendOperation::READING_READY_TO_RECEIVE,
      /*cond=*/!error_ && state_ == ESTABLISHED &&
          prevOpState >= SendOperation::READING_READY_TO_RECEIVE,
      /*actions=*/
      {&ChannelImpl::writeDescriptor, &ChannelImpl::readReadyToReceive});

  sendOps_.attemptTransition(
      opIter,
      /*from=*/SendOperation::READING_READY_TO_RECEIVE,
      /*to=*/SendOperation::FINISHED,
      /*cond=*/error_ && op.doneReadingReadyToReceive,
      /*actions=*/{&ChannelImpl::callSendCallback});

  // This doesn't strictly need to go after the previous op, but it doesn't make
  // sense to busy poll multiple events if only one of them is actually able to
  // then make progress.
  sendOps_.attemptTransition(
      opIter,
      /*from=*/SendOperation::READING_READY_TO_RECEIVE,
      /*to=*/SendOperation::WAITING_FOR_CUDA_EVENT,
      /*cond=*/!error_ && op.doneReadingReadyToReceive &&
          prevOpState >= SendOperation::SENDING_OVER_IB,
      /*actions=*/{&ChannelImpl::waitForSendCudaEvent});

  sendOps_.attemptTransition(
      opIter,
      /*from=*/SendOperation::WAITING_FOR_CUDA_EVENT,
      /*to=*/SendOperation::FINISHED,
      /*cond=*/error_ && op.doneWaitingForCudaEvent,
      /*actions=*/{&ChannelImpl::callSendCallback});

  // Needs to go after previous op to ensure predictable and consistent ordering
  // of send calls on InfiniBand queue pair.
  sendOps_.attemptTransition(
      opIter,
      /*from=*/SendOperation::WAITING_FOR_CUDA_EVENT,
      /*to=*/SendOperation::SENDING_OVER_IB,
      /*cond=*/!error_ && op.doneWaitingForCudaEvent &&
          prevOpState >= SendOperation::SENDING_OVER_IB,
      /*actions=*/{&ChannelImpl::sendOverIb});

  sendOps_.attemptTransition(
      opIter,
      /*from=*/SendOperation::SENDING_OVER_IB,
      /*to=*/SendOperation::FINISHED,
      /*cond=*/op.numChunksBeingSent == 0,
      /*actions=*/{&ChannelImpl::callSendCallback});
}