unsafePerformIO and FFI library initialization

孤人 提交于 2019-12-04 17:37:16

问题


I'm creating an FFI module to a library in C which wants a 1-time, non-reentrant function to be called before anything else is. This call is idempotent, but stateful, so I could just call it in every Haskell call. But it's slow and due to non-reentrancy it could cause conflicts.

So is this the right time to use unsafePerformIO? I could wrap a Bool in an unsafe IORef or MVar to make these initialization calls idempotent by ignoring subsequent calls (calls where the global, hidden IORef state is False).

If not, what is the right way to do this?


回答1:


I prefer the approach of initializing once and providing an unforgeable token as evidence that you have initialized the machine.

So your evidence would be:

data Token = Token

which you export abstractly.

Then your initialization function can return this evidence.

init :: IO Token

Now, you need to pass that proof to your API:

bar  :: Token -> IO Int
bar !tok = c_call_bar

etc.

You can now wrap this stuff up with a monad, or some higher order initialization environment to make it cleaner, but that's the basic idea.

The problem with initializing C libraries using hidden state is that you end up either not being able to parallelize access to the library, or having problems in GHCi, mixing compiled and bytecode, with two different versions of the C library loaded (which will fail with a linker error).




回答2:


I'd like to note that currently some new trick is suggested for/instead of withSocketsDo by Neil Mitchell, based on evaluate ("Forces its argument to be evaluated to weak head normal form when the resultant IO action is executed."):

withSocketsDo act = do evaluate withSocketsInit; act 

{-# NOINLINE withSocketsInit #-}
withSocketsInit = unsafePerformIO $ do
    initWinsock
    termWinsock

My approach to removing the requirement to call withSocketsDo was to make it very cheap, then sprinkle it everywhere it might be needed.

Not necessarily this is a beautiful idea...

(See also his answer announcing this update in the library.)



来源:https://stackoverflow.com/questions/14145187/unsafeperformio-and-ffi-library-initialization

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!