Spec-Zone.ru › Haskell 7

Data.IORef

Авторские права (c) Университет Глазго 2001
Лицензия BSD-стиль (см. файл libraries/base/LICENSE)
Поддержка libraries@haskell.org
Стабильность экспериментальная
Портируемость портируемая
Безопасный Haskell Надёжный
Язык Haskell2010

Содержание

  • IORefs
    • Модель памяти

Описание

Мутабельные ссылки в монаде IO.

IORefs

data IORef a Исходный код

Мутабельная переменная в монаде IO.

Примеры

Eq (IORef a)

newIORef :: a -> IO (IORef a) Исходный код

Создать новую IORef

readIORef :: IORef a -> IO a Исходный код

Прочитать значение IORef

writeIORef :: IORef a -> a -> IO () Исходный код

Записать новое значение в IORef

modifyIORef :: IORef a -> (a -> a) -> IO () Исходный код

Изменить содержимое IORef.

Обратите внимание, что modifyIORef не применяет функцию строго. Это означает, что если программа вызывает modifyIORef много раз, но редко использует значение, задержки будут накапливаться в памяти, что приведёт к утечке памяти. Это распространённая ошибка при использовании IORef в качестве счётчика. Например, следующее, вероятно, приведёт к переполнению стека:

ref <- newIORef 0
replicateM_ 1000000 $ modifyIORef ref (+1)
readIORef ref >>= print

Чтобы избежать этой проблемы, используйте modifyIORef' вместо этого.

modifyIORef' :: IORef a -> (a -> a) -> IO () Исходный код

Строгая версия modifyIORef

С версии: 4.6.0.0

atomicModifyIORef :: IORef a -> (a -> (a, b)) -> IO b Исходный код

Атомарно изменяет содержимое IORef.

Эта функция полезна для безопасного использования IORef в многопоточной программе. Если у вас только одна IORef, то использование atomicModifyIORef для доступа и изменения предотвратит гонки.

Расширение атомарности до нескольких IORef затруднительно, поэтому рекомендуется использовать MVar вместо этого, если вам нужно что-то более сложное.

atomicModifyIORef не применяет функцию строго. Это важно знать, даже если всё, что вы делаете, это заменяете значение. Например, это приведёт к утечке памяти:

ref <- newIORef '1'
forever $ atomicModifyIORef ref (\_ -> ('2', ()))

Используйте atomicModifyIORef' или atomicWriteIORef для решения этой проблемы.

atomicModifyIORef' :: IORef a -> (a -> (a, b)) -> IO b Исходный код

Строгая версия atomicModifyIORef. Это принудительно вызывает как значение, хранящееся в IORef, так и возвращённое значение.

С версии: 4.6.0.0

atomicWriteIORef :: IORef a -> a -> IO () Исходный код

Вариант writeIORef со свойством "барьера для переупорядочивания", которым обладает atomicModifyIORef.

С версии: 4.6.0.0

mkWeakIORef :: IORef a -> IO () -> IO (Weak (IORef a)) Исходный код

Создать Weak указатель на IORef, используя второй аргумент в качестве финализатора для выполнения при сборке мусора IORef

Модель памяти

В многопоточной программе операции IORef могут появляться вне очереди для другого потока, в зависимости от модели памяти подлежащей архитектуры процессора. Например, на x86 загрузки могут выполняться до сохранений, поэтому в следующем примере:

 maybePrint :: IORef Bool -> IORef Bool -> IO ()
 maybePrint myRef yourRef = do
   writeIORef myRef True
   yourVal <- readIORef yourRef
   unless yourVal $ putStrLn "critical section"

 main :: IO ()
 main = do
   r1 <- newIORef False
   r2 <- newIORef False
   forkIO $ maybePrint r1 r2
   forkIO $ maybePrint r2 r1
   threadDelay 1000000

возможно, что строка "critical section" будет напечатана дважды, даже если нет переплетения операций двух потоков, которое позволяет такой результат. Модель памяти x86 позволяет readIORef произойти до более раннего writeIORef.

Реализация должна гарантировать, что переупорядочивание операций с памятью не может привести к ошибкам в корректном с точки зрения типов коде. В частности, при проверке значения, считанного из IORef, операции записи в память, которые создали это значение, должны произойти с точки зрения текущего потока.

atomicModifyIORef действует как барьер для переупорядочения. Несколько операций atomicModifyIORef происходят в строгом порядке программы. Операция atomicModifyIORef никогда не наблюдается до любой более ранней (в порядке программы) операции IORef или после любой более поздней операции IORef.

© The University of Glasgow and others
Licensed under a BSD-style license (see top of the page).
https://downloads.haskell.org/~ghc/7.10.3/docs/html/libraries/base-4.8.2.0/Data-IORef.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API