GHC.Conc.Sync
| Copyright | (c) The University of Glasgow 1994-2002 |
|---|---|
| License | see libraries/base/LICENSE |
| Maintainer | ghc-devs@haskell.org |
| Stability | internal |
| Portability | non-portable (GHC extensions) |
| Safe Haskell | None |
| Language | Haskell2010 |
Описание
Основные средства параллелизма.
Потоки
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 | |
fromThreadId :: ThreadId -> Word64 Source
Сопоставляет поток с целочисленным идентификатором, который является уникальным в текущем процессе.
Since: base-4.19.0.0
showThreadId :: ThreadId -> String Source
myThreadId :: IO ThreadId Source
Возвращает ThreadId вызывающего потока (только GHC).
killThread :: ThreadId -> IO () Source
killThread raises the ThreadKilled exception in the given thread (GHC only).
killThread tid = throwTo tid ThreadKilled
throwTo :: Exception e => ThreadId -> e -> IO () Source
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, за исключением того, что исключение вызывается как асинхронное исключение. Это означает, что если есть заключительное чистое вычисление, что будет иметь место, если текущая операция ввода-вывода находится внутри unsafePerformIO или unsafeInterleaveIO, это вычисление не заменяется исключением постоянно, а приостанавливается так, как будто оно получило асинхронное исключение.
Обратите внимание, что если throwTo вызывается с текущей нитью в качестве целевой, исключение будет вызвано, даже если нить в данный момент находится внутри mask или uninterruptibleMask.
Действие yield позволяет (вынуждает в реализации кооперативной многозадачности) контекстно-переключаться на любую другую в данный момент готовую нить (если таковые имеются) и иногда полезно при реализации абстракций параллелизма.
labelThread :: ThreadId -> String -> IO () Source
labelThread сохраняет строку в качестве идентификатора этой нити. Этот идентификатор будет использоваться в отладочном выводе, чтобы упростить различение различных нитей (иначе у вас будет только адрес объекта состояния нити в куче). Он также отправляет событие в журнал событий RTS.
labelThreadByteArray# :: ThreadId -> ByteArray# -> IO () Source
labelThreadByteArray# устанавливает метку нити на заданную строку UTF-8, содержащуюся в ByteArray#.
Since: base-4.18
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
threadLabel :: ThreadId -> IO (Maybe String) Source
Запрос метки нити, возвращая Nothing если метка нити не была установлена.
Since: base-4.18
data ThreadStatus Source
Текущее состояние нити
Конструкторы
| ThreadRunning | нить в данный момент готова или запущена |
| ThreadFinished | нить завершена |
| ThreadBlocked BlockReason | нить заблокирована на некотором ресурсе |
| ThreadDied | нить получила необработанное исключение |
Примеры
| Show ThreadStatus Исходный код | С момента: base-4.3.0.0 |
Определено в GHC.Internal.Conc.Sync МетодыshowsPrec :: Int -> ThreadStatus -> ShowS Исходный код show :: ThreadStatus -> Строка Исходный код showList :: [ThreadStatus] -> ShowS Исходный код | |
| Eq ThreadStatus Исходный код | С момента: base-4.3.0.0 |
Определено в GHC.Internal.Conc.Sync Методы(==) :: ThreadStatus -> ThreadStatus -> Булево Исходный код (/=) :: ThreadStatus -> ThreadStatus -> Булево Исходный код | |
| Ord ThreadStatus Исходный код | С момента: base-4.3.0.0 |
Определено в GHC.Internal.Conc.Sync Методыcompare :: ThreadStatus -> ThreadStatus -> Порядок Исходный код (<) :: ThreadStatus -> ThreadStatus -> Булево Исходный код (<=) :: ThreadStatus -> ThreadStatus -> Булево Исходный код (>) :: ThreadStatus -> ThreadStatus -> Булево Исходный код (>=) :: ThreadStatus -> ThreadStatus -> Булево Исходный код max :: ThreadStatus -> ThreadStatus -> ThreadStatus Исходный код min :: ThreadStatus -> ThreadStatus -> ThreadStatus Исходный код | |
data ПричинаБлокировки Исходный код
Конструкторы
| BlockedOnMVar | заблокировано на |
| BlockedOnBlackHole | заблокировано на вычислении, выполняемом другой нитью |
| BlockedOnException | заблокировано в |
| BlockedOnSTM | заблокировано в |
| BlockedOnForeignCall | в настоящее время выполняется внешний вызов |
| BlockedOnOther | заблокировано на другом ресурсе. Без |
Примеры использования
| Show BlockReason Исходный код | С момента: base-4.3.0.0 |
Определено в GHC.Internal.Conc.Sync МетодыshowsPrec :: Int -> BlockReason -> ShowS Исходный код show :: BlockReason -> Строка Исходный код showList :: [BlockReason] -> ShowS Исходный код | |
| 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 -> Порядок Исходный код (<) :: BlockReason -> BlockReason -> Bool Исходный код (<=) :: BlockReason -> BlockReason -> Bool Исходный код (>) :: BlockReason -> BlockReason -> Bool Исходный код (>=) :: BlockReason -> BlockReason -> Bool Исходный код max :: BlockReason -> BlockReason -> BlockReason Исходный код min :: BlockReason -> BlockReason -> BlockReason Исходный код | |
threadStatus :: Идентификатор потока -> IO Статус потока Исходный код
Запрос текущего состояния выполнения потока.
threadCapability :: Идентификатор потока -> IO (Целое число, Булево значение) Исходный код
Возвращает номер возможности, на которой в данный момент выполняется поток, и булево значение, указывающее, заблокирован ли поток к этой возможности или нет. Поток заблокирован к возможности, если он был создан с forkOn.
С момента: base-4.4.0.0
Разветвление и подобное
forkIO :: IO () -> IO Идентификатор потока Исходный код
Создает новый поток для выполнения вычисления IO, переданного в качестве первого аргумента, и возвращает ThreadId вновь созданного потока.
Новый поток будет лёгким, не связанным потоком. Внешние вызовы, сделанные этим потоком, не гарантируются для выполнения в определённом потоке ОС; если требуется, чтобы внешние вызовы выполнялись в определённом потоке ОС, то используйте forkOS вместо этого.
Новый поток наследует состояние маскирования родительского потока (см. mask).
У вновь созданного потока есть обработчик исключений, который игнорирует исключения BlockedIndefinitelyOnMVar, BlockedIndefinitelyOnSTM, и ThreadKilled, и передаёт все остальные исключения обработчику необработанных исключений.
ВНИМАНИЕ: Исключение в новом потоке не будут переброшены в поток, который его создал. Это означает, что вы можете полностью не знать о проблеме, если/когда это произойдёт. Вы можете использовать библиотеку async вместо этого.
forkIOWithUnmask :: ((forall a. IO a -> IO a) -> IO ()) -> IO Идентификатор потока Исходный код
Подобно forkIO, но дочерний поток получает функцию, которая может использоваться для разблокирования асинхронных исключений. Эта функция обычно используется следующим образом
... mask_ $ forkIOWithUnmask $ \unmask ->
catch (unmask ...) handler
чтобы обработчик исключений в дочернем потоке был установлен с асинхронными исключениями, замаскированными, в то время как основная часть работы дочернего потока выполняется в разблокированном состоянии.
Обратите внимание, что функция разблокирования, переданная дочернему потоку, должна использоваться только в этом потоке; поведение не определено, если она вызывается в другом потоке.
С момента: base-4.4.0.0
forkOn :: Целое число -> IO () -> IO Идентификатор потока Исходный код
Подобно 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 Source
Подобно forkIOWithUnmask, но дочерний поток привязывается к заданному процессору, как и с помощью forkOn.
С момента выпуска: base-4.4.0.0
Способности
значение, переданное флагу +RTS -N. Это количество потоков Haskell, которые могут выполняться истинно одновременно в любой момент времени, и обычно устанавливается в соответствии с количеством физических ядер процессора на машине.
Строго говоря, лучше использовать getNumCapabilities, так как количество способностей может изменяться во время выполнения.
getNumCapabilities :: IO Int Source
Возвращает количество потоков Haskell, которые могут выполняться истинно одновременно (на отдельных физических процессорах) в любой момент времени. Чтобы изменить это значение, используйте setNumCapabilities.
С момента выпуска: base-4.4.0.0
setNumCapabilities :: Int -> IO () Source
Устанавливает количество потоков Haskell, которые могут выполняться истинно одновременно (на отдельных физических процессорах) в любой момент времени. Значение, переданное forkOn, интерпретируется по модулю этого значения. Начальное значение задаётся флагом времени выполнения +RTS -N.
Это также количество потоков, которые будут участвовать в параллельном сборке мусора. Сильно рекомендуется, чтобы количество способностей не превышало количество физических ядер процессора, и часто может быть полезно оставить одно или несколько ядер свободными, чтобы избежать конфликтов с другими процессами в системе.
С момента выпуска: base-4.5.0.0
getNumProcessors :: IO Int Source
Возвращает количество ЦП в системе.
С момента выпуска: base-4.5.0.0
Искры
Возвращает количество искр в текущем локальном пуле искр.
childHandler :: SomeException -> IO () Source
par :: a -> b -> b infixr 0 Source
pseq :: a -> b -> b infixr 0 Source
Внутренняя функция, используемая RTS для запуска искр.
PrimMVar
newStablePtrPrimMVar :: MVar a -> IO (StablePtr PrimMVar) Source
Создаёт StablePtr, который можно передавать в функцию C hs_try_putmvar(). RTS требуется StablePtr к базовому MVar#, но StablePtr# может ссылаться только на поднятые типы, поэтому приходится обманывать, принуждая к преобразованию.
Счётчик выделения и квота
setAllocationCounter :: Int64 -> IO () Source
Каждый поток имеет счётчик выделения, который отслеживает, сколько памяти было выделено потоком. Счётчик инициализируется нулём, и setAllocationCounter устанавливает текущее значение. Счётчик выделения отсчитывает *вниз*, поэтому в отсутствие вызова setAllocationCounter его значение является отрицанием количества байтов выделенной памяти потоком.
С этим счётчиком можно сделать две вещи:
- Использовать его как простой механизм профилирования с помощью
getAllocationCounter. - Использовать его как ограничение ресурсов. См.
enableAllocationLimit.
Учёт выделения памяти точный только с точностью до примерно 4 Кбайт.
С момента выпуска: base-4.8.0.0
getAllocationCounter :: IO Int64 Source
Возвращает текущее значение счётчика выделения для текущего потока.
С момента выпуска: base-4.8.0.0
enableAllocationLimit :: IO () Source
Включает обработку счётчика выделения как ограничения для текущего потока. Когда ограничение выделения включено, если счётчик выделения уменьшается до значения меньше нуля, поток получит асинхронное исключение AllocationLimitExceeded. В этом случае счётчик сбрасывается (по умолчанию до 100 Кбайт, но настраивается с помощью опции +RTS -xq), чтобы он мог обработать исключение и выполнить необходимые действия по очистке. Если он исчерпает это дополнительное разрешение, будет отправлено другое исключение AllocationLimitExceeded, и так далее. Как и другие асинхронные исключения, исключение AllocationLimitExceeded откладывается, пока поток находится внутри mask или обработчика исключений в catch.
Обратите внимание, что выделение памяти не связано с живой памятью, также известной как обитанием в куче. Поток может выделить большое количество памяти и сохранить всё от нуля до всего. Лучше рассматривать ограничение выделения как ограничение на время работы ЦП, а не как ограничение на память.
По сравнению с использованием таймаутов, ограничения выделения не учитывают время ожидания или время работы в сторонних вызовах.
С момента выпуска: base-4.8.0.0
disableAllocationLimit :: IO () Source
Отключает обработку ограничения выделения для текущего потока.
С момента выпуска: 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 |
| Полугруппа a => Полугруппа (STM a) Исходный код | С момента: base-4.17.0.0 |
Определено в GHC.Internal.Conc.Sync Методы(<>) :: STM a -> STM a -> STM a Исходный код sconcat :: Непустой список (STM a) -> STM a Исходный код stimes :: Целочисленный 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 Исходный код
Повтор выполнения текущей памяти транзакции, так как она увидела значения в TVar, которые означают, что она не должна продолжать (например, TVar представляют собой общий буфер, который теперь пуст). Реализация может заблокировать поток до тех пор, пока одна из TVar не будет обновлена. (Только GHC)
orElse :: STM a -> STM a -> STM a Исходный код
Составление двух альтернативных действий STM (только GHC).
Если первое действие выполняется без повторного выполнения, оно образует результат orElse. В противном случае, если первое действие повторяется, вместо него выполняется второе действие. Если оба действия повторяются, orElse в целом повторяется.
throwSTM :: Исключение 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 :: Исключение e => STM a -> (e -> STM a) -> STM a Исходный код
Обработка исключений внутри действий STM.
catchSTM m f перехватывает любое исключение, брошенное m с использованием throwSTM, используя функцию f для обработки исключения. Если исключение выбрасывается, все изменения, внесенные m, отменяются, но изменения, внесенные до m, сохраняются.
data TVar a Исходный код
Объекты общей памяти, которые поддерживают атомарные транзакции памяти.
Экземпляры
| Равенство (TVar a) Исходный код | С момента: base-4.8.0.0 |
Определено в GHC.Internal.Conc.Sync Методы(==) :: TVar a -> TVar a -> Булево Исходный код (/=) :: TVar a -> TVar a -> Булево Исходный код | |
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 () Source
Записывает предоставленное значение в 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 будет пустым в течение того времени, пока выполняется действие.
modifyMVar_ :: MVar a -> (a -> IO a) -> IO () Source
Изменить значение MVar.
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-Sync.html