Skip to content

Commit

Permalink
Improve handling of messages after Runner gets disposed
Browse files Browse the repository at this point in the history
  • Loading branch information
Timothé Larivière committed Feb 12, 2024
1 parent 6de97c0 commit 6c88f7c
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 5 deletions.
10 changes: 8 additions & 2 deletions src/Fabulous/MvuComponent.fs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,14 @@ module MvuComponent =

let ctx = new ComponentContext(1)

let runner =
new Runner<obj, obj, obj>((fun () -> ctx.TryGetValue(0).Value), (fun v -> ctx.SetValue(0, v)), data.Program)
let getModel () =
match ctx.TryGetValue(0) with
| ValueNone -> failwith("Model not found in ComponentContext " + ctx.Id.ToString())
| ValueSome model -> model

let setModel v = ctx.SetValue(0, v)

let runner = new Runner<obj, obj, obj>(getModel, setModel, data.Program)

ctx.LinkDisposable(runner)

Expand Down
10 changes: 7 additions & 3 deletions src/Fabulous/Runner.fs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ open System.Collections.Concurrent
type Runner<'arg, 'model, 'msg>(getState: unit -> 'model, setState: 'model -> unit, program: Program<'arg, 'model, 'msg>) =
let mutable _activeSubs = Sub.Internal.empty
let mutable _reentering = false
let mutable _stopped = false
let queue = ConcurrentQueue<'msg>()

let onError (message, exn) =
Expand All @@ -21,7 +22,7 @@ type Runner<'arg, 'model, 'msg>(getState: unit -> 'model, setState: 'model -> un
let processMsgs dispatch msg =
let mutable lastMsg = ValueSome msg

while lastMsg.IsSome do
while not _stopped && lastMsg.IsSome do
let model = getState()
let newModel, cmd = program.Update(lastMsg.Value, model)
let subs = program.Subscribe(newModel)
Expand All @@ -39,7 +40,9 @@ type Runner<'arg, 'model, 'msg>(getState: unit -> 'model, setState: 'model -> un

let rec dispatch msg =
try
if _reentering then
if _stopped then
() // Message arrived after Runner got disposed, simply discard it
else if _reentering then
queue.Enqueue(msg)
else
_reentering <- true
Expand Down Expand Up @@ -74,7 +77,8 @@ type Runner<'arg, 'model, 'msg>(getState: unit -> 'model, setState: 'model -> un

let stop () =
try
_reentering <- true
_stopped <- true
queue.Clear()
Sub.Internal.Fx.stop onError _activeSubs
_activeSubs <- Sub.Internal.empty
with ex ->
Expand Down

0 comments on commit 6c88f7c

Please sign in to comment.