标签: ioref

强制评估IORef:rnf,deepSeq或其他什么?

我有一个长时间运行的过程forkIO'd,它产生像素颜色值:

takesAgesToRun :: [[Color]]

myForkedProcess :: IORef [[Color]] -> IO ()
myForkedProcess ref = do let colors = takesAgesToRun
                         writeIORef ref colors
Run Code Online (Sandbox Code Playgroud)

(其中Color只包含三个Double值).

正如预期的那样,当读取"另一侧"时IORef,存储的值只是一个thunk,因此会阻止主进程.

我知道我需要完全评估[[Color]]正常形式的值,但似乎有两种方法可以实现这一点,而且,我不确定如何将其合并到我的代码中.

我该怎么做?我是否使用rnf,deepSeq或其他一些线程策略?这些是其中一个首选,其他人是否已被弃用?它如何适合我的代码?

(PS请忽略这样一个事实,即将图像存储为颜色列表列表是愚蠢的 - 这只是代码的简化版本).

multithreading haskell ioref

4
推荐指数
1
解决办法
240
查看次数

如何使用带镜头的IORef?

想知道如何最好地将Control.Lens包与IORefs 结合起来.具体来说,我希望能够使用atomicModifyIORef镜头,以便我可以提供类型的功能,a -> (a, b)并从操作返回一个值.代码段:

let inc x = (x+1, x)
ior <- newIORef ((1, 1) :: (Int, Int))
thisShouldBe1 <- ior & atomicModifyIORef ?? _1 inc -- this is the bit I'm stuck on
Run Code Online (Sandbox Code Playgroud)

haskell atomic haskell-lens ioref

4
推荐指数
1
解决办法
430
查看次数

IORef和STRef的汇编

为了测量那些Refs的性能,我将GHC生成的组件转储到以下代码中:

import Data.IORef

main = do
  r <- newIORef 18
  v <- readIORef r
  print v
Run Code Online (Sandbox Code Playgroud)

我期望IORef完全被优化掉,只留下一个系统调用来写字符串"18"的stdout.相反,我得到250行组装.你知道有多少人会被执行吗?以下是我认为该计划的核心内容:

.globl Main.main1_info
Main.main1_info:
_c1Zi:
    leaq -8(%rbp),%rax
    cmpq %r15,%rax
    jb _c1Zj
_c1Zk:
    movq $block_c1Z9_info,-8(%rbp)
    movl $Main.main2_closure+1,%ebx
    addq $-8,%rbp
    jmp stg_newMutVar#
_c1Zn:
    movq $24,904(%r13)
    jmp stg_gc_unpt_r1
.align 8
    .long   S1Zo_srt-(block_c1Z9_info)+0
    .long   0
    .quad   0
    .quad   30064771104
block_c1Z9_info:
_c1Z9:
    addq $24,%r12
    cmpq 856(%r13),%r12
    ja _c1Zn
_c1Zm:
    movq 8(%rbx),%rax
    movq $sat_s1Z2_info,-16(%r12)
    movq %rax,(%r12)
    movl $GHC.Types.True_closure+2,%edi
    leaq -16(%r12),%rsi
    movl $GHC.IO.Handle.FD.stdout_closure,%r14d
    addq $8,%rbp
    jmp GHC.IO.Handle.Text.hPutStr2_info
_c1Zj:
    movl $Main.main1_closure,%ebx
    jmp …
Run Code Online (Sandbox Code Playgroud)

performance haskell ioref

4
推荐指数
1
解决办法
309
查看次数

Haskell IORef - 答案与获得答案的功能

我正在努力了解如何IORefs真正使用,并且我无法按照我在https://www.seas.upenn.edu/~cis194/spring15/lectures/12-unsafe.html上找到的示例代码进行操作

newCounter :: IO (IO Int)
newCounter = do
  r <- newIORef 0
  return $ do
    v <- readIORef r
    writeIORef r (v + 1)
    return v

printCounts :: IO ()
printCounts = do
  c <- newCounter
  print =<< c
  print =<< c
  print =<< c
Run Code Online (Sandbox Code Playgroud)

