我创建C中的FFI模块的库,希望被称为1次,不可重入函数之前别的是。 这个调用是幂等的,但有状态,所以我只是把它在每一个哈斯克尔通话。 但是,它的速度慢,并且由于非重入可能会导致冲突。
因此,这是使用unsafePerformIO正确的时间? 我可以在一个不安全的IOREF或无功换一个布尔值,使通过忽略后续调用(调用在全球,隐藏IOREF状态是假)幂等这些初始化调用。
如果没有,什么是做的正确方法?
我创建C中的FFI模块的库,希望被称为1次,不可重入函数之前别的是。 这个调用是幂等的,但有状态,所以我只是把它在每一个哈斯克尔通话。 但是,它的速度慢,并且由于非重入可能会导致冲突。
因此,这是使用unsafePerformIO正确的时间? 我可以在一个不安全的IOREF或无功换一个布尔值,使通过忽略后续调用(调用在全球,隐藏IOREF状态是假)幂等这些初始化调用。
如果没有,什么是做的正确方法?
我喜欢初始化一次,并提供伪造的令牌,你已经初始化的机器证据的方法。
所以,你的证据是:
data Token = Token
你出口抽象。
那么你的初始化函数可以返回这方面的证据。
init :: IO Token
现在,你需要的是证明传递到您的API:
bar :: Token -> IO Int
bar !tok = c_call_bar
等等
现在你可以用这个东西了一个单子,或者一些更高阶的初始化环境,使之更清洁,但是这是基本的想法。
与初始化使用隐藏状态的C库的问题是,你最终要么不能够并行访问图书馆,或有问题GHCI,混合编译字节码,有两个不同的版本加载的C库(这将失败,链接错误)。
我想指出,目前一些新的技巧,建议为/,而不是withSocketsDo
由尼尔·米切尔的基础上evaluate
(“强制执行所产生的IO操作时它的参数进行评估,以微弱的头部正常形态。”):
withSocketsDo act = do evaluate withSocketsInit; act
{-# NOINLINE withSocketsInit #-}
withSocketsInit = unsafePerformIO $ do
initWinsock
termWinsock
我以消除调用withSocketsDo要求的办法是使很便宜,然后到处洒它可能是必要的。
不一定,这是一个美好的理想......
(另见他的回答宣布在图书馆此更新。)