GHC.Conc
| Авторские права | (c) Университет Глазго, 1994–2023 |
|---|---|
| Лицензия | см. libraries/base/LICENSE |
| Сопровождающие | ghc-devs@haskell.org |
| Стабильность | внутренняя |
| Переносимость | непереносимый код (расширения GHC) |
| Безопасный Haskell | Небезопасный |
| Язык | Haskell2010 |
Описание
Основные средства для параллелизма.
API этого модуля нестабилен и не предназначен для использования широкой публикой. Если вам непременно нужно от него зависеть, обязательно задайте строгую верхнюю границу версии, например base < 4.X вместо base < 5, поскольку интерфейс может быстро меняться без особых предупреждений.
ThreadId — абстрактный тип, представляющий дескриптор потока. ThreadId является экземпляром Eq, Ord и Show, причём экземпляр Ord задаёт произвольный полный порядок для ThreadId. Экземпляр Show позволяет преобразовать ThreadId с произвольным значением в строковое представление; вывод значения ThreadId иногда бывает полезен при отладке или диагностике поведения параллельной программы.
Примечание: в GHC наличие ThreadId фактически означает наличие указателя на сам поток. Поэтому сам поток нельзя будет собрать сборщиком мусора, пока вы не освободите ThreadId. Эту особенность было бы трудно исправить, продолжая поддерживать threadStatus.
Экземпляры
| Eq ThreadId Источник | Начиная с: base-4.2.0.0 |
| Ord ThreadId Источник | Начиная с: base-4.2.0.0 |
Определён в GHC.Internal.Conc.Sync | |
| Show ThreadId Источник | Начиная с: base-4.2.0.0 |
Создание потоков и тому подобное
forkIO :: IO () -> IO ThreadId Источник
Создаёт новый поток для выполнения вычисления IO, переданного первым аргументом, и возвращает ThreadId вновь созданного потока.
Новый поток будет лёгким, непривязанным потоком. Вызовы внешних функций из этого потока не гарантированно выполняются каким-либо определённым потоком ОС; если необходимо, чтобы внешние вызовы выполнялись конкретным потоком ОС, используйте вместо этого forkOS.
Новый поток наследует маскированное состояние родительского потока (см. mask).
Для вновь созданного потока задаётся обработчик исключений, который отбрасывает исключения BlockedIndefinitelyOnMVar, BlockedIndefinitelyOnSTM и ThreadKilled, а все остальные исключения передаёт обработчику неперехваченных исключений.
ПРЕДУПРЕЖДЕНИЕ: исключения в новом потоке не будут повторно вызваны в потоке, который его создал. Это означает, что вы можете совершенно не знать о возникшей проблеме. Вместо этого можно использовать библиотеку async.
forkIOWithUnmask :: ((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId Источник
Как forkIO, но дочернему потоку передаётся функция, которую можно использовать для снятия маски с асинхронных исключений. Обычно эту функцию используют следующим образом
... mask_ $ forkIOWithUnmask $ \unmask ->
catch (unmask ...) handler
чтобы обработчик исключений в дочернем потоке устанавливался при замаскированных асинхронных исключениях, а основная часть дочернего потока выполнялась в незамаскированном состоянии.
Обратите внимание: функцию снятия маски, переданную дочернему потоку, следует использовать только в этом потоке; её вызов из другого потока приводит к неопределённому поведению.
Начиная с: 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 отличается от описанного в статье «Asynchronous exceptions in 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 () Источник
labelThread сохраняет строку в качестве идентификатора этого потока. Идентификатор используется в отладочном выводе, чтобы упростить различение потоков (в противном случае доступен только адрес объекта состояния потока в куче). Функция также записывает событие в журнал событий RTS.
mkWeakThreadId :: ThreadId -> IO (Weak ThreadId) Источник
Создаёт слабую ссылку на ThreadId. Это может быть важно, если нужно хранить ссылку на ThreadId и при этом по-прежнему разрешать потоку получать семейство исключений BlockedIndefinitely (например, BlockedIndefinitelyOnMVar). Обычная ссылка на ThreadId помешает доставке исключений BlockedIndefinitely, поскольку её в любой момент можно использовать как цель для throwTo, что разблокирует поток.
С другой стороны, хранение Weak ThreadId не помешает потоку получать исключения BlockedIndefinitely. Исключение всё ещё можно вызвать для Weak ThreadId, но сначала вызывающий код должен использовать deRefWeak, чтобы определить, существует ли ещё поток.
Начиная с: base-4.6.0.0
listThreads :: IO [ThreadId] Источник
Перечисляет потоки Haskell в текущем процессе.
Начиная с: base-4.18
data ThreadStatus Источник
Текущее состояние потока
Конструкторы
| ThreadRunning | поток готов к выполнению или выполняется |
| ThreadFinished | поток завершил работу |
| ThreadBlocked BlockReason | поток заблокирован в ожидании некоторого ресурса |
| ThreadDied | поток получил неперехваченное исключение |
Экземпляры
| Eq ThreadStatus Источник | Начиная с: base-4.3.0.0 |
Определён в GHC.Internal.Conc.Sync Методы(==) :: ThreadStatus -> ThreadStatus -> Bool Источник (/=) :: ThreadStatus -> ThreadStatus -> Bool Источник | |
| Ord ThreadStatus Источник | Начиная с: base-4.3.0.0 |
Определён в GHC.Internal.Conc.Sync Методыcompare :: ThreadStatus -> ThreadStatus -> Ordering Источник (<) :: ThreadStatus -> ThreadStatus -> Bool Источник (<=) :: ThreadStatus -> ThreadStatus -> Bool Источник (>) :: ThreadStatus -> ThreadStatus -> Bool Источник (>=) :: ThreadStatus -> ThreadStatus -> Bool Источник max :: ThreadStatus -> ThreadStatus -> ThreadStatus Источник min :: ThreadStatus -> ThreadStatus -> ThreadStatus Источник | |
| Show ThreadStatus Источник | Начиная с: base-4.3.0.0 |
Определён в GHC.Internal.Conc.Sync МетодыshowsPrec :: Int -> ThreadStatus -> ShowS Источник show :: ThreadStatus -> String Источник showList :: [ThreadStatus] -> ShowS Источник | |
data BlockReason Источник
Конструкторы
| BlockedOnMVar | заблокирован на |
| BlockedOnBlackHole | заблокирован на вычислении, выполняемом другим потоком |
| BlockedOnException | заблокирован в |
| BlockedOnSTM | заблокирован в |
| BlockedOnForeignCall | в данный момент выполняется внешний вызов |
| BlockedOnOther | заблокирован на каком-либо другом ресурсе. Без |
Экземпляры
| Eq BlockReason Источник | Начиная с: base-4.3.0.0 |
Определён в GHC.Internal.Conc.Sync Методы(==) :: BlockReason -> BlockReason -> Bool Источник (/=) :: BlockReason -> BlockReason -> Bool Источник | |
| Ord BlockReason Источник | Начиная с: base-4.3.0.0 |
Определён в GHC.Internal.Conc.Sync Методыcompare :: BlockReason -> BlockReason -> Ordering Источник (<) :: BlockReason -> BlockReason -> Bool Источник (<=) :: BlockReason -> BlockReason -> Bool Источник (>) :: BlockReason -> BlockReason -> Bool Источник (>=) :: BlockReason -> BlockReason -> Bool Источник max :: BlockReason -> BlockReason -> BlockReason Источник min :: BlockReason -> BlockReason -> BlockReason Источник | |
| Show BlockReason Источник | Начиная с: base-4.3.0.0 |
Определён в GHC.Internal.Conc.Sync МетодыshowsPrec :: Int -> BlockReason -> ShowS Источник show :: BlockReason -> String Источник showList :: [BlockReason] -> ShowS Источник | |
threadStatus :: ThreadId -> IO ThreadStatus Источник
Запрашивает текущее состояние выполнения потока.
threadCapability :: ThreadId -> IO (Int, Bool) Источник
Возвращает номер capability, на которой в данный момент выполняется поток, и логическое значение, указывающее, привязан ли поток к этой capability. Поток привязан к capability, если он был создан с помощью forkOn.
Начиная с: base-4.4.0.0
newStablePtrPrimMVar :: MVar a -> IO (StablePtr PrimMVar) Источник
Создаёт StablePtr, который можно передать функции C hs_try_putmvar(). RTS требуется StablePtr для базового MVar#, но StablePtr# может ссылаться только на lifted-типы, поэтому приходится обходить это ограничение с помощью приведения типа.
Ожидание
threadDelay :: Int -> IO () Источник
Приостанавливает текущий поток на заданное число микросекунд (только GHC).
Нет гарантии, что поток будет возобновлён сразу после истечения задержки, но он ни в коем случае не продолжит выполнение раньше указанного времени.
Будьте осторожны и не превышайте maxBound :: Int, которое на 32-разрядных машинах составляет всего 2147483647 мкс, то есть менее 36 минут. Рассмотрите возможность использования Control.Concurrent.Thread.Delay.delay из пакета unbounded-delays.
registerDelay :: Int -> IO (TVar Bool) Источник
Изменяет значение возвращённого TVar с начального значения False на True по истечении заданного числа микросекунд. Также применимы оговорки, относящиеся к threadDelay.
Будьте осторожны и не превышайте maxBound :: Int, которое на 32-разрядных машинах составляет всего 2147483647 мкс, то есть менее 36 минут.
threadWaitRead :: Fd -> IO () Источник
Блокирует текущий поток, пока на указанном файловом дескрипторе не появятся данные для чтения (только GHC).
Если файловый дескриптор был закрыт, пока этот поток находился в заблокированном состоянии, будет выброшено исключение IOError. Чтобы безопасно закрыть файловый дескриптор, использовавшийся с threadWaitRead, используйте closeFdWith.
threadWaitWrite :: Fd -> IO () Источник
Блокирует текущий поток, пока в указанный файловый дескриптор нельзя будет записать данные (только GHC).
Если файловый дескриптор был закрыт, пока этот поток находился в заблокированном состоянии, будет выброшено исключение IOError. Чтобы безопасно закрыть файловый дескриптор, использовавшийся с threadWaitWrite, используйте closeFdWith.
threadWaitReadSTM :: Fd -> IO (STM (), IO ()) Источник
Возвращает действие STM, которое можно использовать для ожидания данных для чтения из файлового дескриптора. Второе возвращаемое значение — действие IO, которое можно использовать для отмены регистрации интереса к файловому дескриптору.
threadWaitWriteSTM :: Fd -> IO (STM (), IO ()) Источник
Возвращает действие STM, которое можно использовать для ожидания возможности записать данные в файловый дескриптор. Второе возвращаемое значение — действие IO, которое можно использовать для отмены регистрации интереса к файловому дескриптору.
Аргументы
| :: (Fd -> IO ()) | Низкоуровневое действие, выполняющее фактическое закрытие. |
| -> Fd | Файловый дескриптор, который нужно закрыть. |
| -> IO () |
Закрывает файловый дескриптор безопасным с точки зрения параллелизма способом (только GHC). Если вы используете threadWaitRead или threadWaitWrite для выполнения блокирующего ввода-вывода, вы обязаны использовать эту функцию для закрытия файловых дескрипторов, иначе заблокированные потоки могут не пробудиться.
Все потоки, заблокированные на файловом дескрипторе с помощью threadWaitRead или threadWaitWrite, будут разблокированы путём выбрасывания исключений IO.
Обратите внимание: в системах, повторно использующих файловые дескрипторы (например, Linux), вызов этой функции для дескриптора, которым потенциально могут пользоваться другие потоки, всегда сопряжён с гонками, если не использовать дополнительную синхронизацию.
Рекомендуется вызывать closeFdWith только после того, как другие потоки перестанут использовать указанный файловый дескриптор.
Счётчик и ограничение выделения памяти
setAllocationCounter :: Int64 -> IO () Источник
У каждого потока есть счётчик выделения памяти, отслеживающий объём памяти, выделенной этим потоком. Счётчик инициализируется нулём, а setAllocationCounter задаёт его текущее значение. Счётчик выделения памяти ведёт обратный отсчёт, поэтому, если не вызывать setAllocationCounter, его значение равно отрицательному числу байтов памяти, выделенной потоком.
Этот счётчик можно использовать двумя способами:
- В качестве простого средства профилирования с помощью
getAllocationCounter. - В качестве ограничения ресурса. См.
enableAllocationLimit.
Учёт выделенной памяти точен с погрешностью примерно 4 Кбайт.
Начиная с: base-4.8.0.0
getAllocationCounter :: IO Int64 Источник
Возвращает текущее значение счётчика выделения памяти для текущего потока.
Начиная с: base-4.8.0.0
enableAllocationLimit :: IO () Источник
Включает использование счётчика выделения памяти в качестве ограничения для текущего потока. Когда ограничение выделения памяти включено, если счётчик опустится ниже нуля, потоку будет отправлено асинхронное исключение AllocationLimitExceeded. При этом счётчик инициализируется заново (по умолчанию значением 100K, которое можно настроить параметром +RTS -xq), чтобы поток мог обработать исключение и выполнить необходимую очистку. Если этот дополнительный запас будет исчерпан, будет отправлено ещё одно исключение AllocationLimitExceeded и так далее. Как и другие асинхронные исключения, исключение AllocationLimitExceeded откладывается, пока поток находится внутри mask или обработчика исключений в catch.
Обратите внимание, что выделение памяти не связано с живой памятью, также известной как занятость кучи. Поток может выделить большой объём памяти и сохранить от нуля до всего этого объёма. Ограничение выделения памяти правильнее рассматривать как ограничение на время процессора, а не на объём памяти.
В отличие от тайм-аутов, ограничения выделения памяти не учитывают время, проведённое в заблокированном состоянии или во внешних вызовах.
Начиная с: base-4.8.0.0
disableAllocationLimit :: IO () Источник
Отключает обработку ограничения выделения памяти для текущего потока.
Начиная с: base-4.8.0.0
TVars
Монада, поддерживающая атомарные транзакции с памятью.
Экземпляры
| Alternative STM Источник |
Выбирает первое действие С версии: base-4.8.0.0 |
| Applicative STM Источник | С версии: base-4.8.0.0 |
| Functor STM Источник | С версии: base-4.3.0.0 |
| Monad STM Источник | С версии: base-4.3.0.0 |
| MonadPlus STM Источник |
Выбирает первое действие С версии: base-4.3.0.0 |
| Monoid a => Monoid (STM a) Источник | С версии: base-4.17.0.0 |
| Semigroup a => Semigroup (STM a) Источник | С версии: base-4.17.0.0 |
atomically :: STM a -> IO a Источник
Атомарно выполняет последовательность действий STM.
Использование atomically внутри unsafePerformIO или unsafeInterleaveIO нарушает некоторые гарантии, предоставляемые STM. Это позволяет выполнить транзакцию внутри другой транзакции в зависимости от того, когда вычисляется thunk. При попытке вложенной транзакции среда выполнения выбрасывает исключение. atomically можно безопасно использовать внутри unsafePerformIO или unsafeInterleaveIO, однако система типов не исключает программы, которые могут попытаться выполнить вложенные транзакции, поэтому программист должен принять особые меры, чтобы предотвратить это.
Однако существуют функции для создания транзакционных переменных, которые всегда можно безопасно вызывать в unsafePerformIO. См.: newTVarIO, newTChanIO, newBroadcastTChanIO, newTQueueIO, newTBQueueIO и newTMVarIO.
Использование unsafePerformIO внутри atomically также опасно, но по другим причинам. Подробнее см. unsafeIOToSTM.
Повторяет выполнение текущей транзакции с памятью, поскольку она прочитала значения из 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. Для выбрасывания исключения внутри монады STM предпочтительно использовать вариант throwSTM вместо throw, поскольку он гарантирует упорядочивание относительно других операций STM, тогда как throw такой гарантии не даёт.
catchSTM :: Exception e => STM a -> (e -> STM a) -> STM a Источник
Обработка исключений в действиях STM.
catchSTM m f перехватывает любое исключение, выброшенное m с помощью throwSTM, используя функцию f для обработки исключения. Если исключение выброшено, все изменения, сделанные m, откатываются, но изменения, внесённые до m, сохраняются.
Общие области памяти, поддерживающие атомарные транзакции с памятью.
Экземпляры
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 Источник
Небезопасно выполняет IO в монаде STM. Внимание: это крайне опасная операция.
- Реализация STM часто выполняет транзакции несколько раз, поэтому необходимо учитывать это, если операции IO имеют побочные эффекты.
- Реализация STM прерывает транзакции, которые заведомо некорректны и должны быть запущены заново. Это может произойти в середине
unsafeIOToSTM, поэтому не следует захватывать ресурсы, которые необходимо освободить (при прерывании транзакции обработчики исключений игнорируются). Например, сюда относится выполнение операций IO с использованием Handles. Ошибки в этом месте, скорее всего, приведут к случайным взаимным блокировкам. - Во время выполнения IO транзакция могла получить несогласованное представление памяти. Инварианты, которые, как ожидается, должны выполняться во всей программе, могут нарушаться внутри транзакции из-за особенностей реализации транзакций. Обычно программист этого не заметит, но использование
unsafeIOToSTMможет сделать это заметным.
Разное
withMVar :: MVar a -> (a -> IO b) -> IO b Источник
Предоставляет действие IO с текущим значением MVar. На время выполнения действия MVar будет пустым.
type HandlerFun = ForeignPtr Word8 -> IO () Источник
setHandler :: Signal -> Maybe (HandlerFun, Dynamic) -> IO (Maybe (HandlerFun, Dynamic)) Источник
runHandlers :: ForeignPtr Word8 -> Signal -> IO () Источник
ensureIOManagerIsRunning :: IO () Источник
ioManagerCapabilitiesChanged :: IO () Источник
setUncaughtExceptionHandler :: (SomeException -> IO ()) -> IO () Источник
getUncaughtExceptionHandler :: IO (SomeException -> IO ()) Источник
reportError :: SomeException -> IO () Источник
reportStackOverflow :: IO () Источник
reportHeapOverflow :: IO () Источник
© The University of Glasgow and others
Licensed under a BSD-style license (see top of the page).
https://downloads.haskell.org/~ghc/9.14.1/docs/libraries/base-4.22.0.0-66f8/GHC-Conc.html