Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf9e67ae

Browse files
dsymeKevinRansom
authored andcommitted
Make transitive builder cancellation explicit (dotnet#2460)
* make transitive project cancellation explicit* fix build* add time stamp cache* updates to avoid work items* add time stamp cache (2)* avoid duplicate cancellation check (cancellation is implicit on bind of cancellable)* add time stamp cache (4)* fix build (6)* add debug output
1 parente1b9479 commitf9e67ae

File tree

13 files changed

+719
-487
lines changed

13 files changed

+719
-487
lines changed

‎src/absil/illib.fs‎

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,7 @@ type ResultOrException<'TResult> =
505505
moduleResultOrException=
506506

507507
letsuccess a= Result a
508+
508509
letraze(b:exn)= Exception b
509510

510511
// map
@@ -523,6 +524,124 @@ module ResultOrException =
523524
| Result x-> success x
524525
| Exception_err-> f()
525526

527+
[<RequireQualifiedAccess>]
528+
typeValueOrCancelled<'TResult>=
529+
| Valueof'TResult
530+
| CancelledofOperationCanceledException
531+
532+
/// Represents a cancellable computation with explicit representation of a cancelled result.
533+
///
534+
/// A cancellable computation is passed may be cancelled via a CancellationToken, which is propagated implicitly.
535+
/// If cancellation occurs, it is propagated as data rather than by raising an OperationCancelledException.
536+
typeCancellable<'TResult>= Cancellableof(System.Threading.CancellationToken->ValueOrCancelled<'TResult>)
537+
538+
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
539+
moduleCancellable=
540+
541+
/// Bind the result of a cancellable computation
542+
letbind f(Cancellable f1)=
543+
Cancellable(fun ct->
544+
if ct.IsCancellationRequestedthen
545+
ValueOrCancelled.Cancelled(OperationCanceledException())
546+
else
547+
match f1 ctwith
548+
| ValueOrCancelled.Value res1->
549+
if ct.IsCancellationRequestedthen
550+
ValueOrCancelled.Cancelled(OperationCanceledException())
551+
else
552+
let(Cancellable f2)= f res1
553+
f2 ct
554+
| ValueOrCancelled.Cancelled err1->
555+
ValueOrCancelled.Cancelled err1)
556+
557+
/// Map the result of a cancellable computation
558+
letmap f(Cancellable f1)=
559+
Cancellable(fun ct->
560+
match f1 ctwith
561+
| ValueOrCancelled.Value res1-> ValueOrCancelled.Value(f res1)
562+
| ValueOrCancelled.Cancelled err1-> ValueOrCancelled.Cancelled err1)
563+
564+
/// Return a simple value as the result of a cancellable computation
565+
letret x= Cancellable(fun _-> ValueOrCancelled.Value x)
566+
567+
/// Fold a cancellable computation along a sequence of inputs
568+
letfold f acc seq=
569+
(ret acc,seq)||> Seq.fold(fun acc x-> acc|> bind(fun acc-> f acc x))
570+
571+
/// Iterate a cancellable computation over a collection
572+
leteach f seq=
573+
([],seq)||> fold(fun acc x-> f x|> map(fun x2-> x2::acc))|> map List.rev
574+
575+
/// Delay a cancellable computation
576+
letdelay(f:unit->Cancellable<'T>)= Cancellable(fun ct->let(Cancellable g)= f()in g ct)
577+
578+
/// Run a cancellable computation using the given cancellation token
579+
letrun ct(Cancellable f)= f ct
580+
581+
/// Run the computation in a mode where it may not be cancelled. The computation never results in a
582+
/// ValueOrCancelled.Cancelled.
583+
letrunWithoutCancellation comp=
584+
letres= run System.Threading.CancellationToken.None comp
585+
match reswith
586+
| ValueOrCancelled.Cancelled_-> failwith"unexpected cancellation"
587+
| ValueOrCancelled.Value r-> r
588+
589+
/// Bind the cancellation token associated with the computation
590+
lettoken()= Cancellable(fun ct-> ValueOrCancelled.Value ct)
591+
592+
/// Represents a canceled computation
593+
letcanceled()= Cancellable(fun _-> ValueOrCancelled.Cancelled(new OperationCanceledException()))
594+
595+
/// Catch exceptions in a computation
596+
letprivatecatch(Cancellable e)=
597+
Cancellable(fun ct->
598+
try
599+
match e ctwith
600+
| ValueOrCancelled.Value r-> ValueOrCancelled.Value(Choice1Of2 r)
601+
| ValueOrCancelled.Cancelled e-> ValueOrCancelled.Cancelled e
602+
with err->
603+
ValueOrCancelled.Value(Choice2Of2 err))
604+
605+
/// Implement try/finally for a cancellable computation
606+
lettryFinally e compensation=
607+
catch e|> bind(fun res->
608+
compensation();
609+
match reswith Choice1Of2 r-> ret r| Choice2Of2 err-> raise err)
610+
611+
/// Implement try/with for a cancellable computation
612+
lettryWith e handler=
613+
catch e|> bind(fun res->
614+
match reswith Choice1Of2 r-> ret r| Choice2Of2 err-> handler err)
615+
616+
// /// Run the cancellable computation within an Async computation. This isn't actaully used in the codebase, but left
617+
// here in case we need it in the future
618+
//
619+
// let toAsync e =
620+
// async {
621+
// let! ct = Async.CancellationToken
622+
// return!
623+
// Async.FromContinuations(fun (cont, econt, ccont) ->
624+
// // Run the computation synchronously using the given cancellation token
625+
// let res = try Choice1Of2 (run ct e) with err -> Choice2Of2 err
626+
// match res with
627+
// | Choice1Of2 (ValueOrCancelled.Value v) -> cont v
628+
// | Choice1Of2 (ValueOrCancelled.Cancelled err) -> ccont err
629+
// | Choice2Of2 err -> econt err)
630+
// }
631+
632+
typeCancellableBuilder()=
633+
memberx.Bind(e,k)= Cancellable.bind k e
634+
memberx.Return(v)= Cancellable.ret v
635+
memberx.ReturnFrom(v)= v
636+
memberx.Combine(e1,e2)= e1|> Cancellable.bind(fun()-> e2)
637+
memberx.TryWith(e,handler)= Cancellable.tryWith e handler
638+
memberx.Using(resource,e)= Cancellable.tryFinally(e resource)(fun()->(resource:> System.IDisposable).Dispose())
639+
memberx.TryFinally(e,compensation)= Cancellable.tryFinally e compensation
640+
memberx.Delay(f)= Cancellable.delay f
641+
memberx.Zero()= Cancellable.ret()
642+
643+
letcancellable= CancellableBuilder()
644+
526645
/// Computations that can cooperatively yield by returning a continuation
527646
///
528647
/// - Any yield of a NotYetDone should typically be "abandonable" without adverse consequences. No resource release
@@ -533,6 +652,8 @@ module ResultOrException =
533652
///
534653
/// - The key thing is that you can take an Eventually value and run it with
535654
/// Eventually.repeatedlyProgressUntilDoneOrTimeShareOverOrCanceled
655+
///
656+
/// - Cancellation results in a suspended computation rather than complete abandonment
536657
typeEventually<'T>=
537658
| Doneof'T
538659
| NotYetDoneof(CompilationThreadToken->Eventually<'T>)
@@ -559,6 +680,8 @@ module Eventually =
559680

560681
/// Keep running the computation bit by bit until a time limit is reached.
561682
/// The runner gets called each time the computation is restarted
683+
///
684+
/// If cancellation happens, the operation is left half-complete, ready to resume.
562685
letrepeatedlyProgressUntilDoneOrTimeShareOverOrCanceled timeShareInMilliseconds(ct:CancellationToken)runner e=
563686
letsw=new System.Diagnostics.Stopwatch()
564687
let recrunTimeShare ctok e=
@@ -578,7 +701,7 @@ module Eventually =
578701
NotYetDone(fun ctok-> runTimeShare ctok e)
579702

580703
/// Keep running the asynchronous computation bit by bit. The runner gets called each time the computation is restarted.
581-
/// Can be cancelled in the normal way.
704+
/// Can be cancelledas an Asyncin the normal way.
582705
letforceAsync(runner:(CompilationThreadToken-> Eventually<'T>)->Async<Eventually<'T>>)(e:Eventually<'T>):Async<'Toption>=
583706
let recloop(e:Eventually<'T>)=
584707
async{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp