Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend try/finally block to work with awaitable finalizers #4

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions Ply.fs
Original file line number Diff line number Diff line change
Expand Up @@ -279,26 +279,29 @@ module TplPrimitives =
})
with ex -> catch ex

let tryFinally (continuation : unit -> Ply<'u>) (finallyBody : unit -> unit) =
let tryFinally (continuation : unit -> Ply<'u>) (finallyBody : unit -> Ply<unit>) =
let inline withFinally f =
try f()
with ex ->
finallyBody()
throwPreserve ex
let fin = finallyBody()
if fin.IsCompletedSuccessfully then throwPreserve ex else
Ply(await = PlyAwaitable<unit, 'u>(fin.awaitable, fun() -> throwPreserve ex))

let next = withFinally continuation
if next.IsCompletedSuccessfully then
finallyBody()
next
if next.IsCompletedSuccessfully then
let fin = finallyBody()
if fin.IsCompletedSuccessfully then next else
Ply(await = PlyAwaitable<unit, 'u>(fin.awaitable, fun() -> next))
else
let mutable awaitable = next.awaitable
Ply(await = { new Awaitable<'u>() with
override __.Await(csm) = awaitable.Await(&csm)
override this.GetNext() =
let next = withFinally awaitable.GetNext
if next.IsCompletedSuccessfully then
finallyBody()
next
let fin = finallyBody()
if fin.IsCompletedSuccessfully then next else
Ply(await = PlyAwaitable<unit, 'u>(fin.awaitable, fun() -> next))
else
awaitable <- next.awaitable
Ply(await = this)
Expand All @@ -307,7 +310,9 @@ module TplPrimitives =
let using (disposable : #IDisposable) (body : #IDisposable -> Ply<'u>) =
tryFinally
(fun () -> body disposable)
(fun () -> if isNotNull disposable then disposable.Dispose())
(fun () ->
if isNotNull disposable then disposable.Dispose()
zero)

let forLoop (sequence : 'a seq) (body : 'a -> Ply<unit>) =
using (sequence.GetEnumerator()) (fun e -> whileLoop e.MoveNext (fun () -> body e.Current))
Expand Down Expand Up @@ -472,6 +477,6 @@ module TplPrimitives =
member inline __.Combine(ply : Ply<unit>, continuation: unit -> Ply<'t>) = combine ply continuation
member inline __.While(condition : unit -> bool, body : unit -> Ply<unit>) = whileLoop condition body
member inline __.TryWith(body : unit -> Ply<'t>, catch : exn -> Ply<'t>) = tryWith body catch
member inline __.TryFinally(body : unit -> Ply<'t>, finallyBody : unit -> unit) = tryFinally body finallyBody
member inline __.TryFinally(body : unit -> Ply<'t>, finallyBody : unit -> Ply<unit>) = tryFinally body finallyBody
member inline __.Using(disposable : #IDisposable, body : #IDisposable -> Ply<'u>) = using disposable body
member inline __.For(sequence : seq<_>, body : _ -> Ply<unit>) = forLoop sequence body