From 1009d7d468da2b2bf1151d07e70b6f0c3a7ab248 Mon Sep 17 00:00:00 2001 From: Patrick Stevens Date: Sat, 7 Jan 2023 10:39:25 +0000 Subject: [PATCH] Tasks (#10) --- RayTracing.App/Program.fs | 2 +- RayTracing.Test/TestPpmOutput.fs | 2 +- RayTracing/ImageOutput.fs | 76 ++++++++++++++++++-------------- RayTracing/RayTracing.fsproj | 3 +- 4 files changed, 46 insertions(+), 37 deletions(-) diff --git a/RayTracing.App/Program.fs b/RayTracing.App/Program.fs index 1bc875c..3eaab98 100644 --- a/RayTracing.App/Program.fs +++ b/RayTracing.App/Program.fs @@ -44,7 +44,7 @@ module Program = AnsiConsole.WriteLine (sprintf "Temporary output being written eagerly to '%s'" tempOutput.FullName) async { - do! await + do! Async.AwaitTask await let! pixelMap = ImageOutput.readPixelMap readTask.Increment tempOutput (Image.rowCount image) (Image.colCount image) diff --git a/RayTracing.Test/TestPpmOutput.fs b/RayTracing.Test/TestPpmOutput.fs index 17112d5..1aee69d 100644 --- a/RayTracing.Test/TestPpmOutput.fs +++ b/RayTracing.Test/TestPpmOutput.fs @@ -41,7 +41,7 @@ module TestRayTracing = let tempOutput, await = ImageOutput.toPpm ignore image fs async { - do! await + do! Async.AwaitTask await let! pixelMap = ImageOutput.readPixelMap ignore tempOutput (Image.rowCount image) (Image.colCount image) let arr = ImageOutput.assertComplete pixelMap do! ImageOutput.writePpm false ignore arr outputFile diff --git a/RayTracing/ImageOutput.fs b/RayTracing/ImageOutput.fs index 7d6d351..ce999e5 100644 --- a/RayTracing/ImageOutput.fs +++ b/RayTracing/ImageOutput.fs @@ -6,6 +6,7 @@ open System.Collections.Immutable open System.IO open System.IO.Abstractions open System.Text +open System.Threading.Tasks open SkiaSharp [] @@ -122,65 +123,72 @@ module ImageOutput = return result } + let inline writeAsciiInt (writer : Stream) (i : int) : unit = + let mutable places = 0 + let mutable tmp = i + let mutable pow = 1 + + while tmp > 0 do + tmp <- tmp / 10 + pow <- pow * 10 + places <- places + 1 + + pow <- pow / 10 + + while pow > 0 do + writer.WriteByte (byte ((i / pow) % 10) + 48uy) // '0' + pow <- pow / 10 + let resume (incrementProgress : float -> unit) (soFar : IReadOnlyDictionary) (image : Image) (fs : IFileSystem) - : IFileInfo * Async + : IFileInfo * Task = - let rec go (writer : Stream) (rowNum : int) (rowEnum : IEnumerator) = - async { - if not (rowEnum.MoveNext ()) then - return () - else + let tempFile = fs.Path.GetTempFileName () |> fs.FileInfo.FromFileName - let row = rowEnum.Current + tempFile, + task { + use outputStream = tempFile.OpenWrite () + use enumerator = image.Rows.GetEnumerator () + let mutable rowNum = 0 - do! + while enumerator.MoveNext () do + + let row = enumerator.Current + + let! _ = row |> Array.mapi (fun colNum pixel -> - async { + backgroundTask { let! pixel = match soFar.TryGetValue ((rowNum, colNum)) with | false, _ -> pixel | true, v -> async { return v } - let toWrite = ASCIIEncoding.Default.GetBytes (sprintf "%i,%i" rowNum colNum) - lock - writer + outputStream (fun () -> - writer.Write (toWrite, 0, toWrite.Length) - writer.WriteByte 10uy // '\n' - writer.WriteByte pixel.Red - writer.WriteByte pixel.Green - writer.WriteByte pixel.Blue + writeAsciiInt outputStream rowNum + outputStream.WriteByte 44uy // ',' + writeAsciiInt outputStream colNum + outputStream.WriteByte 10uy // '\n' + outputStream.WriteByte pixel.Red + outputStream.WriteByte pixel.Green + outputStream.WriteByte pixel.Blue ) incrementProgress 1.0 return () } ) -#if DEBUG - |> Async.Sequential -#else - |> Async.Parallel -#endif - |> Async.Ignore + |> Task.WhenAll - return! go writer (rowNum + 1) rowEnum - } - - let tempFile = fs.Path.GetTempFileName () |> fs.FileInfo.FromFileName - - tempFile, - async { - use outputStream = tempFile.OpenWrite () - use enumerator = image.Rows.GetEnumerator () - return! go outputStream 0 enumerator + rowNum <- rowNum + 1 } + let writePpm (gammaCorrect : bool) (incrementProgress : float -> unit) @@ -227,7 +235,7 @@ module ImageOutput = (progressIncrement : float -> unit) (image : Image) (fs : IFileSystem) - : IFileInfo * Async + : IFileInfo * Task = resume progressIncrement ImmutableDictionary.Empty image fs diff --git a/RayTracing/RayTracing.fsproj b/RayTracing/RayTracing.fsproj index 6ee5c6d..ca67382 100644 --- a/RayTracing/RayTracing.fsproj +++ b/RayTracing/RayTracing.fsproj @@ -1,7 +1,8 @@  - net7.0 + net7.0 + true