printCounts执行" c <- newCounter"时,为什么不能cnewCounter" return $ do"块中得到完成工作的结果,这似乎应该IO 0在第一次被调用时被分配给常量" "然后永远不会改变?相反,c似乎被赋予了在" return $ do"块中定义的函数,然后每次printCounts到达另一个" print =<< c …

io closures haskell do-notation ioref

4
推荐指数
1
解决办法
123
查看次数

在写IORef之前应该检查一下变化吗?

有代码读取IORef并根据某些条件和计算创建一个新值.现在它将新值写入IORef.但它有可能根本没有改变.新值可能与旧值相同.

关于在编写IORef之前是否检查值是否不同,或者只是编写IORef,需要考虑哪些因素?

writeIORef在设置之前检查值是否已更改?

通过先检查,你可以避免写入并节省一点性能吗?

haskell reference ioref

3
推荐指数
1
解决办法
188
查看次数

共享可变状态:何时使用IORefs

我有一个写入Map和PSQ的主线程.在Map和PSQ中,我使用相同的密钥,以便通过查看PSQ,可以找到具有最小优先级的条目,其具有O(1)复杂度并且被映射到Map中的值.

现在,当我的主线程在需要时添加/修改Map和PSQ时,我有第二个线程,它经常(forever $ do)查看PSQ以确定最旧的键何时是N ms之前然后应该刷新它.

为此,两个线程都需要查看相同的可变数据.维持国家的最佳方式是什么?这是IOREfs的案例吗?还有什么方法可以解决这个问题?

这里的"一些"pre-alpha代码:

import Data.Time
import Data.Functor
import Data.Time.Clock.POSIX
import qualified Data.PSQueue as PSQ
import qualified Data.Map as Map
import Data.Maybe
import Control.Concurrent
import Control.Concurrent.MVar
import Control.Monad
import Network.Socket hiding (send, sendTo, recv, recvFrom)
import Network.Socket.ByteString
import qualified Data.ByteString.Char8 as B 

--PSQ = (host, PID) POSIXTime
--where the tuple is k and POSIXTime is p

--Map is (host, PortNumber) [messages]
--where the tuple is the key and [messages] is a list of messages

key …
Run Code Online (Sandbox Code Playgroud)

haskell shared-state ioref

2
推荐指数
1
解决办法
340
查看次数

使用StateT与ReaderT IORef进行异常处理

通过坚持而IORef不是尝试使用State Monad 来维持状态似乎要容易得多.下面我们有2个可供选择的State Monads.一个使用StateT,另一个使用ReaderT IORef.该ReaderT IORef可以轻松地运行在一个已知状态的最终处理.

