GHC.Conc
| 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 | Since: base-4.2.0.0 |
| Ord ThreadId | Since: base-4.2.0.0 |
Определено в GHC.Conc.Sync | |
| Show ThreadId | Since: 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, переданная дочернему потоку, должна использоваться только в этом потоке; поведение не определено, если она вызывается в другом потоке.
Since: base-4.4.0.0
forkOn :: Int -> IO () -> IO ThreadId Source
Как 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, за исключением того, что исключение вызывается как асинхронное исключение. Это означает, что если есть окружающее чистое вычисление, что будет происходить, если текущая операция ввода-вывода находится внутри 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 с поддержкой отладки. Этот идентификатор будет использоваться в выходных данных отладки, чтобы облегчить различение разных потоков (в противном случае вы получите только адрес объекта состояния потока в куче).
Другие приложения, такие как графический отладчик 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 Исходный код
Ожидание
threadDelay :: Целое число -> IO () Исходный код
Приостанавливает текущий поток на заданное количество микросекунд (только GHC).
Нет гарантии, что поток будет перепланирован немедленно по истечении задержки, но поток никогда не будет продолжен раньше указанного времени.
registerDelay :: Целое число -> IO (TVar Булево) Исходный код
Изменяет значение возвращаемой TVar из начального значения False на True после заданного количества микросекунд. Применяются ограничения, связанные с threadDelay.
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 ()) Source
Возвращает действие STM, которое можно использовать для ожидания, пока данные не будут записаны в дескриптор файла. Второе возвращаемое значение — действие IO, которое можно использовать для отмены интереса к дескриптору файла.
Аргументы
| :: (Fd -> IO ()) | Действие низкого уровня, которое выполняет фактическое закрытие. |
| -> Fd | Дескриптор файла для закрытия. |
| -> IO () |
Закрывает дескриптор файла безопасным для конкурентного доступа способом (только GHC). Если вы используете threadWaitRead или threadWaitWrite для выполнения блокирующего ввода-вывода, вы обязаны использовать эту функцию для закрытия дескрипторов файлов, иначе заблокированные потоки могут не разбудиться.
Любые потоки, которые заблокированы на дескрипторе файла с помощью threadWaitRead или threadWaitWrite, будут разблокированы с помощью генерации исключений IO.
Счётчик и лимит выделения памяти
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.
Обратите внимание, что выделение памяти не связано с живой памятью, также известной как резиденцией в куче. Поток может выделить большое количество памяти и сохранить от нуля до всей этой памяти. Лучше представлять лимит выделения как ограничение на время работы CPU, а не на память.
По сравнению с использованием таймаутов, лимиты выделения не учитывают время блокировки или выполнение вызовов в другие модули.
С версии: base-4.8.0.0
disableAllocationLimit :: IO () Source
Отключает обработку лимита выделения для текущего потока.
С версии: base-4.8.0.0
TVars
Моноид, поддерживающий атомарные транзакции памяти.
Примеры использования
| Монадa STM | С версии: base-4.3.0.0 |
| Функтор STM | С версии: base-4.3.0.0 |
| Применительно STM | С версии: base-4.8.0.0 |
| Монадa с плюсом STM | С версии: base-4.3.0.0 |
| Альтернатива STM | С версии: base-4.8.0.0 |
atomically :: STM a -> IO a Источник
Выполнить серию действий STM атомарно.
Использование atomically внутри unsafePerformIO или unsafeInterleaveIO нарушает некоторые гарантии, предоставляемые STM. Это позволяет запускать транзакцию внутри другой транзакции, в зависимости от того, когда будет вычислено лямбда-выражение. Если попытка вложенной транзакции произойдет, runtime бросит исключение. Можно безопасно использовать atomically внутри unsafePerformIO или unsafeInterleaveIO, но компилятор не исключает программы, которые могут попытаться выполнить вложенные транзакции, что означает, что программист должен быть особенно внимателен, чтобы предотвратить это.
Однако есть функции для создания транзакционных переменных, которые всегда можно безопасно вызывать в unsafePerformIO. См.: newTVarIO, newTChanIO, newBroadcastTChanIO, newTQueueIO, newTBQueueIO, и newTMVarIO.
Использование unsafePerformIO внутри atomically также опасно, но по другим причинам. См. unsafeIOToSTM для получения дополнительной информации.
Повторить выполнение текущей транзакции памяти, потому что она увидела значения в 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 :: 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 с использованием обработчиков, например. Неверно это сделать, скорее всего, приведёт к случайным тупикам. - Во время выполнения IO транзакция могла увидеть несовместимый вид памяти. Инварианты, которые, как вы ожидаете, будут истинными на протяжении всего вашего программы, могут быть ложными внутри транзакции из-за того, как реализованы транзакции. Обычно программист этого не увидит, но использование
unsafeIOToSTMможет это раскрыть.
Разное
withMVar :: MVar a -> (a -> IO b) -> IO b Source
Предоставить действие IO с текущим значением 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 () Исходный код
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/8.10.2/docs/html/libraries/base-4.14.1.0/GHC-Conc.html