gpt4 book ai didi

.net - 在异步之间发出信号的无锁方式

转载 作者:行者123 更新时间:2023-12-04 04:23:59 25 4
gpt4 key购买 nike

我正在寻找一种无锁方式来在F#中的两个Async之间发信号。我有两个尾递归的async函数,在进行下一个递归之前,我想让一个直到另一个发出信号为止。我可以为此使用一个事件,但是看起来.NET事件在内部使用锁。到目前为止,我发现的唯一解决方案是使用ntdll.dll中的键控事件,但我希望使用一种无​​需直接引用特定于平台的DLL的解决方案。有什么方法可以使用System.Threading.Interlocked或其他.NET技术来实现这一目标?

这是我要实现的一个简单示例:

let rec loop1 () =
async {
// do work
// somehow signal loop2
return! loop1 ()
}

let rec loop2 state =
async {
// wait for signal from loop1
// do work
return! loop2 state // This would actually be a new state, not the old state
}

最佳答案

我查看了Szer建议在Hopac的IVar上对事件进行建模的建议,并研究了标准F#Event的实现方式。结合两者,我想到了:

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

关于.net - 在异步之间发出信号的无锁方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50395696/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com