GHC.Conc
| Copyright | (c) The University of Glasgow 1994-2023 |
|---|---|
| License | see libraries/base/LICENSE |
| Maintainer | ghc-devs@haskell.org |
| Stability | internal |
| Portability | non-portable (GHC extensions) |
| Safe Haskell | Unsafe |
| Language | Haskell2010 |
Описание
Основные средства конкурентного программирования.
API этого модуля нестабилен и не предназначен для использования широкой публикой. Если вам абсолютно необходимо от него зависеть, убедитесь, что вы используете жёсткое верхнее ограничение, например, base < 4.X вместо base < 5, поскольку интерфейс может быстро меняться без предупреждения.
A ThreadId is an abstract type representing a handle to a thread. ThreadId is an instance of Eq, Ord and Show, where the Ord instance implements an arbitrary total ordering over ThreadIds. The Show instance lets you convert an arbitrary-valued ThreadId to string form; showing a ThreadId value is occasionally useful when debugging or diagnosing the behaviour of a concurrent program.
Примечание: в GHC, если у вас есть ThreadId, у вас по сути есть указатель на сам поток. Это означает, что сам поток не может быть очищен сборщиком мусора, пока вы не отбросите ThreadId. Исправить этот недостаток, продолжая поддерживать threadStatus, было бы сложно.
Экземпляры
| Show ThreadId Source | Since: base-4.2.0.0 |
| Eq ThreadId Source | Since: base-4.2.0.0 |
| Ord ThreadId Source | Since: base-4.2.0.0 |
Defined in GHC.Internal.Conc.Sync | |
Разветвление и тому подобное
forkIO :: IO () -> IO ThreadId Source
Создаёт новый поток для выполнения вычисления IO, переданного в качестве первого аргумента, и возвращает ThreadId вновь созданного потока.
Новый поток будет лёгким, несвязанным потоком. Не гарантируется, что внешние вызовы, сделанные этим потоком, будут сделаны каким-либо конкретным потоком ОС; если вам необходимо, чтобы внешние вызовы выполнялись конкретным потоком ОС, используйте forkOS вместо этого.
Новый поток наследует замаскированное состояние родителя (см. mask).
Вновь созданный поток имеет обработчик исключений, который игнорирует исключения BlockedIndefinitelyOnMVar, BlockedIndefinitelyOnSTM и ThreadKilled, и передаёт все другие исключения обработчику неперехваченных исключений.
ВНИМАНИЕ: Исключения в новом потоке не будут переброшены в поток, который его создал. Это означает, что вы можете совершенно не знать о проблеме, если/когда это произойдёт. Возможно, вам стоит использовать библиотеку async вместо этого.
forkIOWithUnmask :: ((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId Source
Как forkIO, но дочернему потоку передаётся функция, которая может использоваться для снятия маски с асинхронных исключений. Эта функция обычно используется следующим образом
... mask_ $ forkIOWithUnmask $ \unmask ->
catch (unmask ...) handler
чтобы обработчик исключений в дочерней потоке был установлен с замаскированными асинхронными исключениями, в то время как основное тело дочернего потока выполняется в незамаскированном состоянии.
Обратите внимание, что функция unmask, переданная дочернему потоку, должна использоваться только в этом потоке; поведение не определено, если она вызывается в другом потоке.
С момента: base-4.4.0.0
forkOn :: Int -> IO () -> IO ThreadId Источник
Как forkIO, но позволяет указать, на какой возможности должен работать поток. В отличие от потока forkIO, поток, созданный forkOn, будет оставаться на той же возможности на протяжении всего своего жизненного цикла (потоки forkIO могут мигрировать между возможностями в соответствии с политикой планирования). forkOn полезно для переопределения политики планирования, когда заранее известно, как лучше распределить потоки.
Аргумент Int задаёт номер возможности (см. getNumCapabilities). Обычно возможности соответствуют физическим процессорам, но точное поведение зависит от реализации. Значение, переданное forkOn, интерпретируется по модулю общего числа возможностей, возвращаемого getNumCapabilities.
Примечание GHC: количество возможностей задаётся параметром +RTS -N при запуске программы. Возможности могут быть закреплены за фактическими ядрами процессоров с помощью +RTS -qa, если это поддерживается подлежащей операционной системой, хотя на практике это обычно не требуется (и может даже снизить производительность в некоторых случаях — рекомендуется экспериментирование).
С момента: base-4.4.0.0
forkOnWithUnmask :: Int -> ((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId Источник
Как forkIOWithUnmask, но дочерний поток привязывается к заданному процессору, как с forkOn.
С момента: base-4.4.0.0
numCapabilities :: Int Источник
значение, переданное флагу +RTS -N. Это количество потоков Haskell, которые могут работать истинно одновременно в любой момент времени, и обычно устанавливается равным количеству физических ядер процессора на машине.
Строго говоря, лучше использовать getNumCapabilities, так как количество возможностей может изменяться во время выполнения.
getNumCapabilities :: IO Int Источник
Возвращает количество потоков Haskell, которые могут работать истинно одновременно (на отдельных физических процессорах) в любой момент времени. Чтобы изменить это значение, используйте setNumCapabilities.
С момента: base-4.4.0.0
setNumCapabilities :: Int -> IO () Источник
Устанавливает количество потоков Haskell, которые могут работать истинно одновременно (на отдельных физических процессорах) в любой момент времени. Переданное в forkOn значение интерпретируется по модулю этого значения. Начальное значение задаётся параметром выполнения +RTS -N.
Это также количество потоков, которые будут участвовать в параллельном сборке мусора. Сильно рекомендуется, чтобы количество возможностей не было больше количества физических ядер процессора, и зачастую полезно оставлять одно или несколько ядер свободными, чтобы избежать конфликтов с другими процессами в системе.
С момента: base-4.5.0.0
getNumProcessors :: IO Int Источник
Возвращает количество ЦП, имеющихся в машине
С момента: base-4.5.0.0
Возвращает количество искр в настоящее время в локальном пуле искр
childHandler :: SomeException -> IO () Источник
myThreadId :: IO ThreadId Источник
Возвращает ThreadId вызывающего потока (только GHC).
killThread :: ThreadId -> IO () Источник
killThread вызывает исключение ThreadKilled в заданном потоке (только GHC).
killThread tid = throwTo tid ThreadKilled
throwTo :: Exception e => ThreadId -> e -> IO () Источник
throwTo вызывает произвольное исключение в целевом потоке (только GHC).
Доставка исключений синхронизируется между исходным и целевым потоком: throwTo не возвращается, пока исключение не будет вызвано в целевом потоке. Таким образом, вызывающий поток может быть уверен, что целевой поток получил исключение. Доставка исключений также атомарна относительно других исключений. Атомарность является полезным свойством при работе с проблемами гонок: например, если есть два потока, которые могут убить друг друга, гарантируется, что только один из потоков сможет убить другой.
Любая работа, которую выполнял целевой поток, когда было вызвано исключение, не теряется: вычисление приостанавливается до тех пор, пока это не потребуется другому потоку.
Если целевой поток в настоящее время выполняет вызов к внешней функции, исключение не будет вызвано (и, следовательно, throwTo не вернётся) до завершения вызова. Это имеет место независимо от того, находится ли вызов внутри mask или нет. Однако в GHC вызов к внешней функции может быть помечен как interruptible, в этом случае throwTo заставит RTS попытаться заставить вызов вернуть значение; см. документацию GHC для получения дополнительной информации.
Важное примечание: поведение throwTo отличается от описанного в статье "Асинхронные исключения в Haskell" (http://research.microsoft.com/~simonpj/Papers/asynch-exns.htm). В статье throwTo является асинхронной; но реализация библиотеки использует более синхронный дизайн, в котором throwTo не возвращается до тех пор, пока исключение не будет получено целевым потоком. Компромисс обсуждается в разделе 9 статьи. Как любая блокирующая операция, throwTo поэтому прерывима (см. раздел 5.3 статьи). Однако, в отличие от других прерывимых операций, throwTo всегда прерывима, даже если она фактически не блокируется.
Нет гарантии, что исключение будет доставлено незамедлительно, хотя система выполнения будет стремиться к тому, чтобы не возникало произвольных задержек. В GHC исключение может быть вызвано только тогда, когда поток достигает безопасной точки, где безопасная точка — это место, где происходит выделение памяти. Некоторые циклы не выполняют выделение памяти внутри цикла и поэтому не могут быть прерваны с помощью throwTo.
Если целевой объект throwTo — это вызывающий поток, то поведение такое же, как у throwIO, за исключением того, что исключение выбрасывается как асинхронное исключение. Это означает, что если есть окружающее чистое вычисление, что имело бы место, если текущая операция IO находится внутри unsafePerformIO или unsafeInterleaveIO, это вычисление не заменяется исключением постоянно, а приостанавливается как если бы оно получило асинхронное исключение.
Обратите внимание, что если throwTo вызывается с текущим потоком как целевым объектом, исключение будет выброшено, даже если поток в настоящее время находится внутри mask или uninterruptibleMask.
par :: a -> b -> b infixr 0 Источник
pseq :: a -> b -> b infixr 0 Источник
Внутренняя функция, используемая RTS для запуска искр.
Действие yield позволяет (вынуждает в реализации кооперативной многозадачности) контекстную смену на любой другой в данный момент готовый к выполнению поток (если таковые имеются) и иногда бывает полезно при реализации абстракций конкурентности.
labelThread :: ThreadId -> String -> IO () Source
labelThread сохраняет строку в качестве идентификатора для этого потока. Этот идентификатор будет использоваться в отладочном выводе, чтобы облегчить различение различных потоков (в противном случае у вас будет только адрес объекта состояния потока в куче). Он также генерирует событие в журнале событий RTS.
mkWeakThreadId :: ThreadId -> IO (Weak ThreadId) Source
Создаёт слабую ссылку на ThreadId. Это может быть важно, если вы хотите сохранить ссылку на ThreadId, одновременно позволяя потоку получать исключения семейства BlockedIndefinitely (например, BlockedIndefinitelyOnMVar). Сохранение обычной ThreadId ссылки предотвратит доставку исключений BlockedIndefinitely, потому что ссылка может быть использована как целевой объект для throwTo в любой момент, что разблокирует поток.
Сохранение Weak ThreadId, с другой стороны, не предотвратит получение потоком исключений BlockedIndefinitely. По-прежнему возможно выбросить исключение в Weak ThreadId, но вызывающий код должен использовать deRefWeak сначала, чтобы определить, существует ли поток.
Since: base-4.6.0.0
listThreads :: IO [ThreadId] Source
Список потоков Haskell текущего процесса.
Since: base-4.18
data ThreadStatus Source
Текущее состояние потока
Конструкторы
| ThreadRunning | поток в настоящее время готов к выполнению или выполняется |
| ThreadFinished | поток завершен |
| ThreadBlocked BlockReason | поток заблокирован на некотором ресурсе |
| ThreadDied | поток получил необработанное исключение |
Примеры реализации
| Show ThreadStatus Source | Since: base-4.3.0.0 |
Определено в GHC.Internal.Conc.Sync МетодыshowsPrec :: Int -> ThreadStatus -> ShowS Source show :: ThreadStatus -> String Source showList :: [ThreadStatus] -> ShowS Source | |
| Eq ThreadStatus Source | Since: base-4.3.0.0 |
Определено в GHC.Internal.Conc.Sync Методы(==) :: ThreadStatus -> ThreadStatus -> Bool Source (/=) :: ThreadStatus -> ThreadStatus -> Bool Source | |
| Ord ThreadStatus Source | Since: base-4.3.0.0 |
Определено в GHC.Internal.Conc.Sync Методыcompare :: ThreadStatus -> ThreadStatus -> Ordering Source (<) :: ThreadStatus -> ThreadStatus -> Bool Source (<=) :: ThreadStatus -> ThreadStatus -> Bool Source (>) :: ThreadStatus -> ThreadStatus -> Bool Source (>=) :: ThreadStatus -> ThreadStatus -> Bool Source max :: ThreadStatus -> ThreadStatus -> ThreadStatus Source min :: ThreadStatus -> ThreadStatus -> ThreadStatus Source | |
data BlockReason Source
Краткое описание конструкторов
| BlockedOnMVar | блокировано на |
| BlockedOnBlackHole | блокировано на вычислении, выполняемом другим потоком |
| BlockedOnException | блокировано в |
| BlockedOnSTM | блокировано в |
| BlockedOnForeignCall | в настоящее время находится во внешнем вызове |
| BlockedOnOther | блокировано на каком-то другом ресурсе. Без |
Экземпляры
| Show BlockReason Source | Since: base-4.3.0.0 |
Определено в GHC.Internal.Conc.Sync Краткое описание методовshowsPrec :: Int -> BlockReason -> ShowS Source show :: BlockReason -> String Source showList :: [BlockReason] -> ShowS Source | |
| Eq BlockReason Source | Since: base-4.3.0.0 |
Определено в GHC.Internal.Conc.Sync Краткое описание методов(==) :: BlockReason -> BlockReason -> Bool Source (/=) :: BlockReason -> BlockReason -> Bool Source | |
| Ord BlockReason Source | Since: base-4.3.0.0 |
Определено в GHC.Internal.Conc.Sync Краткое описание методовcompare :: BlockReason -> BlockReason -> Ordering Source (<) :: BlockReason -> BlockReason -> Bool Source (<=) :: BlockReason -> BlockReason -> Bool Source (>) :: BlockReason -> BlockReason -> Bool Source (>=) :: BlockReason -> BlockReason -> Bool Source max :: BlockReason -> BlockReason -> BlockReason Source min :: BlockReason -> BlockReason -> BlockReason Source | |
threadStatus :: ThreadId -> IO ThreadStatus Source
Запрос текущего состояния выполнения потока.
threadCapability :: ThreadId -> IO (Int, Bool) Source
Возвращает номер возможности, на которой в данный момент выполняется поток, и булево значение, указывающее, заблокирован ли поток на этой возможности или нет. Поток блокируется на возможности, если он был создан с помощью forkOn.
Since: base-4.4.0.0
newStablePtrPrimMVar :: MVar a -> IO (StablePtr PrimMVar) Source
Создает StablePtr, который может быть передан в функцию C hs_try_putmvar(). RTS требует StablePtr к базовому MVar#, но StablePtr# может ссылаться только на поднятые типы, поэтому нам приходится жульничать, используя приведение типов.
Ожидание
threadDelay :: Int -> IO () Source
Приостанавливает текущий поток на заданное количество микросекунд (только GHC).
Нет гарантии, что поток будет немедленно перепланирован по истечении задержки, но поток никогда не продолжит выполнение раньше, чем указано.
Будьте осторожны, чтобы не превышать maxBound :: Int, что на 32-битных машинах составляет всего 2147483647 мкс, менее 36 минут. Рассмотрите возможность использования Control.Concurrent.Thread.Delay.delay из пакета unbounded-delays.
registerDelay :: Int -> IO (TVar Bool) Source
Изменить значение возвращаемого TVar с начального значения False на True после заданного количества микросекунд. Применяются те же оговорки, что и для threadDelay.
Будьте внимательны, чтобы не превысить maxBound :: Int, которое на 32-битных машинах составляет всего 2147483647 мкс, что меньше 36 минут.
threadWaitRead :: Fd -> IO () Source
Заблокировать текущий поток до тех пор, пока данные не станут доступны для чтения в заданном дескрипторе файла (только для GHC).
Это вызовет IOError, если дескриптор файла был закрыт, пока этот поток был заблокирован. Чтобы безопасно закрыть дескриптор файла, который использовался с threadWaitRead, используйте closeFdWith.
threadWaitWrite :: Fd -> IO () Source
Заблокировать текущий поток до тех пор, пока данные не смогут быть записаны в заданный дескриптор файла (только для GHC).
Это вызовет IOError, если дескриптор файла был закрыт, пока этот поток был заблокирован. Чтобы безопасно закрыть дескриптор файла, который использовался с threadWaitWrite, используйте closeFdWith.
threadWaitReadSTM :: Fd -> IO (STM (), IO ()) Source
Возвращает действие STM, которое можно использовать для ожидания данных для чтения из дескриптора файла. Второе возвращаемое значение — действие IO, которое можно использовать для отмены интереса к дескриптору файла.
threadWaitWriteSTM :: Fd -> IO (STM (), IO ()) Source
Возвращает действие STM, которое можно использовать для ожидания возможности записи в дескриптор файла. Второе возвращаемое значение — действие IO, которое можно использовать для отмены интереса к дескриптору файла.
Аргументы
| :: (Fd -> IO ()) | Действие низкого уровня, выполняющее реальное закрытие. |
| -> Fd | Дескриптор файла для закрытия. |
| -> IO () |
Закрыть дескриптор файла безопасным для конкурентного доступа способом (только для GHC). Если вы используете threadWaitRead или threadWaitWrite для выполнения блокирующего ввода-вывода, вы обязательно должны использовать эту функцию для закрытия дескрипторов файлов, иначе заблокированные потоки могут не быть разблокированы.
Любые потоки, заблокированные на дескрипторе файла с помощью threadWaitRead или threadWaitWrite, будут разблокированы путем выброса исключений IO.
Счётчик и предел выделения памяти
setAllocationCounter :: Int64 -> IO () Source
Каждый поток имеет счётчик выделения памяти, отслеживающий количество выделенной памяти потоком. Счётчик инициализируется нулём, а setAllocationCounter устанавливает текущее значение. Счётчик выделения памяти отсчитывает *вниз*, так что в отсутствие вызова setAllocationCounter его значение является отрицанием количества байтов памяти, выделенной потоком.
С этим счётчиком можно выполнить два действия:
- Использовать его как простой механизм профилирования, с помощью
getAllocationCounter. - Использовать его как ограничение ресурсов. См.
enableAllocationLimit.
Отслеживание выделения памяти точное только приблизительно до 4Кбайт.
Since: base-4.8.0.0
getAllocationCounter :: IO Int64 Source
Возвращает текущее значение счётчика выделения памяти для текущего потока.
Since: base-4.8.0.0
enableAllocationLimit :: IO () Source
Включает возможность использования счётчика выделения памяти в качестве ограничения для текущего потока. Когда ограничение по выделению памяти включено, если счётчик выделения памяти уменьшится ниже нуля, потоку будет отправлено асинхронное исключение AllocationLimitExceeded. В этом случае счётчик сбрасывается (по умолчанию до 100К, но настраиваемо с помощью опции +RTS -xq) для того, чтобы он мог обработать исключение и выполнить необходимые операции по очистке. Если он исчерпает это дополнительное ограничение, будет отправлено ещё одно исключение AllocationLimitExceeded, и так далее. Как и другие асинхронные исключения, исключение AllocationLimitExceeded откладывается, пока поток находится внутри mask или обработчика исключений в catch.
Обратите внимание, что выделение памяти не связано с *актуальной памятью*, также известной как *резиденцией кучи*. Поток может выделить большое количество памяти и сохранить всё от нуля до всего её объёма. Лучше думать об ограничении выделения как об ограничении *времени CPU*, а не как об ограничении памяти.
По сравнению с использованием таймаутов, ограничения на выделение памяти не учитывают время, затраченное на блокировку или выполнение внешних вызовов.
Since: base-4.8.0.0
disableAllocationLimit :: IO () Source
Отключить обработку лимита выделения памяти для текущего потока.
Since: base-4.8.0.0
TVars
Моноид, поддерживающий атомарные транзакции памяти.
Примеры
| Alternative STM Source |
Берёт первое не- Since: base-4.8.0.0 |
| Applicative STM Source | Since: base-4.8.0.0 |
| Functor STM Source | Since: base-4.3.0.0 |
| Monad STM Source | Since: base-4.3.0.0 |
| MonadPlus STM Source |
Берёт первое не- Since: base-4.3.0.0 |
| Monoid a => Monoid (STM a) Source | Since: base-4.17.0.0 |
| Semigroup a => Semigroup (STM a) Source | Since: base-4.17.0.0 |
Определено в GHC.Internal.Conc.Sync Методы(<>) :: STM a -> STM a -> STM a Исходный код sconcat :: NonEmpty (STM a) -> STM a Исходный код stimes :: Integral b => b -> STM a -> STM a Исходный код |
atomically :: STM a -> IO a Исходный код
Выполнить серию действий STM атомарно.
Использование atomically внутри unsafePerformIO или unsafeInterleaveIO нарушает некоторые гарантии, предоставляемые STM. Это позволяет запускать транзакцию внутри другой транзакции, в зависимости от того, когда вычисляется лямбда-выражение. Если попытка вложенной транзакции имеет место, runtime выбрасывает исключение. Безопасное использование atomically внутри unsafePerformIO или unsafeInterleaveIO возможно, но компилятор не исключает программы, которые могут пытаться выполнить вложенные транзакции, что означает, что программист должен уделять особое внимание предотвращению таких ситуаций.
Однако существуют функции для создания транзакционных переменных, которые всегда можно безопасно вызывать в unsafePerformIO. См.: newTVarIO, newTChanIO, newBroadcastTChanIO, newTQueueIO, newTBQueueIO, и newTMVarIO.
Использование unsafePerformIO внутри atomically также опасно, но по другим причинам. См. unsafeIOToSTM для получения более подробной информации об этом.
retry :: STM a Исходный код
Повторить выполнение текущей памяти транзакции, потому что она обнаружила значения в TVars, которые означают, что выполнение не должно продолжаться (например, TVars представляют собой общий буфер, который теперь пуст). Реализация может заблокировать поток до тех пор, пока один из TVars, который она прочитала, не будет обновлен. (Только GHC)
orElse :: STM a -> STM a -> STM a Исходный код
Композиция двух альтернативных действий STM (только GHC).
Если первое действие завершается без повтора, то оно формирует результат orElse. В противном случае, если первое действие повторяется, то второе действие выполняется вместо него. Если оба действия повторяются, то orElse в целом повторяется.
throwSTM :: Exception e => e -> STM a Исходный код
Вариант throw, который может быть использован только внутри монады STM.
Выбрасывание исключения в STM прерывает транзакцию и распространяет исключение. Если исключение перехвачено с помощью catchSTM, только изменения, заключенные в блок перехвата, отменяются; изменения, сделанные вне catchSTM, сохраняются.
Если исключение не перехвачено внутри STM, оно повторно выбрасывается atomically, и вся STM отменяется.
Хотя throwSTM имеет тип, который является экземпляром типа throw, эти две функции отличаются:
throw e `seq` x ===> throw e throwSTM e `seq` x ===> x
Первый пример вызовет исключение e, а второй - нет. Фактически, throwSTM будет вызывать исключение только при использовании внутри монады STM. Вариант throwSTM должен использоваться вместо throw для поднятия исключения внутри монады STM, потому что он гарантирует порядок относительно других операций STM, в то время как throw этого не делает.
catchSTM :: Exception e => STM a -> (e -> STM a) -> STM a Исходный код
Обработка исключений внутри действий STM.
catchSTM m f перехватывает любое исключение, брошенное m с помощью throwSTM, используя функцию f для обработки исключения. Если происходит исключение, любые изменения, внесенные m, отменяются, но изменения до m сохраняются.
data TVar a Исходный код
Обменные места памяти, поддерживающие атомарные транзакции памяти.
Экземпляры
| Eq (TVar a) Исходный код | С момента: base-4.8.0.0 |
Определено в GHC.Internal.Conc.Sync | |
newTVar :: a -> STM (TVar a) Исходный код
Создать новую TVar, содержащую предоставленное значение
newTVarIO :: a -> IO (TVar a) Исходный код
Вариант IO newTVar. Это полезно для создания TVar верхнего уровня с помощью unsafePerformIO, поскольку использование atomically внутри unsafePerformIO невозможно.
readTVar :: TVar a -> STM a Исходный код
Возвращает текущее значение, хранящееся в TVar.
readTVarIO :: TVar a -> IO a Исходный код
Возвращает текущее значение, хранящееся в TVar. Это эквивалентно
readTVarIO = atomically . readTVar
но работает намного быстрее, так как не выполняет полную транзакцию, а просто считывает текущее значение TVar.
writeTVar :: TVar a -> a -> STM () Исходный код
Записать предоставленное значение в TVar.
unsafeIOToSTM :: IO a -> STM a Source
Опасно выполняет IO в STM монаде. Осторожно: это очень опасно.
- Реализация STM часто будет запускать транзакции несколько раз, поэтому вам нужно быть готовым к этому, если ваша IO имеет побочные эффекты.
- Реализация STM будет прерывать транзакции, которые, как известно, недействительны и требуют перезапуска. Это может произойти в середине
unsafeIOToSTM, поэтому убедитесь, что вы не получаете никаких ресурсов, требующих освобождения (обработчики исключений игнорируются при прерывании транзакции). Это включает в себя выполнение любой IO с использованием дескрипторов файлов, например. Неправильное выполнение этой операции, вероятно, приведёт к случайным тупикам. - Транзакция может увидеть несогласованное состояние памяти, когда выполняется IO. Инварианты, которые вы ожидаете, будут истинными на протяжении всего вашего приложения, могут быть ложными внутри транзакции из-за способа реализации транзакций. Обычно это не было бы заметно программисту, но использование
unsafeIOToSTMможет это продемонстрировать.
Разное
withMVar :: MVar a -> (a -> IO b) -> IO b Source
Предоставьте действие IO с текущим значением MVar. MVar будет пустым в течение времени, пока выполняется действие.
type HandlerFun = ForeignPtr Word8 -> IO () Source
setHandler :: Signal -> Maybe (HandlerFun, Dynamic) -> IO (Maybe (HandlerFun, Dynamic)) Source
runHandlers :: ForeignPtr Word8 -> Signal -> IO () Source
ensureIOManagerIsRunning :: IO () Source
ioManagerCapabilitiesChanged :: IO () Source
setUncaughtExceptionHandler :: (SomeException -> IO ()) -> IO () Source
getUncaughtExceptionHandler :: IO (SomeException -> IO ()) Source
reportError :: SomeException -> IO () Source
reportStackOverflow :: IO () Source
reportHeapOverflow :: IO () Source
© The University of Glasgow and others
Licensed under a BSD-style license (see top of the page).
https://downloads.haskell.org/~ghc/9.12.1/docs/libraries/base-4.21.0.0-8e62/GHC-Conc.html