55namespace FSharpx.Control
66open System
77open System.Threading
8+ open System.Threading .Tasks
89
910// ----------------------------------------------------------------------------
1011
@@ -92,4 +93,25 @@ module AsyncExtensions =
9293 static member bindChoices ( f : 'a -> Async < Choice < 'b , 'e2 >>) ( a : Async < Choice < 'a , 'e1 >>) : Async < Choice < 'b , Choice < 'e1 , 'e2 >>> =
9394 a |> Async.bind ( function
9495 | Choice1Of2 a' -> f a' |> Async.map ( function Choice1Of2 b -> Choice1Of2 b | Choice2Of2 e2 -> Choice2Of2 ( Choice2Of2 e2))
95- | Choice2Of2 e1 -> Choice2Of2 ( Choice1Of2 e1) |> async.Return)
96+ | Choice2Of2 e1 -> Choice2Of2 ( Choice1Of2 e1) |> async.Return)
97+
98+ /// Creates a computation which produces a tuple consiting of the value produces by the first
99+ /// argument computation to complete and a handle to the other computation. The second computation
100+ /// to complete is memoized.
101+ static member internal chooseBoth ( a : Async < 'a >) ( b : Async < 'a >) : Async < 'a * Async < 'a >> =
102+ Async.FromContinuations <| fun ( ok , err , cnc ) ->
103+ let state = ref 0
104+ let tcs = TaskCompletionSource< 'a>()
105+ let inline ok a =
106+ if ( Interlocked.CompareExchange( state, 1 , 0 ) = 0 ) then
107+ ok ( a, tcs.Task |> Async.AwaitTask)
108+ else
109+ tcs.SetResult a
110+ let inline err ( ex : exn ) =
111+ if ( Interlocked.CompareExchange( state, 1 , 0 ) = 0 ) then err ex
112+ else tcs.SetException ex
113+ let inline cnc ex =
114+ if ( Interlocked.CompareExchange( state, 1 , 0 ) = 0 ) then cnc ex
115+ else tcs.SetCanceled()
116+ Async.StartWithContinuations( a, ok, err, cnc)
117+ Async.StartWithContinuations( b, ok, err, cnc)
0 commit comments