Skip to content

Commit

Permalink
Cancel background work (#3063)
Browse files Browse the repository at this point in the history
* cleanup

* cleanup

* diagnostics

* cleanup diagnostics

* even cleaner diagnostics

* cleanup diagnostics

* default tuning

* adjust tuning, more logging

* add test, fix whitespace

* cancel background steps

* reduce changes
  • Loading branch information
dsyme authored and KevinRansom committed Jul 13, 2017
1 parent b4c4d62 commit f180548
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 73 deletions.
25 changes: 22 additions & 3 deletions src/fsharp/vs/Reactor.fs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type internal IReactorOperations =
[<NoEquality; NoComparison>]
type internal ReactorCommands =
/// Kick off a build.
| SetBackgroundOp of ( (* userOpName: *) string * (* opName: *) string * (* opArg: *) string * (CompilationThreadToken -> bool)) option
| SetBackgroundOp of ( (* userOpName: *) string * (* opName: *) string * (* opArg: *) string * (CompilationThreadToken -> CancellationToken -> bool)) option
/// Do some work not synchronized in the mailbox.
| Op of userOpName: string * opName: string * opArg: string * CancellationToken * (CompilationThreadToken -> unit) * (unit -> unit)
/// Finish the background building
Expand All @@ -39,6 +39,7 @@ type Reactor() =
// so that when the reactor picks up a thread from the threadpool we can set the culture
let culture = new CultureInfo(CultureInfo.CurrentUICulture.Name)

let mutable bgOpCts = new CancellationTokenSource()
/// Mailbox dispatch function.
let builder =
MailboxProcessor<_>.Start <| fun inbox ->
Expand Down Expand Up @@ -74,6 +75,7 @@ type Reactor() =
| Some (SetBackgroundOp bgOpOpt) ->
//Trace.TraceInformation("Reactor: --> set background op, remaining {0}", inbox.CurrentQueueLength)
return! loop (bgOpOpt, onComplete, false)

| Some (Op (userOpName, opName, opArg, ct, op, ccont)) ->
if ct.IsCancellationRequested then ccont() else
Trace.TraceInformation("Reactor: {0:n3} --> {1}.{2} ({3}), remaining {4}", DateTime.Now.TimeOfDay.TotalSeconds, userOpName, opName, opArg, inbox.CurrentQueueLength)
Expand All @@ -92,21 +94,33 @@ type Reactor() =
| None -> ()
| Some (bgUserOpName, bgOpName, bgOpArg, bgOp) ->
Trace.TraceInformation("Reactor: {0:n3} --> wait for background {1}.{2} ({3}), remaining {4}", DateTime.Now.TimeOfDay.TotalSeconds, bgUserOpName, bgOpName, bgOpArg, inbox.CurrentQueueLength)
while bgOp ctok do
bgOpCts.Dispose()
bgOpCts <- new CancellationTokenSource()
while not bgOpCts.IsCancellationRequested && bgOp ctok bgOpCts.Token do
()

if bgOpCts.IsCancellationRequested then
Trace.TraceInformation("FCS: <-- wait for background was cancelled {0}.{1}", bgUserOpName, bgOpName)

channel.Reply(())
return! loop (None, onComplete, false)

| Some (CompleteAllQueuedOps channel) ->
Trace.TraceInformation("Reactor: {0:n3} --> stop background work and complete all queued ops, remaining {1}", DateTime.Now.TimeOfDay.TotalSeconds, inbox.CurrentQueueLength)
return! loop (None, Some channel, false)

| None ->
match bgOpOpt, onComplete with
| _, Some onComplete -> onComplete.Reply()
| Some (bgUserOpName, bgOpName, bgOpArg, bgOp), None ->
Trace.TraceInformation("Reactor: {0:n3} --> background step {1}.{2} ({3})", DateTime.Now.TimeOfDay.TotalSeconds, bgUserOpName, bgOpName, bgOpArg)
let time = Stopwatch()
time.Start()
let res = bgOp ctok
bgOpCts.Dispose()
bgOpCts <- new CancellationTokenSource()
let res = bgOp ctok bgOpCts.Token
if bgOpCts.IsCancellationRequested then
Trace.TraceInformation("FCS: <-- background step {0}.{1}, was cancelled", bgUserOpName, bgOpName)
time.Stop()
let taken = time.Elapsed.TotalMilliseconds
//if span.TotalMilliseconds > 100.0 then
Expand All @@ -126,8 +140,13 @@ type Reactor() =
// [Foreground Mailbox Accessors] -----------------------------------------------------------
member r.SetBackgroundOp(bgOpOpt) =
Trace.TraceInformation("Reactor: {0:n3} enqueue start background, length {1}", DateTime.Now.TimeOfDay.TotalSeconds, builder.CurrentQueueLength)
bgOpCts.Cancel()
builder.Post(SetBackgroundOp bgOpOpt)

member r.CancelBackgroundOp() =
Trace.TraceInformation("FCS: trying to cancel any active background work")
bgOpCts.Cancel()

member r.EnqueueOp(userOpName, opName, opArg, op) =
Trace.TraceInformation("Reactor: {0:n3} enqueue {1}.{2} ({3}), length {4}", DateTime.Now.TimeOfDay.TotalSeconds, userOpName, opName, opArg, builder.CurrentQueueLength)
builder.Post(Op(userOpName, opName, opArg, CancellationToken.None, op, (fun () -> ())))
Expand Down
5 changes: 4 additions & 1 deletion src/fsharp/vs/Reactor.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ type internal Reactor =

/// Set the background building function, which is called repeatedly
/// until it returns 'false'. If None then no background operation is used.
member SetBackgroundOp : ( (* userOpName:*) string * (* opName: *) string * (* opArg: *) string * (CompilationThreadToken -> bool)) option -> unit
member SetBackgroundOp : ( (* userOpName:*) string * (* opName: *) string * (* opArg: *) string * (CompilationThreadToken -> CancellationToken -> bool)) option -> unit

/// Cancel any work being don by the background building function.
member CancelBackgroundOp : unit -> unit

/// Block until the current implicit background build is complete. Unit test only.
member WaitForBackgroundOpCompletion : unit -> unit
Expand Down
Loading

0 comments on commit f180548

Please sign in to comment.