Skip to content

Commit e08be38

Browse files
committed
concurrent logger
1 parent 8e15d57 commit e08be38

File tree

2 files changed

+53
-3
lines changed

2 files changed

+53
-3
lines changed

src/Compiler/Facilities/DiagnosticsLogger.fs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,31 @@ type CapturingDiagnosticsLogger(nm, ?eagerFormat) =
375375
let errors = diagnostics.ToArray()
376376
errors |> Array.iter diagnosticsLogger.DiagnosticSink
377377

378+
type ConcurrentCapturingDiagnosticsLogger(nm, ?eagerFormat) =
379+
inherit DiagnosticsLogger(nm)
380+
let mutable errorCount = 0
381+
let diagnostics = System.Collections.Concurrent.ConcurrentQueue()
382+
383+
override _.DiagnosticSink(diagnostic, severity) =
384+
let diagnostic =
385+
match eagerFormat with
386+
| None -> diagnostic
387+
| Some f -> f diagnostic
388+
389+
if severity = FSharpDiagnosticSeverity.Error then
390+
Interlocked.Increment &errorCount |> ignore
391+
392+
diagnostics.Enqueue(diagnostic, severity)
393+
394+
override _.ErrorCount = errorCount
395+
396+
member _.Diagnostics = diagnostics |> Seq.toList
397+
398+
member _.CommitDelayedDiagnostics(diagnosticsLogger: DiagnosticsLogger) =
399+
// Eagerly grab all the errors and warnings from the mutable collection
400+
let errors = diagnostics.ToArray()
401+
errors |> Array.iter diagnosticsLogger.DiagnosticSink
402+
378403
/// Type holds thread-static globals for use by the compiler.
379404
type DiagnosticsThreadStatics =
380405
static let buildPhase = new AsyncLocal<BuildPhase>()
@@ -517,6 +542,17 @@ let UseTransformedDiagnosticsLogger (transformer: DiagnosticsLogger -> #Diagnost
517542
let UseDiagnosticsLogger newLogger =
518543
UseTransformedDiagnosticsLogger(fun _ -> newLogger)
519544

545+
let CaptureDiagnosticsConcurrently () =
546+
let newLogger = ConcurrentCapturingDiagnosticsLogger("CaptureDiagnosticsConcurrently")
547+
let oldLogger = DiagnosticsThreadStatics.DiagnosticsLogger
548+
DiagnosticsThreadStatics.DiagnosticsLogger <- newLogger
549+
550+
{ new IDisposable with
551+
member _.Dispose() =
552+
newLogger.CommitDelayedDiagnostics oldLogger
553+
DiagnosticsThreadStatics.DiagnosticsLogger <- oldLogger
554+
}
555+
520556
let SetThreadBuildPhaseNoUnwind (phase: BuildPhase) =
521557
DiagnosticsThreadStatics.BuildPhase <- phase
522558

@@ -855,14 +891,11 @@ type StackGuard(maxDepth: int, name: string) =
855891

856892
try
857893
if depth % maxDepth = 0 then
858-
let diagnosticsLogger = DiagnosticsThreadStatics.DiagnosticsLogger
859-
let buildPhase = DiagnosticsThreadStatics.BuildPhase
860894
let ct = Cancellable.Token
861895

862896
async {
863897
do! Async.SwitchToNewThread()
864898
Thread.CurrentThread.Name <- $"F# Extra Compilation Thread for {name} (depth {depth})"
865-
use _scope = new CompilationGlobalsScope(diagnosticsLogger, buildPhase)
866899
use _token = Cancellable.UsingToken ct
867900
return f ()
868901
}

src/Compiler/Facilities/DiagnosticsLogger.fsi

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,21 @@ type CapturingDiagnosticsLogger =
226226

227227
override ErrorCount: int
228228

229+
/// Represents a DiagnosticsLogger that captures all diagnostics, optionally formatting them
230+
/// eagerly.
231+
type ConcurrentCapturingDiagnosticsLogger =
232+
inherit DiagnosticsLogger
233+
234+
new: nm: string * ?eagerFormat: (PhasedDiagnostic -> PhasedDiagnostic) -> ConcurrentCapturingDiagnosticsLogger
235+
236+
member CommitDelayedDiagnostics: diagnosticsLogger: DiagnosticsLogger -> unit
237+
238+
override DiagnosticSink: diagnostic: PhasedDiagnostic * severity: FSharpDiagnosticSeverity -> unit
239+
240+
member Diagnostics: (PhasedDiagnostic * FSharpDiagnosticSeverity) list
241+
242+
override ErrorCount: int
243+
229244
/// Thread statics for the installed diagnostic logger
230245
[<Class>]
231246
type DiagnosticsThreadStatics =
@@ -280,6 +295,8 @@ val UseTransformedDiagnosticsLogger: transformer: (DiagnosticsLogger -> #Diagnos
280295

281296
val UseDiagnosticsLogger: newLogger: DiagnosticsLogger -> IDisposable
282297

298+
val CaptureDiagnosticsConcurrently: unit -> IDisposable
299+
283300
val SetThreadBuildPhaseNoUnwind: phase: BuildPhase -> unit
284301

285302
val SetThreadDiagnosticsLoggerNoUnwind: diagnosticsLogger: DiagnosticsLogger -> unit

0 commit comments

Comments
 (0)