GHC.Conc.Sync
| Copyright | (c) The University of Glasgow 1994-2002 |
|---|---|
| License | see libraries/base/LICENSE |
| Maintainer | cvs-ghc@haskell.org |
| Stability | internal |
| Portability | non-portable (GHC extensions) |
| Safe Haskell | Unsafe |
| 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. Надеюсь, этот недостаток будет исправлен позже.
Экземпляры
| Eq ThreadId | С версии: base-4.2.0.0 |
| Ord ThreadId | С версии: base-4.2.0.0 |
Определено в GHC.Conc.Sync | |
| Show ThreadId | С версии: base-4.2.0.0 |
Разветвление и тому подобное
forkIO :: IO () -> IO ThreadId Source
Создаёт новый поток для выполнения вычисления IO, переданного в качестве первого аргумента, и возвращает ThreadId вновь созданного потока.
Новый поток будет лёгким, несвязанным потоком. Внешние вызовы, сделанные этим потоком, не гарантируется, что будут сделаны каким-либо конкретным потоком ОС; если вам необходимо, чтобы внешние вызовы выполнялись конкретным потоком ОС, используйте forkOS вместо этого.
Новый поток наследует замаскированное состояние родительского (см. mask).
Вновь созданный поток имеет обработчик исключений, который игнорирует исключения BlockedIndefinitelyOnMVar, BlockedIndefinitelyOnSTM и ThreadKilled, и передаёт все остальные исключения обработчику неперехваченных исключений.
forkIOWithUnmask :: ((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId Source
Как forkIO, но дочернему потоку передаётся функция, которая может использоваться для снятия маски с асинхронных исключений. Эта функция обычно используется следующим образом
... mask_ $ forkIOWithUnmask $ \unmask ->
catch (unmask ...) handler
так, чтобы обработчик исключений в дочернем потоке был установлен с замаскированными асинхронными исключениями, а основная часть дочернего потока выполнялась в незамаскированном состоянии.
Обратите внимание, что функция unmask, переданная дочернему потоку, должна использоваться только в этом потоке; поведение не определено, если она вызывается в другом потоке.
С версии: base-4.4.0.0
Подобно 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 с поддержкой отладки. Этот идентификатор будет использоваться в выходных данных отладки для упрощения различения различных потоков (в противном случае у вас будет только адрес объекта состояния потока в куче).
Другие приложения, такие как графический отладчик Concurrent Haskell Debugger (http://www.informatik.uni-kiel.de/~fhu/chd/), также могут перегрузить labelThread для своих целей.
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
data ThreadStatus Source
Текущий статус потока
Краткое описание конструкторов
| ThreadRunning | поток в данный момент выполняется или готов к выполнению |
| ThreadFinished | поток завершен |
| ThreadBlocked BlockReason | поток заблокирован на некотором ресурсе |
| ThreadDied | поток получил неперехваченное исключение |
Instances
| Eq ThreadStatus | Since: base-4.3.0.0 |
Defined in GHC.Conc.Sync Methods(==) :: ThreadStatus -> ThreadStatus -> Bool Source (/=) :: ThreadStatus -> ThreadStatus -> Bool Source | |
| Ord ThreadStatus | Since: base-4.3.0.0 |
Defined in GHC.Conc.Sync Methodscompare :: 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 | |
| Show ThreadStatus | Since: base-4.3.0.0 |
Defined in GHC.Conc.Sync MethodsshowsPrec :: Int -> ThreadStatus -> ShowS Source show :: ThreadStatus -> String Source showList :: [ThreadStatus] -> ShowS Source | |
data BlockReason Source
Краткое описание конструкторов
| BlockedOnMVar | заблокирован на |
| BlockedOnBlackHole | заблокирован на вычислении, выполняемом другим потоком |
| BlockedOnException | заблокирован в |
| BlockedOnSTM | заблокирован в |
| BlockedOnForeignCall | в данный момент выполняется внешний вызов |
| BlockedOnOther | заблокирован на каком-то другом ресурсе. Без |
Примеры использования
| Eq BlockReason | С момента: base-4.3.0.0 |
Определено в GHC.Conc.Sync Методы(==) :: BlockReason -> BlockReason -> Bool Исходный код (/=) :: BlockReason -> BlockReason -> Bool Исходный код | |
| Ord BlockReason | С момента: base-4.3.0.0 |
Определено в GHC.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.Conc.Sync МетодыshowsPrec :: Int -> BlockReason -> ShowS Исходный код show :: BlockReason -> Строка Исходный код showList :: [BlockReason] -> ShowS Исходный код | |
threadStatus :: ThreadId -> IO ThreadStatus Исходный код
threadCapability :: ThreadId -> IO (Целое число, Булево значение) Исходный код
Возвращает номер ресурса, на котором в данный момент выполняется поток, и булево значение, указывающее, заблокирован ли поток к этому ресурсу. Поток заблокирован к ресурсу, если он был создан с помощью forkOn.
С момента: base-4.4.0.0
newStablePtrPrimMVar :: MVar () -> IO (StablePtr PrimMVar) Исходный код
Создаёт StablePtr, который можно передать в функцию C hs_try_putmvar(). RTS требует StablePtr к базовому MVar#, но StablePtr# может ссылаться только на повышенные типы, поэтому мы вынуждены обмануть, принудительно преобразуя типы.
data PrimMVar Исходный код
Счётчик и квота выделения памяти
setAllocationCounter :: Int64 -> IO () Исходный код
Каждый поток имеет счётчик выделения памяти, который отслеживает, сколько памяти было выделено потоком. Счётчик инициализируется нулём, и setAllocationCounter устанавливает текущее значение. Счётчик выделения памяти отсчитывается *вниз*, поэтому в отсутствие вызова setAllocationCounter его значение является отрицанием количества выделенных байтов памяти потоком.
С этим счётчиком можно сделать две вещи:
- Использовать его как простой механизм профилирования с помощью
getAllocationCounter. - Использовать его как ограничение ресурсов. См.
enableAllocationLimit.
Отчёт о выделении памяти точен только примерно до 4 Кб.
С момента: base-4.8.0.0
getAllocationCounter :: IO Int64 Исходный код
Возвращает текущее значение счётчика выделения памяти для текущего потока.
С момента: base-4.8.0.0
enableAllocationLimit :: IO () Исходный код
Включает возможность использования счётчика выделения памяти в качестве ограничения для текущего потока. Когда ограничение выделения памяти включено, если счётчик выделения памяти упадёт ниже нуля, поток получит асинхронное исключение AllocationLimitExceeded. В этом случае счётчик сбрасывается (по умолчанию до 100 Кб, но настраиваемое с помощью параметра +RTS -xq), чтобы он мог обработать исключение и выполнить необходимые действия по очистке. Если он исчерпает это дополнительное разрешение, будет отправлено другое исключение AllocationLimitExceeded, и так далее. Как и другие асинхронные исключения, исключение AllocationLimitExceeded откладывается, пока поток находится внутри mask или обработчике исключений в catch.
Обратите внимание, что выделение памяти не связано с живой памятью, также известной как обитанием в куче. Поток может выделить большое количество памяти и сохранить от нуля до всего. Лучше думать об ограничении выделения как об ограничении времени работы ЦП, а не как об ограничении памяти.
По сравнению с использованием тайм-аутов, ограничения выделения памяти не учитывают время, потраченное на ожидание или выполнение внешних вызовов.
Since: base-4.8.0.0
disableAllocationLimit :: IO () Source
Отключить обработку лимита выделения памяти для текущего потока.
Since: base-4.8.0.0
TVars
Монад, поддерживающий атомарные транзакции памяти.
Экземпляры
| Monad STM | Since: base-4.3.0.0 |
| Functor STM | Since: base-4.3.0.0 |
| Applicative STM | Since: base-4.8.0.0 |
| MonadPlus STM | Since: base-4.3.0.0 |
| Alternative STM | Since: base-4.8.0.0 |
atomically :: STM a -> IO a Source
Выполнить серию действий 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 Source
Составление двух альтернативных действий STM (только GHC).
Если первое действие завершается без повторной попытки, то оно формирует результат orElse. В противном случае, если первое действие повторяется, то вместо него выполняется второе действие. Если оба действия повторяются, то orElse в целом повторяется.
throwSTM :: Exception e => e -> STM a Source
Вариант throw, который можно использовать только внутри монады STM.
Выброс исключения в STM прерывает транзакцию и распространяет исключение. Если исключение перехвачено через catchSTM, только изменения, заключенные в блок catch, отменяются; изменения, сделанные за пределами 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 Source
Обработка исключений внутри действий STM.
catchSTM m f перехватывает любое исключение, выброшенное m с помощью throwSTM, используя функцию f для обработки исключения. Если исключение выброшено, все изменения, внесённые m, отменяются, но изменения, внесённые до m, сохраняются.
Локальные места памяти с поддержкой атомных операций транзакции.
Экземпляры
newTVar :: a -> STM (TVar a) Source
Создание нового TVar, содержащего предоставленное значение.
newTVarIO :: a -> IO (TVar a) Source
Вариант IO функции newTVar. Это полезно для создания глобальных TVar с использованием unsafePerformIO, поскольку использование atomically внутри unsafePerformIO невозможно.
readTVar :: TVar a -> STM a Source
Возвращает текущее значение, хранящееся в TVar.
readTVarIO :: TVar a -> IO a Source
Возвращает текущее значение, хранящееся в 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. Инварианты, которые вы ожидаете в вашей программе, могут не выполняться внутри транзакции из-за способа реализации транзакций. Обычно это не видно программисту, но использование
unsafeIOToSTMможет его раскрыть.
Разное
withMVar :: MVar a -> (a -> IO b) -> IO b Source
Обеспечивает выполнение действия с текущим значением 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/8.10.2/docs/html/libraries/base-4.14.1.0/GHC-Conc-Sync.html