Короткая версия: не используйте потоки для этого, используйте процессы. Убийство запущенного процесса, вероятно, является наилучшим достижением в этой ситуации в целом.
Длинный ответ: во-первых, полезно прояснить небольшую путаницу в вопросе.
все, нет такой вещи как "бегущий Promise
"; Promise
- это структура данных для передачи результата асинхронной операции. Блок start
действительно выполняет три вещи:
- Создание
Promise
(к которому он относится) - Планирование некоторого кода для запуска
- Организация этого результат выполнения этого кода отражается в сохранении или нарушении
Promise
Это может звучать немного академично c, но на самом деле имеет значение: Promise
не знает, что в конечном итоге в конечном итоге он останется или сломается.
Во-вторых, блок start
не - по крайней мере со встроенным планировщиком - не поддерживается потоком, а работает в пуле потоков. Даже если бы вы могли найти способ «убрать» поток, планировщик пула потоков не будет доволен тем, что один из потоков, которые он ожидает съесть из рабочей очереди при исчезновении. Вы можете написать свой собственный планировщик, который действительно каждый раз будет работать с потоком fre sh, но это еще не полное решение: что если часть кода, которую пользователь запросил, выполняет выполнение расписаний самостоятельно, и тогда await
с? Тогда нет ни одного потока, который нужно убить, чтобы действительно остановить все.
Предположим, однако, что нам удалось решить все это, и мы получаем список из одного или нескольких потоков, которые мы действительно хотим убивать без их сотрудничества (совместные ситуации довольно просты; мы используем Promise
и проводим опрос кода, который очень часто, и die
, если это аннулирование Promise
когда-либо сохраняется / прерывается).
Любой такой механизм, который хочет иметь возможность остановить поток, заблокированный на чем-либо (не только на вычислениях, но и на операциях ввода-вывода, блокировки и т. Д. c.), Потребовал бы глубокой интеграции и взаимодействия из базовой среды выполнения (такой как MoarVM). , Например, попытка отменить поток, который в данный момент выполняет сборку мусора, приведет к катастрофе (скорее всего, к блокировке виртуальной машины в целом). Другие неудачные времена отмены могут привести к повреждению памяти, если она была на полпути через операцию, которую небезопасно прерывать, взаимоблокировки в другом месте, если уничтоженный поток удерживал блокировки, и так далее. Таким образом, нужен механизм безопасного наведения. (У нас уже есть что-то в этом роде в MoarVM, чтобы знать, когда это безопасно для G C, однако отмена подразумевает разные требования. Вероятно, она пересекает многочисленные части кодовой базы VM.)
И это еще не все : та же ситуация повторяется и на уровне языка раку. Например, Lock::Async
- это не та блокировка, о которой знает базовая среда выполнения. Вероятно, лучшее, что можно сделать, это попытаться разорвать стек вызовов и запустить все LEAVE
фазеры; таким образом, есть некоторая надежда (если люди использовали метод .protect
; если они просто вызвали lock
и unlock
явно, мы закончили). Но даже если нам удастся не утратить ресурсы (это уже большая проблема), мы все равно не будем знать - в целом - убил ли код, который мы убили, мир в каком-либо непротиворечивом состоянии. В контексте REPL это может привести к сомнительным результатам в последующих исполнениях, которые получают доступ к тому же глобальному состоянию. Это, вероятно, раздражает, но то, что действительно пугает меня, так это то, что люди используют такой механизм отмены в производственной системе - что они и сделают, если мы его реализуем.
Таким образом, для реализации такой функции потребуется значительное количество трудная работа во время выполнения и самого Ракудо, и в результате получился бы огромный леггинс (я даже не перечислял все вещи, которые могли бы ошибаться, только первые несколько, которые приходили на ум). В отличие от этого, уничтожение процесса очищает все ресурсы, и у процесса есть собственное пространство памяти, поэтому нет проблем с согласованностью.