Я взглянул на предложение Сзера смоделировать событие на IVar Хопака и выяснил, как реализовано стандартное событие F #.Объединив два, я придумал это:
open System
open System.Threading
type LockFreeEvent<'args>() =
let mutable multicast: Handler<'args> = null
let wait =
let spin = SpinWait()
spin.SpinOnce
member __.Trigger arg =
match multicast with
| null -> ()
| d -> d.Invoke(null, arg) |> ignore
member __.Publish =
{new IEvent<'args> with
member __.AddHandler handler =
let snapshot = multicast
while snapshot <> Interlocked.CompareExchange<Handler<'args>>(&multicast, Delegate.Combine(multicast, handler) :?> Handler<'args>, snapshot) do
wait ()
member __.RemoveHandler handler =
let snapshot = multicast
while snapshot <> Interlocked.CompareExchange(&multicast, Delegate.Remove(multicast, handler) :?> Handler<'args>, snapshot) do
wait ()
member this.Subscribe observer =
let handler = new Handler<_>(fun sender args -> observer.OnNext(args))
(this :?> IEvent<_,_>).AddHandler(handler)
{ new IDisposable with
member __.Dispose() = (this :?> IEvent<_,_>).RemoveHandler(handler)
}
}
Как это выглядит?Я думаю, что это должно реализовать ту же функциональность, что и стандартное событие F #, но без блокировки, если в Delegate.Combine
не происходит блокировка.Я думаю, что мне, возможно, придется сделать Trigger
также по-другому.