{-# LANGUAGE GeneralizedNewtypeDeriving, ScopedTypeVariables #-}
import Control.Monad.State (MonadState, execStateT, modify, StateT)
import Control.Applicative (Applicative)
import Control.Monad (void)
import Control.Monad.IO.Class ( MonadIO, liftIO )
import Data.IORef
import Control.Exception.Base
import Control.Monad.Reader (MonadReader, runReaderT, ask, ReaderT)

type StateRef = IORef Int
newtype ReadIORef a = ReadIORef { unStIORef :: ReaderT StateRef IO a } deriving (Functor, Applicative, Monad, MonadIO, MonadReader StateRef)
newtype St a        = StM       { unSt      :: …
Run Code Online (Sandbox Code Playgroud)

monads haskell ioref

2
推荐指数
1
解决办法
470
查看次数

如何在使用IO时在Haskell中的两个函数调用之间共享IORef状态?

我正在努力学习Haskell,我正在玩IORef,我试图保存并查找记录.我的代码看起来像这样(注意我在这个例子中选择了"String"作为IORef类型只是为了方便和简介,在我的实际代码中我正在使用记录.而且还忽略我使用的是Set而不是一张地图,我会改变一下):

module MyTest where

import           Data.IORef
import           Data.Set
import           Data.Foldable          (find)

type State = (Set String)
type IORefState = IORef State

saveStringToState :: IO IORefState -> String -> IO String
saveStringToState stateIO string = do
  state <- stateIO
  atomicModifyIORef
    state
    (\oldStrings ->
       let updatedStrings = insert string oldStrings
       in (updatedStrings, updatedStrings))
  stringsState <- readIORef state :: IO State
  putStrLn ("### saved: " ++ show stringsState)
  return string

findStringInState :: IO IORefState -> String -> IO (Maybe String)
findStringInState …
Run Code Online (Sandbox Code Playgroud)

haskell shared-state ioref

2
推荐指数
1
解决办法
158
查看次数

readIORef如何工作:创建副本还是不创建副本?

该代码的作用是什么?是someMap(的::Data.Map.Strict.Map)对象的副本是否由myMap引用或仅作为引用?我的意思是在我阅读后可以someMap更改(通过另一个线程)readIORef吗?像C的易失性...可能吗?我希望它是复制/快照,因此任何更改都不会影响我someMap或...?

     do
        ....
        someMap <- readIORef myMap
        ....
Run Code Online (Sandbox Code Playgroud)

haskell immutability do-notation io-monad ioref

2
推荐指数
1
解决办法
78
查看次数

Haskell并发使用简单的IORef?

我一直在问Haskell中关于并发性的几个问题,特别是TVar我对Livelock的问题有所顾虑TVar.

相反,我提出了这个解决方案.

(1)将程序中的所有共享数据包装在一个数据结构中,并将其包装在一个数据结构中IORef.(2)只需使用即可进行任何更改atomicModifyIORef.

我相信这可以防止死锁和活锁(而TVar只会阻止前者).此外,因为atomicModifyIORef简单地将另一个thunk链接到一个链(这是一对指针操作),这不是一个瓶颈.对数据的所有实际操作可以并行完成,只要它们不相互依赖.Haskell运行时系统将解决这个问题.

但是我觉得这太简单了.我错过了什么"陷阱"吗?

concurrency haskell shared-state ioref

1
推荐指数
2
解决办法
928
查看次数

IORef处理清单

这是我之前提出的问题的后续行动.如果方式更新列表中,我想IORef在下面接受的解决方案是O(1)或不是,在每一个电话fetch.我怀疑这是因为IORef可能只是保持指向列表头部的指针(而不是遍历和复制整个列表,每次都是O(n).只需将指针更改为新头应为O(1),并且应该防止急切评估整个列表).但是,ghc-core不会显示低级代码.所以,问这里:

mklstream :: L.ByteString -> (IO S.ByteString -> IO r) -> IO r
mklstream lbs sink = do
  ref <- newIORef (L.toChunks lbs)
  let fetch :: IO S.ByteString
      fetch = do chunks <- readIORef ref
                 case chunks of
                   [] -> return S.empty
                   (c:cs) -> do writeIORef ref cs
                                return c
  sink fetch
Run Code Online (Sandbox Code Playgroud)

haskell time-complexity ioref

1
推荐指数
1
解决办法
181
查看次数

为什么我不能将值写入IORef但可以读取它

在haskell中,我需要一个全局变量,所以我选择使用IORef插槽,这是我的计划:

memo :: IORef Int
memo = unsafePerformIO $ newRefInt 9999

evaluate ARGs s = do
  v <- Right $ unsafePerformIO $ readIORef memo
  val <- Right $ VInt v
  return $ (val, s)

evaluate (Call funcID exp) s = do
...
Right $ writeIORef memo 100
...
Run Code Online (Sandbox Code Playgroud)

我的计划是当执行者评估"呼叫"节点时,它会将参数保存到插槽中.然后,当评估"ARGs"节点时,将读取该备忘录槽.

但无论我做什么,我只能读取9999但不能在该槽中写入新值.

甚至我试过:

memo :: IORef Int
memo = unsafePerformIO $ newRefInt 9999

evaluate ARGs s = do
  Right $ writeIORef memo 100
  v <- Right $ unsafePerformIO $ readIORef memo
  val …
Run Code Online (Sandbox Code Playgroud)

interpreter haskell unsafe-perform-io ioref

0
推荐指数
1
解决办法
197
查看次数