Skip to content

Instantly share code, notes, and snippets.

@ChristopherDavenport
Last active December 13, 2019 13:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ChristopherDavenport/f75012bc89a7b7871f56fd14bf906d5f to your computer and use it in GitHub Desktop.
Save ChristopherDavenport/f75012bc89a7b7871f56fd14bf906d5f to your computer and use it in GitHub Desktop.
An Implementation of a Safe Multi-value Race
object RaceN {
import cats.implicits._
import cats.effect._
import cats.effect.concurrent._
import cats.data.NonEmptyList
// Use with atleast 3, otherwise you should prefer Concurrent.race
def raceN[F[_]: Concurrent, A](x1: F[A], x2: F[A], x3: F[A], xs: F[A]*): F[Either[NonEmptyList[Throwable], A]] = {
for {
deferred <- Deferred[F, A]
out <- Bracket[F, Throwable].bracket(
NonEmptyList.of(x1, x2 +: x3 +: xs:_*).traverse(fa =>
Concurrent[F].start(fa.flatMap(a => deferred.complete(a).as(a)).attempt)
)
){
fibers: NonEmptyList[Fiber[F, Either[Throwable, A]]] =>
Concurrent[F].race(
fibers.traverse(_.join).map(
_.traverse(_.swap).swap
),
deferred.get
)
}(
fibers => fibers.traverse_(_.cancel.attempt)
)
} yield out.fold(identity, Either.right)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment