Ответ 1
Программы, скомпилированные без -threaded
, используют один поток ОС для запуска всех потоков Haskell. Внешние вызовы блокируют все запущенные потоки Haskell.
Программы, скомпилированные с помощью -threaded
, могут использовать несколько потоков ОС для одновременного запуска нескольких потоков Haskell (количество потоков ОС может управляться опцией +RTS -N
). Зарубежные вызовы, отмеченные safe
, не будут блокировать другие запущенные потоки Haskell (поэтому может быть полезно использовать -threaded
даже с +RTS -N1
, если у вас есть несколько потоков Haskell и вызывать внешние вызовы, которые могут занять много времени). Внешние вызовы, отмеченные unsafe
, реализованы как простые вызовы встроенных функций в GHC и блокируют вызванный ими поток ОС.
Что касается вашего первого источника, в нем описывается, что происходит, когда внешний вызов выдается с точки зрения одной возможности. A возможность определяется как виртуальный процессор для запуска кода Haskell, а в потоковом RTS соответствует коллекции потоков ОС, только одна из которых запущена Haskell в любое время (другие потоки ОС используются для создания внешних вызовов без блокировки потоков Haskell). Когда поток Haskell создает внешний вызов safe
, он помещается в список приостановленных потоков и возможность предоставляется другому потоку Haskell.
Связанный поток Haskell имеет фиксированный связанный поток ОС для выполнения внешних вызовов. У несвязанного потока нет связанного потока ОС: внешние вызовы из этого потока могут быть сделаны в любом потоке ОС. Связанные потоки используются для взаимодействия с библиотеками, для которых важно, какие вызовы в библиотеку сделаны из потока ОС, такого как OpenGL, который сохраняет свой контекст рендеринга в локальном состоянии OS-thread.
Дополнительную информацию можно найти в руководстве GHC и в следующей статье:
Расширение интерфейса внешних функций Haskell с помощью Concurrency
Симон Марлоу, Саймон Пейтон Джонс и Вольфганг Таллер, Хаскелл'04