Skip to content

Instantly share code, notes, and snippets.

@djspiewak
Created November 8, 2020 17:36
Show Gist options
  • Select an option

  • Save djspiewak/c7db922fc70b68308d01e59e4369fb7a to your computer and use it in GitHub Desktop.

Select an option

Save djspiewak/c7db922fc70b68308d01e59e4369fb7a to your computer and use it in GitHub Desktop.
def racePair[F[_]: Concurrent, A, B](fa: F[A], fb: F[B]): F[Either[(Outcome[F, E, A], Fiber[F, E, B]), (Fiber[F, E, A], Outcome[F, E, B])]] =
MonadCancel[F] uncancelable { poll =>
for {
fibADef <- Concurrent[F].deferred[Fiber[F, E, A]]
fibBDef <- Concurrent[F].deferred[Fiber[F, E, B]]
result <- Concurrent[F].deferred[Either[(Outcome[F, E, A], Fiber[F, E, B]), (Fiber[F, E, A], Outcome[F, E, B])]]
fibA <- fa guarantee { oc =>
fibBDef.get flatMap { fibB =>
result.complete(Left((oc, fibB))).void
}
}
fibB <- fb guarantee { oc =>
fibADef.get flatMap { fibA =>
result.complete(Right((fibA, oc))).void
}
}
_ <- fibADef.complete(fibA)
_ <- fibBDef.complete(fibB)
back <- poll(result.get) onCancel {
for {
done <- Concurrent[F].deferred[Unit]
_ <- fibA.cancel.guarantee(_ => done.complete(()))
_ <- fibB.cancel.guarantee(_ => done.complete(()))
_ <- done.get
} yield ()
}
} yield back
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment