我将尝试编写一个库,旨在复制Qt的线程语义:信号可以连接到槽,并且所有槽都在已知线程中执行,因此绑定到同一线程的槽与彼此相关是线程安全的。
我有以下API:
问题在于如何从
我需要的东西:
1.类型安全:信号不应连接到期望不同类型的插槽。 2.类型独立性:对于任何给定类型,可以有多个插槽(也许可以通过newtype和/或TH放宽这一点)。 3.易于使用:由于这是一个库,因此应易于创建信号和插槽。
我尝试过的方法:
1.Data.Dynamic:使整个过程非常脆弱,并且我没有找到一种在
我错过了什么?
我有以下API:
data Signal a = Signal Unique a
data Slot a = Slot Unique ThreadId (a -> IO ())
mkSignal :: IO (Signal a)
mkSlot :: ThreadId -> (Slot a -> a -> IO ()) -> IO (Slot a)
connect :: Signal a -> Slot a -> IO ()
-- callable from any thread
emit :: Signal a -> a -> IO ()
-- runs in Slot's thread as a result of `emit`
execute :: Slot a -> a -> IO ()
execute (Slot _ _ f) arg = f arg
问题在于如何从
emit
到execute
。需要以某种方式在运行时存储参数,然后执行IO操作,但是似乎无法通过类型检查器。我需要的东西:
1.类型安全:信号不应连接到期望不同类型的插槽。 2.类型独立性:对于任何给定类型,可以有多个插槽(也许可以通过newtype和/或TH放宽这一点)。 3.易于使用:由于这是一个库,因此应易于创建信号和插槽。
我尝试过的方法:
1.Data.Dynamic:使整个过程非常脆弱,并且我没有找到一种在
Dynamic
上执行正确类型的IO操作的方法。有dynApply,但它是纯的。
2.存在类型:我需要执行传递给mkSlot
的函数,而不是基于类型的任意函数。
3.Data.HList:我不够聪明,无法理解它。我错过了什么?
instance MonadIO STM
:) 对插槽组施加锁可能起作用,但可能不比专用线程读取TChan
更简单。@C.A.McCann:谢谢! :) - ehird