recvCancelable method

(Future<RecvResult<T>>, void Function()) recvCancelable()
inherited

Implementation

@pragma('vm:prefer-inline')
(Future<RecvResult<T>>, void Function()) recvCancelable() {
  if (localRecvChannel case final lc?) return lc.recvCancelable();

  final v0 = buf.tryPop();
  if (v0 != null) {
    return (Future.value(RecvOk<T>(v0)), _noop);
  }
  if (recvDisconnected) {
    return (Future.value(const RecvErrorDisconnected()), _noop);
  }

  final t0 = mx.startRecvTimer();

  final c = buf.addPopWaiter();
  var canceled = false;

  // Double check
  final v1 = buf.tryPop();
  if (v1 != null) {
    buf.removePopWaiter(c);
    return (Future<RecvResult<T>>.value(RecvOk<T>(v1)), _noop);
  }

  final fut = c.future.then<RecvResult<T>>((v2) {
    if (canceled) return const RecvErrorCanceled();
    mx.recvOk(t0);
    return RecvOk<T>(v2);
  }).catchError((Object e) {
    if (e is RecvError) return e;
    return RecvErrorFailed(e);
  });

  @pragma('vm:prefer-inline')
  void cancel() {
    if (canceled) return;
    canceled = true;

    final removed = buf.removePopWaiter(c);
    if (removed) {
      c.completeError(const RecvErrorCanceled());
    }
  }

  return (fut, cancel);
}