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. Надеемся, что этот недостаток будет исправлен позже.
Разветвление и тому подобное
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, переданная дочернему потоку, должна использоваться только в этом потоке; поведение не определено, если она вызывается в другом потоке.
С версии: 4.4.0.0
forkOn :: Int -> IO () -> IO ThreadId Source
Как forkIO, но позволяет указать, на какой возможности должен работать поток. В отличие от потока forkIO, поток, созданный forkOn, будет оставаться на той же возможности в течение всего своего времени существования (потоки forkIO могут мигрировать между возможностями в соответствии с политикой планирования). forkOn полезно для переопределения политики планирования, когда вы заранее знаете, как лучше всего распределить потоки.
Аргумент Int указывает номер возможности (см. getNumCapabilities). Обычно возможности соответствуют физическим процессорам, но точное поведение зависит от реализации. Значение, переданное в forkOn, интерпретируется по модулю общего числа возможностей, возвращаемого getNumCapabilities.
Примечание GHC: количество возможностей указывается параметром +RTS -N при запуске программы. Возможности могут быть привязаны к фактическим ядрам процессора с помощью +RTS -qa, если это поддерживается базовой операционной системой, хотя на практике это обычно не нужно (и может даже снизить производительность в некоторых случаях — рекомендуется экспериментировать).
С версии: 4.4.0.0
forkOnWithUnmask :: Int -> ((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId Source
Как forkIOWithUnmask, но дочерний поток привязан к указанному процессору, как и в случае с forkOn.
С версии: 4.4.0.0
значение, переданное флагу +RTS -N. Это количество потоков Haskell, которые могут работать одновременно в любой момент времени, и обычно устанавливается в количество физических ядер процессора на машине.
Строго говоря, лучше использовать getNumCapabilities, поскольку количество возможностей может изменяться во время выполнения.
getNumCapabilities :: IO Int Source
Возвращает количество потоков Haskell, которые могут работать одновременно (на отдельных физических процессорах) в любой момент времени. Чтобы изменить это значение, используйте setNumCapabilities.
С версии: 4.4.0.0
setNumCapabilities :: Int -> IO () Source
Устанавливает количество потоков Haskell, которые могут работать одновременно (на отдельных физических процессорах) в любой момент времени. Число, переданное forkOn, интерпретируется по модулю этого значения. Начальное значение задаётся флагом времени выполнения +RTS -N.
Это также количество потоков, которые будут участвовать в параллельной сборке мусора. Настоятельно рекомендуется не устанавливать количество возможностей больше, чем количество физических ядер процессора, и часто бывает полезно оставить одно или несколько ядер свободными, чтобы избежать конкуренции с другими процессами на машине.
С версии: 4.5.0.0
getNumProcessors :: IO Int Source
Возвращает количество процессоров, которыми обладает машина
С версии: 4.5.0.0
Возвращает количество искр, находящихся в данный момент в локальном пуле искр
childHandler :: SomeException -> IO () Source
myThreadId :: IO ThreadId Source
Возвращает ThreadId вызывающего потока (только GHC).
killThread :: ThreadId -> IO () Source
killThread вызывает исключение ThreadKilled в данном потоке (только GHC).
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, за исключением того, что исключение выбрасывается как асинхронное исключение. Это означает, что если есть вложенное чистое вычисление, что имело бы место, если текущая операция IO находится внутри unsafePerformIO или unsafeInterleaveIO, то это вычисление не заменяется исключением навсегда, а приостанавливается, как если бы оно получило асинхронное исключение.
Обратите внимание, что если throwTo вызывается с текущим потоком в качестве цели, исключение будет вызвано даже если поток в данный момент находится внутри mask или uninterruptibleMask.
par :: a -> b -> b infixr 0 Source
pseq :: a -> b -> b infixr 0 Source
Внутренняя функция, используемая RTS для запуска искр.
Действие yield позволяет (вынуждает, в реализации кооперативной многозадачности) контекстную смену на любой другой в данный момент готовый к выполнению поток (если таковые имеются), и это иногда полезно при реализации абстракций параллелизма.
labelThread :: ThreadId -> String -> IO () Source
labelThread сохраняет строку в качестве идентификатора для данного потока, если вы построили RTS с поддержкой отладки. Этот идентификатор будет использован в выходных данных отладки для более лёгкого различения разных потоков (иначе у вас будет только адрес объекта состояния потока в куче).
Другие приложения, такие как графический отладчик Concurrent Haskell (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: 4.6.0.0
data ThreadStatus Source
Текущее состояние потока
Конструкторы
| ThreadRunning | поток в данный момент готов к запуску или запущен |
| ThreadFinished | поток завершён |
| ThreadBlocked BlockReason | поток заблокирован на некотором ресурсе |
| ThreadDied | поток получил неперехваченное исключение |
data BlockReason Source
Конструкторы
| BlockedOnMVar | заблокирован на |
| BlockedOnBlackHole | заблокирован на вычислении, которое выполняет другой поток |
| BlockedOnException | заблокирован в |
| BlockedOnSTM | заблокирован в |
| BlockedOnForeignCall | в данный момент выполняет вызов внешней функции |
| BlockedOnOther | заблокирован на другом ресурсе. Без |
threadStatus :: ThreadId -> IO ThreadStatus Source
возвращает номер способности, на которой в настоящее время выполняется поток, и булево значение, указывающее, заблокирован ли поток к этой способности или нет. Поток блокируется к способности, если он был создан с forkOn.
С момента: 4.4.0.0
Счётчик и квота выделения
setAllocationCounter :: Int64 -> IO () Источник
Каждый поток имеет счётчик выделения, который отслеживает, сколько памяти было выделено потоком. Счётчик инициализируется нулём, и setAllocationCounter устанавливает текущее значение. Счётчик выделения считает *вниз*, поэтому в отсутствие вызова setAllocationCounter его значение является отрицанием количества байтов памяти, выделенной потоком.
С этим счётчиком можно сделать две вещи:
- Использовать его как простой механизм профилирования, с
getAllocationCounter. - Использовать его как ограничение ресурсов. См.
enableAllocationLimit.
Подсчёт выделения памяти точен только до примерно 4 Кбайт.
С момента: 4.8.0.0
getAllocationCounter :: IO Int64 Источник
Возвращает текущее значение счётчика выделения для текущего потока.
С момента: 4.8.0.0
enableAllocationLimit :: IO () Источник
Включает счётчик выделения, чтобы он рассматривался как ограничение для текущего потока. Когда ограничение выделения включено, если счётчик выделения уменьшается до значения меньше нуля, поток получает асинхронное исключение AllocationLimitExceeded. В этом случае счётчик сбрасывается (по умолчанию до 100 Кбайт, но настраивается параметром +RTS -xq), чтобы он мог обработать исключение и выполнить необходимые действия по очистке. Если он исчерпает это дополнительное разрешение, отправляется другое исключение AllocationLimitExceeded, и так далее.
Обратите внимание, что выделение памяти не связано с активной памятью, также известной как резиденцией кучи. Поток может выделить большое количество памяти и сохранить всё от нуля до всего. Лучше рассматривать ограничение выделения как ограничение времени выполнения, а не как ограничение памяти.
По сравнению с использованием таймаутов, ограничения выделения не учитывают время, потраченное на ожидание или во внешних вызовах.
С момента: 4.8.0.0
disableAllocationLimit :: IO () Источник
Отключает обработку лимита выделения для текущего потока.
С момента: 4.8.0.0
TVars
Моноид, поддерживающий атомарные транзакции памяти.
Примеры использования
atomically :: STM a -> IO a Источник
Выполняет серию действий STM атомарно.
Вы не можете использовать atomically внутри unsafePerformIO или unsafeInterleaveIO. Любая попытка сделать это приведёт к ошибке во время выполнения. (Причина: это позволило бы создать транзакцию внутри транзакции, в зависимости от того, когда именно будет вычисляться ленивая запись.)
Однако, см. newTVarIO, который может быть вызван внутри unsafePerformIO, и который позволяет выделять TVars верхнего уровня.
Повторно выполняет текущую транзакцию памяти, так как она обнаружила значения в TVars, означающие, что она не должна продолжать (например, TVars представляют собой общий буфер, который теперь пуст). Реализация может заблокировать поток до тех пор, пока одна из TVars, из которой он считывал, не будет обновлена. (Только GHC)
orElse :: STM a -> STM a -> STM a Источник
Объединяет два альтернативных действия STM (только GHC). Если первое действие завершается без повторной попытки, то оно формирует результат orElse. В противном случае, если первое действие повторяется, то вместо него выполняется второе действие. Если оба действия повторяются, то orElse в целом повторяется.
throwSTM :: Exception e => e -> STM a Источник
Вариант throw, который можно использовать только в рамках моноида STM.
Выброс исключения в STM прерывает транзакцию и распространяет исключение.
Хотя throwSTM имеет тип, который является экземпляром типа throw, две функции немного отличаются:
throw e `seq` x ===> throw e throwSTM e `seq` x ===> x
Первый пример вызовет исключение e, а второй нет. На самом деле, throwSTM будет вызывать исключение только при использовании в моноиде STM. Вариант throwSTM следует использовать по предпочтению перед throw для вызова исключения внутри моноида STM, так как он гарантирует порядок относительно других операций STM, в то время как throw этого не делает.
catchSTM :: Exception e => STM a -> (e -> STM a) -> STM a Источник
Обработка исключений в действиях STM.
alwaysSucceeds :: STM a -> STM () Источник
alwaysSucceeds добавляет новое инвариантное условие, которое должно быть истинным при передаче в alwaysSucceeds в конце текущей транзакции и в конце каждой последующей транзакции. Если оно не выполняется на любом из этих этапов, то нарушающая его транзакция прерывается, а исключение, поднятое инвариантом, распространяется.
always :: STM Bool -> STM () Источник
always — это вариант alwaysSucceeds, в котором инвариант выражается как действие STM Bool, которое должно возвращать True. Возврат False или вызов исключения интерпретируются как нарушения инварианта.
Объекты общей памяти, поддерживающие атомарные транзакции памяти.
newTVar :: a -> STM (TVar a) Источник
Создаёт новый 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
modifyMVar_ :: MVar a -> (a -> IO a) -> IO () Source
setUncaughtExceptionHandler :: (SomeException -> IO ()) -> IO () Source
getUncaughtExceptionHandler :: IO (SomeException -> IO ()) Source
reportError :: SomeException -> IO () Source
reportStackOverflow :: IO () Source
© The University of Glasgow and others
Licensed under a BSD-style license (see top of the page).
https://downloads.haskell.org/~ghc/7.10.3/docs/html/libraries/base-4.8.2.0/GHC-Conc-Sync.html