tcl threads

tokuchu

Неужели совсем-совсем никак нельзя пришибить тред в TCL, который ещё не вернулся сам в ожидание событий? Я попробовал создать 2-й интерпретатор, в нём тред. А потом пришибил интерпретатор, но тред, сцука, остался.

Maurog

зеленый, ты как будто в первый раз задаешь вопрос на форуме
опиши подробнее о чем речь, какая версия Tcl, какой код, что за потоки, биндинги или только о скрипте речь и тд

tokuchu

опиши подробнее о чем речь,
Ну мне чего-то показалось, что это будет ясно.
какая версия Tcl
Это важно? Пусть будет 8.5.
какой код
Кода нет. Только планирую.
что за потоки, биндинги
Я ни про что такое не упоминал. Не знаю что ты имеешь в виду.
или только о скрипте речь и тд
Тоже не совсем понял вопроса.
Сейчас ещё раз изложу суть проблемы. В TCL можно создавать треды с помощью расширения Threads. Вот создаётся тред с помощью thread::create. Далее этот тред переходит в режим ожидания событий посредством команды thread::wait. Когда происходит событие (например ему передаются команды для выполнения он их выполняет и потом опять переходит в ожидание. Тред можно "выключить" командой thread::release, но выключается он только когда будет в режиме ожидания. Если там выполняются команды, то он так и продолжит их выполнять. Это всё в документации так и сказано, что его насильно прикрыть нельзя.
И вот меня интересует может быть есть какой-нибудь хитрый способ замочить его всё же.
Я думал, что эту всю теорию нет смысла пересказывать тем, кто в теме вопроса, поэтому кратко написал. Возможно был не прав.

Maurog

я так понимаю, что у тебя приложение полностью скриптовое
под биндингами подразумевался взаимодействие с Си прогой, там это легко делается
потоки могут быть такими http://www.tcl.tk/man/tcl8.2.3/TclLib/Thread.htm
и могут быть согласно http://wiki.tcl.tk/1339 другими, а именно на уровне скрипта (пример: http://mkextensions.sourceforge.net/mkThreads12.htm)
если в скрипт не вывели thread::terminate, то у них была причина
во-первых, можно тебе прочитать лекции про вредность этой операции, про утечки ресурсов, а в случае элементов синхронизации, к дедлокам
во-вторых, если тебе приспичело, то можно
 
  • расширить это расширение и вывести эту команду в скрипт, благо, расширение на sf выложено с кодом
     
  • можно, написать клиенский Си-код, который доступится до внутренних хендлов этой либы и прибьте поток
     
  • можно все же грамотно сделать, а именно поддержать кенселинг на уровне скриптов и прежде, чем выходить, дождаться выхода всех потоков
     

зы: я правильно понимаю, что речь о таком расширении? http://wiki.tcl.tk/2770

Maurog

зы: я правильно понимаю, что речь о таком расширении? http://wiki.tcl.tk/2770
вот фрагмент кода оттуда:

#if 0
/* only Windows 2000 (XP, too?) has this function */
HANDLE (WINAPI *winOpenThreadProcDWORD, BOOL, DWORD);

void
ThreadpInit (void)
{
HMODULE hKernel = GetModuleHandle("kernel32.dll");
winOpenThreadProc = (HANDLE (WINAPI *DWORD, BOOL, DWORD
GetProcAddress(hKernel, "OpenThread");
}

int
ThreadpKill (Tcl_Interp *interp, long id)
{
HANDLE hThread;
int result = TCL_OK;

if (winOpenThreadProc) {
hThread = winOpenThreadProc(THREAD_TERMINATE, FALSE, id);
/*
* not to be misunderstood as "devilishly clever",
* but evil in it's pure form.
*/
TerminateThread(hThread, 666);
} else {
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp
"Can't (yet) kill threads on this OS, sorry.", NULL);
result = TCL_ERROR;
}
return result;
}
#endif


:grin: :grin: :grin:

tokuchu

Я чего-то половину слов не понял. :)
У меня чисто TCL-скрипт, а не как расширение используется. И треды свои, внутренние, с помощью того расширения, на которое ты ссылку дал. Я думал, что это какая-то стандартная фича. Т.е. там нет никакого thread::terminate и "выводить" его туда тоже не кому.
можно все же грамотно сделать, а именно поддержать кенселинг на уровне скриптов и прежде, чем выходить, дождаться выхода всех потоков
Не понимаю, что ты предлагаешь. У меня желание запустить некий тред, а потом при желании убить его, например, если пользователю надоест ждать и он нажмёт кнопочку "Stop". Но пока видимо такая возможность будет существовать только через закрытие всего приложения. Тогда мне пофигу чего ждать или нет — пусть система сама всё позакрывает что надо.
во-первых, можно тебе прочитать лекции про вредность этой операции, про утечки ресурсов
Ну я тоже думал, что наверное при этом не всё будет освобождено. Но как минимум TCL-ные ресурсы я расчитываю, что должны освобождаться. А вообще наверное даже и всё могли бы, т.к. там всё же отдельный интерпретатор порождается как я понял, он то должен понимать что у него есть. А шаред переменных, мьютексов и прочего у меня там нет.

Dasar

т.к. там всё же отдельный интерпретатор порождается как я понял,
тогда лучше отдельный процесс пускать, если уж хочется так кого-нибудь убить

tokuchu

тогда лучше отдельный процесс пускать, если уж хочется так кого-нибудь убить
С процессом возни больше. И не уверен, что с ним будет так же просто связаться.

Dasar

С процессом возни больше. И не уверен, что с ним будет так же просто связаться.
а с тредом ты как связываешься? если ты при этом утверждаешь, что интерпретаторы там разные

tokuchu

а с тредом ты как связываешься?
С помощью thread::send
если ты при этом утверждаешь, что интерпретаторы там разные
Да, так написано в документации. Там не код интерпретаторов свой, а как бы "виртуальные" интерпретаторы, у каждого более-менее своё окружение как я понимаю. Там можно и в одном треде несколько интерпретаторов создавать.

Maurog

Т.е. там нет никакого thread::terminate и "выводить" его туда тоже не кому.
ну а ты на что?:) не можешь собрать свою версию threads с терминейтом?

tokuchu

не можешь собрать свою версию threads с терминейтом?
Не, это что-то сложное. :) Ну и потом если бы это было так просто, то они бы и сами это сделали бы. Разве нет?
Тем более, что этот скрипт будет упаковываться с tclkit под вендой. Эти треды там уже встроены.

tokuchu

На самом деле мне это и не очень-то нужно сейчас. Т.е. в данном случае закрывание приложения вполне устраивает. Поэтому интерес больше академический. Т.к. потенциальные заморочки от того, что чего-то под вендой компилять надо :), утечка ресурсов и т.п. гораздо больше пользы, которую они могут принести. :)

Maurog

Ну и потом если бы это было так просто, то они бы и сами это сделали бы. Разве нет?
скрипты относятся к более высокоуровневым языкам нежели C, поэтому unsafe код им не свойственнен. все должно работать предсказуемо, в случае ошибок красивые ошибки должны летать. понимаешь?

Dasar

все должно работать предсказуемо, в случае ошибок красивые ошибки должны летать. понимаешь?
но киляться будет интерпретатор, который явно написан на C, и едва ли работа интерпретатора будет предсказуемой во время киляния

tokuchu

скрипты относятся к более высокоуровневым языкам нежели C, поэтому unsafe код им не свойственнен. все должно работать предсказуемо, в случае ошибок красивые ошибки должны летать. понимаешь?
Не совсем понимаю. Ты предлагаешь unsafe решение? И его поэтому не сделали, т.к. оно unsafe? А чем именно оно плохо?

Maurog

И его поэтому не сделали, т.к. оно unsafe?
да, так считаю. потоки терминейтить - это плохо

tokuchu

А чего, кстати, в других языках подобные проблемы возникают? В смысле есть потребность тормозить ставшие ненужными треды или я не должен этого хотеть?
Я просто тредами нигде не пользуюсь. Тут просто гуи понадобилось сваять, а там без тредов с отзывчивостью интерфейса плохо.

tokuchu

да, так считаю. потоки терминейтить - это плохо
Ну смотря как терминейтить, если всё почистить, то никакой разницы нет? Хотя наверное ты прав и там для этого нужно ещё что-то допиливать. Но с другой стороны интерпретаторы можно создавать-удалять. Не работающие, правда, но прям очень существенной разницы мне кажется нет. Разве что в треде могут какие-нибудь нескриптовые вещи использоваться (расширения или коллбеки какие). Но тут в плане ресурсов в интерпретаторе тоже это всё чистить надо.

kokoc88

В смысле есть потребность тормозить ставшие ненужными треды или я не должен этого хотеть?
Потребность есть, и она решается выходом из функции потока.

tokuchu

Потребность есть, и она решается выходом из функции потока.
В смысле тред сам завершается? С этим-то проблем нет. Я про случай когда тред занят обработкой чего-нибудь. Допустим какого-нибудь тяжёлого запроса к БД. А нам надоело ждать и мы решили его завершить.

kokoc88

Я про случай когда тред занят обработкой чего-нибудь. Допустим какого-нибудь тяжёлого запроса к БД. А нам надоело ждать и мы решили его завершить.
В таком случае красивым решением было бы начинать операцию в БД с таймаутом в самом потоке. Завершать операции извне всегда тяжелее, поэтому поток должен сам следить за таймаутом и после любого завершения операции отдавать результат куда-нибудь.

tokuchu

В таком случае красивым решением было бы начинать операцию в БД с таймаутом в самом потоке.
Я не про таймаут говорил, а про "внезапную" отмену. Т.е. когда таймаута как такового нет, но может поступить команда извне, что "хватит".

Dasar

В смысле есть потребность тормозить ставшие ненужными треды или я не должен этого хотеть?
потребность - есть, решения - нет.
более-менее отработано только киляние процессов, и там за зачисткой следит ОС, и то там возможны всякие неожиданности (например, процесс начал переписывать файл конфига, пару байт записал, а остальное не успел -> конфига больше нет)

kokoc88

Я не про таймаут говорил, а про "внезапную" отмену. Т.е. когда таймаута как такового нет, но может поступить команда извне, что "хватит".
Есть множество красивых решений данной проблемы. Простой способ: можно немедленно отобразить отмену в GUI, а потоку дать нормально отработать с таймаутом. Более продвинутый способ: одновременно ждать завершения команды в БД и сигнала отмены. Ещё один способ, немного кривой: закрыть сокет к БД из другого потока, предварительно выставив какой-нибудь bool флаг отмены. Четвёртый способ: проверить, поддерживает ли платформа отмену ожидания, например, как в Java пара Object.wait и Thread.interrupt И, конечно же, пятый способ: написать полностью асинхронное решение.

tokuchu

Ну первый способ на "красивый" нифига не тянет. А остальные требуют специальных возможностей от интерфейса БД или ещё чего.

kokoc88

Ну первый способ на "красивый" нифига не тянет.
Это зависит от конкретной реализации. Например, можно выполнять ожидание в цикле и каждые 1-5 секунд проверять факт отмены операции. Есть тысячи задач, в которых такой способ отлично работает и просто реализуется. И даже этот способ в сотни раз лучше криворукой терминации потоков.
А остальные требуют специальных возможностей от интерфейса БД или ещё чего.
Второй и третий способы вообще ничего не требуют. Если только у тебя не абсолютно примитивная платформа без возможности передавать данные между потоками без событийной модели; или без аналога pthread condition.

tokuchu

Второй и третий способы вообще ничего не требуют. Если только у тебя не абсолютно примитивная платформа без возможности передавать данные между потоками без событийной модели; или без аналога pthread condition.
Ну конечно? А асинхронный вызов к БД, который можно "одновременно" ждать?

kokoc88

Ну конечно? А асинхронный вызов к БД, который можно "одновременно" ждать?
Конечно. Синхронное ожидание вызова к БД - это ожидание condition и/или синхронная операция с сокетом. (Повторюсь, речь идёт именно о синхронном вызове, потому что все асинхронные вызовы можно ждать "одновременно", ибо без этого теряется всякий смысл слова "асинхронно".) Все известные мне языки и платформы позволяют реализовать первый, второй и третий вариант, так что реальным препятствием может быть только примитивная многопоточность в TCL.

ava3443

асинхронный вызов к БД
Не знаю, какая у тебя БД, и вообще с tcl дела пока не имел, но например в случае Oracle, судя по man oratcl, асинхронно работать можно - по ссылке и пример есть.
The optional -async argument specifies that all com-
mands allowing asynchronous (nonblocking) operation
will do so. The commands affected are: oraparse,
oraexec, orafetch and those that make use of these such
as orasql, orabindexec and oraplexec. These commands
will immediately return a code of OCI_STILL_EXECUTING
which is equal to the numeric value of -3123. Repeat
calls to these commands with the same arguements until
a return value of OCI_SUCCESS, a 0, is retuned. See
the section below on ASYNChrONOUS TRANSACTION HANDLING.

tokuchu

Конечно.
Ну так это разве не специальные возможности?
И да, например, тот интерфейс к БД, который есть у меня (ODBC какой-то) — он синхронный.
Да и не обязаны все интерфейсы быть асинхронными.
А знание того, что БД подключена через сокет и его закрывание — это уже из области хаков. В том смысле, что я тоже не назвал бы это красивым, т.к. это специфичное решение.
может быть только примитивная многопоточность в TCL
Ну это мне трудно сказать. В данном конкретном случае она, похоже, не сильно хуже, чем в других языках, т.к. проблема не только в TCL возникает. А с другой стороны оно выполнило для меня почти все свои функции, по крайней мере основные.

tokuchu

Не знаю, какая у тебя БД, и вообще с tcl дела пока не имел, но например в случае Oracle, судя по man oratcl, асинхронно работать можно - по ссылке и пример есть.
Ну а я разве говорил, что асинхронных интерфейсов в нём не существует? :)

kokoc88

Ну так это разве не специальные возможности?
Нет, это не специальные возможности.
И да, например, тот интерфейс к БД, который есть у меня (ODBC какой-то) — он синхронный.
Да и не обязаны все интерфейсы быть асинхронными.
Для реализации почти всех моих подходов асинхронные интерфейсы не являются необходимыми.
А знание того, что БД подключена через сокет и его закрывание — это уже из области хаков. В том смысле, что я тоже не назвал бы это красивым, т.к. это специфичное решение.

Я написал, что этот способ кривой. Видимо, ты это не заметил. Убийство потоков - это не просто некрасивое, это нерабочее решение.

tokuchu

Нет, это не специальные возможности.
Ну а я придерживаюсь другого мнения. Т.к. из имеющегося в наличии синхронного интерфейса я не могу получить автоматически асинхронный.
Для реализации почти всех моих подходов асинхронные интерфейсы не являются необходимыми.
И для этого тоже? Я про него писал:
Для реализации почти всех моих подходов асинхронные интерфейсы не являются необходимыми.
Я написал, что этот способ кривой.
Ну ты просто писал, что есть красивые решения и я думал, что дальше примеры.

kokoc88

Ну а я придерживаюсь другого мнения. Т.к. из имеющегося в наличии синхронного интерфейса я не могу получить автоматически асинхронный.
Из какого именно интерфейса и что ты не можешь получить? Я ещё раз повторяю, что мои подходы не требуют асинхронных интерфейсов. Хотя тут мы уже можем запутаться в разных определениях того, что именно считать асинхронным решением.
И для этого тоже? Я про него писал:
С первого по четвёртый делаются без асинхронного интерфейса обычными методами, блокирующими потоки. Хотя если ты считаешь любой метод неблокирующей проверки состояния сокета или команды в БД асинхронным, то да, требуют. Но реализуются на любой платформе простейшими средствами типа pthread condition, waitformultipleobjectsex и так далее.
Ну ты просто писал, что есть красивые решения и я думал, что дальше примеры.
Все примеры в десятки раз красивее терминации потоков.

tokuchu

Не то скопипестил. Как это можно делать синхронно:
одновременно ждать завершения команды в БД и сигнала отмены

kokoc88

Не то скопипестил. Как это можно делать синхронно:
В винде waitformultipleobjectsex, в phtreads парой compareandexchange и condition; можно ещё вспомнить про семафоры, select/poll, и так далее...

tokuchu

В винде waitformultipleobjectsex, в phtreads парой compareandexchange и condition; можно ещё вспомнить про семафоры, select/poll, и так далее...
И это по твоему синхронно? Я под этим имел в виду то, что я не могу поллить работающий запрос. Я могу это эмулировать тредами, когда я в одном жду, а другие выполняют запросы и возвращают ответ.
Но, кстати, всё равно, в случае "ожидания отмены и окончания запроса из базы" вопрос о том как замочить запрос если придёт отмена остаётся нерешённым.

kokoc88

И это по твоему синхронно?
Ожидание сразу нескольких событий в одном потоке? Да, это синхронно.
Но, кстати, всё равно, в случае "ожидания отмены и окончания запроса из базы" вопрос о том как замочить запрос если придёт отмена остаётся нерешённым.
Закрываешь запрос к БД и всё. (Подсказываю, что в способе с закрытием сокета вовсе необязательно должен быть сокет.) Многие библиотеки поддерживают закрытие/отмену вызова из другого потока. Если твоя библиотека работы с базой данных вообще ничего не поддерживает, то остаётся только дождаться завершения запроса к БД. В рабочей программе потоки не убивают.

ava3443

я не могу поллить работающий запрос
в ODBC тоже есть non-blocking режим (SQLSetConnectAttr либо SQLSetStmtAttr с аттрибутом SQL_ATTR_ASYNC_ENABLE).
Сидишь в цикле пока код возврата == SQL_STILL_EXECUTING, каждый проход цикла проверяешь, нужно ли работать дальше, или пора прерваться. Плюс спишь ещё сколько-то. Что сложного? Как тут сделать без busy-waiting - не знаю.
По-правильному, прежде чем ставить SQL_ATTR_ASYNC_ENABLE, надо проверить, поддерживается ли оно - при помощи SQLGetInfo и SQL_ASYNC_MODE.

tokuchu

Ожидание сразу нескольких событий в одном потоке? Да, это синхронно.
Ну я значит более жёсткую синхронность имел в виду. :)
Закрываешь запрос к БД и всё.
Как? Если у меня поллинга нету на него?
В рабочей программе потоки не убивают.
Ну так зачем софистикой было заниматься. Я собственно спрашивал мнения: "или я не должен этого хотеть". А ты начал говорить, что есть красивые решения, я уже обнадёжился. :)
Хотя вон Сергей говорил, что такая проблема у него тоже есть, ну по крайней мере в теории.

tokuchu

в ODBC тоже есть non-blocking режим (SQLSetConnectAttr либо SQLSetStmtAttr с аттрибутом SQL_ATTR_ASYNC_ENABLE).
Сидишь в цикле пока код возврата == SQL_STILL_EXECUTING, каждый проход цикла проверяешь, нужно ли работать дальше, или пора прерваться. Что сложного?
Чего сложного? :) Я же на TCL пишу и ODBC я использую в том смысле, что есть расширение, которое позволяет к базе через ODBC подключаться, но мне оно non-blocking режим не предоставляет. И это только пример, рассматривай это как данность в данном вопросе, что есть блокирующийся интерфейс к чему-либо.

kokoc88

Как? Если у меня поллинга нету на него?
Из другого потока. Я же написал: в методе с закрытием сокета вовсе необязательно должен быть сокет. Обычно при этом в поток, который делает запрос, возвращается какая-нибудь ошибка.
Я собственно спрашивал мнения: "или я не должен этого хотеть". А ты начал говорить, что есть красивые решения, я уже обнадёжился.
Они есть, и я их привёл, чтобы обосновать мнение, что "ты не должен хотеть убивать потоки". В чём проблема-то, я должен был просто написать "не должен" и всё? Я предпочитаю хоть как-то аргументировать свои посты.
Хотя вон Сергей говорил, что такая проблема у него тоже есть, ну по крайней мере в теории.
В .NET можно реализовать все 4 метода, и частично пятый.

kokoc88

И это только пример, рассматривай это как данность в данном вопросе, что есть блокирующийся интерфейс к чему-либо.
Надо постараться, чтобы найти такую библиотеку, в которой не реализуется вообще ничего из вышеперечисленного. А если ты её каким-то образом нашёл, то нужно понимать, что нельзя одновременно и шоколадку съесть, и кое-куда залезть. Но потоки убивать всё равно нельзя, такова жизнь...

Dasar

В .NET можно реализовать все 4 метода, и частично пятый.
нет никаких 5 методов
код бывает трех видов: синхронный, синхронный с возможностью отмены из другого треда, асинхронный.
95%(а скорее все 99%) кода - относятся к синхронному виду
писать свой асинхронный код или синхронный с возможностью отмены - на порядок геморрнее, чем синхронный
и соответственно есть три с половиной способа для отмены синхронного кода:
1. запускать отдельно и ждать когда сам завершится
2. переписать код на синхронный с возможностью отмены
3. переписать код на асинхронный
4.(использовать только если очень надо) запускать в виде процесса и прибивать процесс при отмене

kokoc88

нет никаких 5 методов
На практике есть, и больше пяти. Не путай конкретику, которую можно использовать на практике в коде, и что-то теоретическое.

Dasar

На практике есть, и больше пяти.
ты уже фактически перечисляешь каким образом можно организовать посылку сигнала синхронному коду с возможностью отмены, или с помощью каких хаков и для каких частных случаев можно превратить без переписывания синхронный код в синхронный с отменой
согласен, что таких хаков и частных случаев - вагон и маленькая тележка

kokoc88

ты уже фактически перечисляешь каким образом можно организовать посылку сигнала синхронному коду с возможностью отмены, или с помощью каких хаков и для каких частных случаев можно превратить без переписывания синхронный код в синхронный с отменой
Да, я перечисляю практические подходы к решению проблемы. Мне предлагается вместо конкретных решений просто теоретизировать?
согласен, что таких хаков и частных случаев - вагон и маленькая тележка

Чтобы поддержать дискуссию, привёл бы свои решения, которые ты использовал на практике.

Dasar

Чтобы поддержать дискуссию, привёл бы свои решения, которые ты использовал на практике.
автоматическое преобразование синхронного кода в асинхронный (вернее в continuation point-код)
использование своего интерпретатора с возможностью отмены
но это едва ли поможет ТС

tokuchu

Из другого потока. Я же написал: в методе с закрытием сокета вовсе необязательно должен быть сокет. Обычно при этом в поток, который делает запрос, возвращается какая-нибудь ошибка.
Ну как же я верну ему ошибку? Я не могу ему ничего "подсунуть". Для этого нужны те самые "специальные возможности".
Они есть, и я их привёл, чтобы обосновать мнение, что "ты не должен хотеть убивать потоки". В чём проблема-то, я должен был просто написать "не должен" и всё? Я предпочитаю хоть как-то аргументировать свои посты.
У меня "красивые" не вяжутся с "не должен". Т.е. ты вроде говоришь, что они красивые, но так же говоришь, что они плохие, но есть. У меня на это диссонанс. Если они делают плохо, то они некрасивые. Красивые — это когда хорошо, да ещё и элегантно. :)
Сергей дело говорит, что всё что ты предлагаешь — это передалать синхронный код в асинхронный. А меня интересовало как раз как можно было бы синхронный код завершить. Тем более, что в TCL он обрабатывается в отдельном интерпретаторе и в принципе есть потенциальная техническая возможность всё это дело аккуратно подчистить.

kokoc88

Ну как же я верну ему ошибку? Я не могу ему ничего "подсунуть". Для этого нужны те самые "специальные возможности".
Зачем тебе возвращать ошибку? Закрываешь запрос к БД из одного потока; библиотека для работы с БД знает, что нужно закрыть внутри (сокет, пайп или что-то другое); в поток, который ждёт выполнения операции, приходит ошибка (вообще средствами ОС).
У меня "красивые" не вяжутся с "не должен". Т.е. ты вроде говоришь, что они красивые, но так же говоришь, что они плохие, но есть. У меня на это диссонанс. Если они делают плохо, то они некрасивые. Красивые — это когда хорошо, да ещё и элегантно.
Зависит от задачи, если других вариантов нет, то красивыми считаются те решения, которые правильно работают и просто реализуются.
Сергей дело говорит, что всё что ты предлагаешь — это передалать синхронный код в асинхронный. А меня интересовало как раз как можно было бы синхронный код завершить.

Ты не понимаешь ни его, ни меня, ни мнения других людей, которые тут высказались. В общем-то для тебя достаточно стандартно: спросить какую-нибудь ерунду, а затем никого не слушать и минусовать посты. Я тебе ещё раз повторяю, что как минимум 2, 3 и 4 способы - это синхронные решения; поэтому сначала разберись в теме, и не веди себя как упёртый туповатый лошок.
Тем более, что в TCL он обрабатывается в отдельном интерпретаторе и в принципе есть потенциальная техническая возможность всё это дело аккуратно подчистить.
Нет никакой возможности "подчистить" потоки операционной системы. Прежде чем лезть спорить с кем-то в этом разделе и выставлять себя полным бараном, тебе следует хоть немного изучить документацию на любой API для терминации потоков:
 
For example, TerminateThread can result in the following problems:
•If the target thread owns a critical section, the critical section will not be released.
•If the target thread is allocating memory from the heap, the heap lock will not be released.
•If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent.
•If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.

tokuchu

Зачем тебе возвращать ошибку? Закрываешь запрос к БД из одного потока; библиотека для работы с БД знает, что нужно закрыть внутри (сокет, пайп или что-то другое); в поток, который ждёт выполнения операции, приходит ошибка (вообще средствами ОС).
Блин. Но библиотека должна же будет что-то вернтуть на запрос. Я это и назвал ошибкой. Я не могу закрыть один запрос из другого треда, если бы такая возможность была, то проблемы не было бы в принципе. В чём смысл этого "решения"?
то красивыми считаются те решения, которые правильно работают
Так они правильно или неправильно работают. А то "так не делают", "это плохо". А плохо-то почему? Мне думается, что если проблемы из-за этого есть. А если оно "правильно работает", то подразумевается, что проблем нет.
Ты не понимаешь ни его, ни меня, ни мнения других людей, которые тут высказались. ... Я тебе ещё раз повторяю, что как минимум 2, 3 и 4 способы - это синхронные решения; поэтому сначала разберись в теме, и не веди себя как упёртый туповатый лошок.
Да мне кажется это ты тут чего-то не понимаешь и пытаешься доказать непонятно что. И я тебе ещё раз повторяю, что можешь называть их как хочешь — синхроннымили и т.п. Но смысл в том, что у тебя это не простой вызов интерфейсной функции, которая возвращает результат. Тебе это трудно осознать что ли?
В общем-то для тебя достаточно стандартно: спросить какую-нибудь ерунду, а затем никого не слушать и минусовать посты.
Ну а вот для меня вот именно твои посты не принесли совсем никакой пользы, в отличии от других ораторов. Мало того, что хуйню пишешь, так ещё и до оскорблений опускаешься.
Нет никакой возможности "подчистить" потоки операционной системы.
Повторяю, я чищу потоки не операционной системы, а TCL. Хотя, конечно тут есть доля правды, т.к. интерпретатор не может контролировать что происходит, например, в расширении, наисанном на C. Он вызовет функцию и будет ждать пока она завершится. Ну как бы если ты это имел в виду, то мог бы так и написать, а не разводить тут мелодрам.
Прежде чем лезть спорить с кем-то в этом разделе и выставлять себя полным бараном, тебе следует хоть немного изучить документацию на любой API для терминации потоков:
Я тут спорил с кем-то про то, что потоки ОС можно правильно подчистить?

kokoc88

Блин. Но библиотека должна же будет что-то вернтуть на запрос.
Она и вернёт, например, ошибку "сокет закрыт"; точно таким же образом, как она вернула бы ошибку "нет связи с сервером".
Это может быть реализовано по-разному на разных платформах, но реализация как правило тривиальна. Ещё раз повторю, что если твоя библиотека и/или платформа вообще однопоточная и/или примитивная, то ты не сможешь корректно решить задачу остановки заблокированного потока по требованию.
Да мне кажется это ты тут чего-то не понимаешь и пытаешься доказать непонятно что. И я тебе ещё раз повторяю, что можешь называть их как хочешь — синхроннымили и т.п. Но смысл в том, что у тебя это не простой вызов интерфейсной функции, которая возвращает результат. Тебе это трудно осознать что ли?
У меня это абсолютно простой вызов синхронной функции, которая возвращает результат. Тебе это трудно осознать что ли?
Ну а вот для меня вот именно твои посты не принесли совсем никакой пользы, в отличии от других ораторов. Мало того, что хуйню пишешь, так ещё и до оскорблений опускаешься.
Тот факт, что ты не можешь понять того, что я пишу, вовсе не означает, что это хуйня.
Повторяю, я чищу потоки не операционной системы, а TCL. Хотя, конечно тут есть доля правды, т.к. интерпретатор не может контролировать что происходит, например, в расширении, наисанном на C. Он вызовет функцию и будет ждать пока она завершится. Ну как бы если ты это имел в виду, то мог бы так и написать, а не разводить тут мелодрам.
Судя по коду, который привели в этой теме, в используемом расширении для TCL потоки много к одному отображаются в потоки ОС. Если ты убьёшь интерпретатор, который залез в malloc, то может накрыться весь процесс. Прервать заблокированный в ядре поток на уровне TCL нельзя; а его прерывание на уровне ОС приведёт к неработоспособности программы.

Dasar

кстати, вот это http://tmml.sourceforge.net/doc/tcl/Cancel.html - это не то, что ты хочешь?

kokoc88

кстати, вот это http://tmml.sourceforge.net/doc/tcl/Cancel.html - это не то, что ты хочешь?
Где-то в теме он уже написал: у него какая-то библиотека, которая делает синхронный запрос к БД. Можно понимать это как синхронный recv например.

Dasar

тогда да, если хочется мгновенной отмены, то не подойдет.
но если достаточно варианта завершения "как только смогла", то должно покатить

tokuchu

У меня это абсолютно простой вызов синхронной функции, которая возвращает результат. Тебе это трудно осознать что ли?
Вот, например, простой вызов синхронной функции, которая возвращает результат:
result = do_some_long_calculation_or_whatever_shit(params)

При таком вызове мы ждём результата работы. Как при этом можно ещё ждать команду отмены?
Тот факт, что ты не можешь понять того, что я пишу, вовсе не означает, что это хуйня.
Когда я говорил, про хуйню — я не имел в виду, что не понятно, а то что бесполезно. Ну не всё, конечно, но по большей части ты о чём-то бесполезном понаписал, учитывая все твои замашки и прочее.
Прервать заблокированный в ядре поток
А вот в том, что он заблокирован в ядре я не был особо уверен. Т.е. в режиме ожидания он-то заблокирован, но вот сам код он может ожидать не только ответа на запрос из TCL-скрипта, но и каких-нибудь своих внутренних событий.

tokuchu

кстати, вот это http://tmml.sourceforge.net/doc/tcl/Cancel.html - это не то, что ты хочешь?
Ну это вообще API для C. Ну а так там что-то написано про такую отмену: "cancels or unwinds the script in progress soon after the next invocation of asynchronous handlers". Это не интересно. :)

kokoc88

При таком вызове мы ждём результата работы. Как при этом можно ещё ждать команду отмены?
Use exceptions, Luke!
Когда я говорил, про хуйню — я не имел в виду, что не понятно, а то что бесполезно. Ну не всё, конечно, но по большей части ты о чём-то бесполезном понаписал, учитывая все твои замашки и прочее.
Судя по твоим ответам, тебе пока что не понятно.

Dasar

многое зависит от того, что именно они называют asynchronous handlers

tokuchu

Use exceptions, Luke!
Эта функция не возвращает исключения, !
Ты умышленно меня троллишь?
Судя по твоим ответам, тебе пока что не понятно.
Да нет, это судя по тому, что ты пишешь, тебе не понятно что спрашивают и ты пишешь про что-то своё.

tokuchu

многое зависит от того, что именно они называют asynchronous handlers
Ну наверное что-нибудь приводящее к ожиданию событий типа vwait. Хотя могу ошибаться.

kokoc88

Эта функция не возвращает исключения, !
Ты умышленно меня троллишь?
Нет, я пытаюсь выяснить, как твоя функция возвращает ошибку. Точно так же, один в один, она вернёт ошибку при прерывании ожидания из другого потока.
Да нет, это судя по тому, что ты пишешь, тебе не понятно что спрашивают и ты пишешь про что-то своё.
Конечно, мне не до конца понятно, что именно ты спрашиваешь. Только проблема не во мне.

kokoc88

многое зависит от того, что именно они называют asynchronous handlers
Может статься, что любое ожидание в этом языке приводит к выпаданию в message loop, и тогда мы приходим к решению вида Object.wait и Thread.interrupt Но это я уже философствую, лень читать документацию.

tokuchu

Нет, я пытаюсь выяснить, как твоя функция возвращает ошибку. Точно так же, один в один, она вернёт ошибку при прерывании ожидания из другого потока.
Это тут при чём?
1) Как это относится к случаю "ждём одновременно отмену и возврат ответа"?
2) Ну да, ошибки как-то возвращаются. Это тут при чём? С этим вопросов нет. Но как другой поток прервёт ожидание? Для этого нужна спецфункция, разве нет? Или есть какой-то магический способ сделать это без неё?
Конечно, мне не до конца понятно, что именно ты спрашиваешь. Только проблема не во мне.
Ну да, логично вместо уточнения вопроса написать что попало в ответ и начать спорить? :grin:

kokoc88

1) Как это относится к случаю "ждём одновременно отмену и возврат ответа"?
Ты либо беспросветно туп, либо находишься на расстоянии светового года от темы разработки многопоточного кода. Попытаюсь объяснить тебе на пальцах, как ребёнку в детском саду, может быть поймёшь. Представь себе такую модель (именно модель, потому что вряд ли такой код заработает): выполняем синхронный recv а затем закрываем сокет из другого потока.
2) Ну да, ошибки как-то возвращаются. Это тут при чём? С этим вопросов нет. Но как другой поток прервёт ожидание? Для этого нужна спецфункция, разве нет? Или есть какой-то магический способ сделать это без неё?

Ты вообще не читаешь, что тебе пишут? Другой поток может закрыть соединение с базой данных, которая знает что нужно закрыть на уровне операционной системы (сокет, пайп, или что-нибудь ещё). Закрытие объекта операционной системы возобновит работу потока, который выполняет синхронное ожидание в ядре. Таким образом, для сокета ты получишь примерно ту же картину, что получил бы при отсутствии соединения с базой данных.
Ну да, логично вместо уточнения вопроса написать что попало в ответ и начать спорить?

Логично задавать вопросы в той области, в которой ты хоть что-нибудь понимаешь. Чтобы не приходилось тебе рассказывать и доказывать, что 1+1=2 или 10.

kokoc88

Как это относится к случаю "ждём одновременно отмену и возврат ответа"?
Вторая модель, более детальная, но для win32: WSASocket с флагом WSA_FLAG_OVERLAPPED, два раза CreateEvent начинаем WSARecv с одним event, выполняем WaitForMultipleObjectsEx на двух event-ах, из другого потока ставим второй event, функция WaitForMultipleObjectsEx возвращает результат, интерпретатор его обрабатывает и, например, выкидывает исключение.

kokoc88

1) Как это относится к случаю "ждём одновременно отмену и возврат ответа"?
Третья модель: используем один pthread condition и переменную типа bool. При этом внутри интерпретатора и завершение ввода-вывода, и отмену вешаем на этот condition. Если происходит отмена, то ставим флаг отмены и посылаем сигнал в condition; если отмены нет, то просто посылаем сигнал в condition (поток во время синхронной операции связывает завершение ввода-вывода с condition). По факту отмены выкидываем исключение или возвращаем код ошибки, пользовательский код закрывает канал в базу данных в finally или деструкторе.

tokuchu

Ты либо беспросветно туп, либо находишься на расстоянии светового года от темы разработки многопоточного кода. Попытаюсь объяснить тебе на пальцах, как ребёнку в детском саду, может быть поймёшь. Представь себе такую модель (именно модель, потому что вряд ли такой код заработает): выполняем синхронный recv а затем закрываем сокет из другого потока.
Ты вообще не читаешь, что тебе пишут? Другой поток может закрыть соединение с базой данных, которая знает что нужно закрыть на уровне операционной системы (сокет, пайп, или что-нибудь ещё). Закрытие объекта операционной системы возобновит работу потока, который выполняет синхронное ожидание в ядре. Таким образом, для сокета ты получишь примерно ту же картину, что получил бы при отсутствии соединения с базой данных.
Это ты либо туп, либо не читаешь и тупо троллишь. Уже 100 раз сказано было. У меня есть эта синхроная функция, она для меня чёрный ящик. И никакой, блядь, функции закрытия у меня нету для того, чтобы вызвать из другого потока.
Я, кажется понимаю, ты предлагаешь закрыть соединение с базой, предполагая, что этот "объект соединения" можно передать в другой поток. Если бы ты пускал меньше слюней и соплей, то может быть можно было бы быстрее понять друг друга.
Но в случае того ODBC интерфейс такой, что его нельзя передать в другой поток.
Да и я не говорил про функции закрытия. Запрос к БД привёл как пример, но почему-то это послужило красной тряпкой для многих. :)
Логично задавать вопросы в той области, в которой ты хоть что-нибудь понимаешь.
Ну это, наверное, самое тупое твоё утверждение в этом треде. :)
Чтобы не приходилось тебе рассказывать и доказывать, что 1+1=2 или 10.
Ну ты тут что-то доказывал, конечно, молодец. Но вот только не в тему. Т.к. я тебе пытаюсь объяснить свою ситуацию, а ты мне почему-то тупо продолжаешь рассказывать про свою, доказывать что-то. :crazy:

kokoc88

Если бы ты пускал меньше слюней и соплей, то может быть можно было бы быстрее понять друг друга.

Если бы ты не был так беспросветно самодоволен, то да, мы бы уже давно поняли друг-друга. Но к сожалению, ты не просто глупый неопытный кодер, ты глупый неопытный кодер, который по ошибке считает, что он что-то умеет.
Ну это, наверное, самое тупое твоё утверждение в этом треде.
Действительно, после того как ты написал "я просто тредами нигде не пользуюсь", можно было ничего тебе не объяснять.
Т.к. я тебе пытаюсь объяснить свою ситуацию, а ты мне почему-то тупо продолжаешь рассказывать про свою, доказывать что-то.
Давай подведём короткий итог дискуссии. Ты спросил, есть ли в других языках/платформах потребность останавливать потоки и как она решается. Я ответил, что есть и привёл примеры решения; по логике вещей тебе стоило поискать аналоги в tcl. Но вместо этого ты, так и не заботав матчасть, начал рассказывать про необходимость каких-то специальных возможностей. Я тебе почти сразу ответил: если в твоей библиотеке/платформе не поддерживается ни одного из приведённых мной методов или их аналогов, то ты не сможешь остановить поток по требованию.
По-моему, на этом тебе следовало пойти изучать механику работы твоей платформы, а не продолжать плакаться мне о том, что ты не можешь понять, как же остановить синхронный запрос из другого потока или как ожидать сразу двух событий в многопоточной среде. Вместо этого ты начал что-то мне доказывать, обнаружив полное отсутствие знаний в обсуждаемой области.

ava3443

Это ты либо туп, либо не читаешь и тупо троллишь.
А ты просто неадекватен, это если сказать мягко.
тебе уж и так, и так распинается, объясняя разные способы как это обычно делают, а тебе лень даже элементарно дать ссылку на используемую тобой библиотеку (tcl-wrapper для ODBC) и пример твоего кода.
За сим удаляюсь, ибо я к сожалению не так терпелив.
P.S. респект - его ответ был первым и, как оказалось, в самым точным, ведь конкретики от тебя за столько постов получили ровным счётом ноль.

tokuchu

Давай подведём короткий итог дискуссии. Ты спросил, есть ли в других языках/платформах потребность останавливать потоки и как она решается. Я ответил, что есть и привёл примеры решения. После чего ты, так и не заботав матчасть, начал рассказывать про необходимость каких-то специальных возможностей. Я тебе почти сразу ответил: если в твоей библиотеке/платформе не поддерживается ни одного из приведённых мной методов или их аналогов, то ты не сможешь остановить поток по требованию.
Ну и продолжил чего-то доказывать. Я же чего-то ступил и начал это на мой случай применять и как-то не забыл, что ты про свою платформу отвечаешь. Ты наверное считаешь себя умным опытным девелопером, который 100% знает, что он всё умеет. И раз ты находишься на таком высоком уровне развития, то мог бы напомнить мне глупому о том, что я сбился, вместо излияний говен непонятно почему.
По-моему, на этом тебе следовало пойти изучать механику работы твоей платформы, а не продолжать плакаться мне о том, что ты не можешь понять, как же остановить синхронный запрос из другого потока. Вместо этого ты начал что-то мне доказывать, обнаружив полное отсутствие знаний в обсуждаемой области.
Я ж тупой, куда мне. Хотел чтобы великий гуру сделал это за меня и всё мне разжевал как маленькому. :grin:

tokuchu

тебе уж и так, и так распинается, объясняя разные способы как это обычно делают,
Я понял, что был не прав в том, что "сбился с мысли" и почему-то начал это на описанное мною применять. Но это не повод говниться был. Хотя и эсклировать говны тоже нехорошо.
а тебе лень даже элементарно дать ссылку на используемую тобой библиотеку и пример твоего кода.
Я говорил, что суть не в конкретной библиотеке. Интересно было обсудить общие принципы.

kokoc88

Я ж тупой, куда мне. Хотел чтобы великий гуру сделал это за меня и всё мне разжевал как маленькому.
Я тебе разжёвывал. Ты заминусовал эти посты и сказал, что всё о чём я написал - бесполезно. Хотя как показали последующие препирательства, ты ни в чём не разобрался.

kokoc88

Я говорил, что суть не в конкретной библиотеке. Интересно было обсудить общие принципы.
А я тебе о каких принципах написал? Я же привёл несколько практических решений, которые применяются в mainstream языках: C#, Java, C++

tokuchu

что "сбился с мысли" и почему-то начал это на описанное мною применять
Даже не совсем так, меня интересовало в контексте, когда у нас полностью синхронный, блокирующийся и т.д. код. А он стал приводить примеры, которые с моей точки зрения требовали чего-то ещё, я пытался это объяснить всего-лишь. Я даже видел, что он дал ответ, что если такого нет, то ничего не поделаешь, но зачем-то ввязался в дискуссию по остальному доказывая какие-то вещи (не говорю, что неправильные но я хотел услышать про другое...
"Ну а потом она лопнула". (это из анекдота) :)

tokuchu

А я тебе о каких принципах написал? Я же привёл несколько практических решений, которые применяются в mainstream языках: C#, Java, C++
Ну не настолько общие принципы я хотел услышать, поэтому и говорил про дополнительные возможности. А то это очень большая область получается. Ну я уже сказал про синхронный, блокирующийся код. Не то, чтобы проблем там нет или каких-то решений. Мне это не интересно просто сейчас.
Ну вот возьмём последние примеры. Я знаю, что не совсем понимаю, т.к. совсем понимать бы я мог, если бы знал это сам, но тогда и вопроса бы не было. Ну вот в общем:
WaitForMultipleObjectsEx - я так понимаю некий аналог select? Тогда мне это не интересно. Я не говорю, что ты неправильно написал или ещё что, но если это аналог select, то под поставленные мною критерии оно не попадает.
Пример с "pthread condition" как я понял реализует модель, что мы оставляем запрос висеть, чтобы он сам завершился. Да, оно удовлетворяет критериям, но не очень красиво. Ну собственно кроме некрасивости здесь у меня других претензий и не было, а детали реализации данного метода в принципе не очень важны.

kokoc88

то под поставленные мною критерии оно не попадает
Какие критерии? Пока что единственный критерий, который я вижу, примерно такой: есть write-only код while(true) { } и его надо прервать по требованию. Это нельзя сделать, и нет никаких принципов, которые тут помогут.

tokuchu

Какие критерии? Пока что единственный критерий, который я вижу, примерно такой: есть write-only код while(true) { } и его надо прервать по требованию.
Именно так! :) Да, да. Меня именно и только это интересует.
Это нельзя сделать, и нет никаких принципов, которые тут помогут.
Ну я не спец во всех языках и платформах, поэтому и спрашивал как там у других. Я так понимаю, что ты этот ответ даёшь касательно C#, Java, C++?

Dasar

Это нельзя сделать, и нет никаких принципов, которые тут помогут.
имхо, ты непоследователен: с одной стороны - обзываешь оппонента дилетантом, а с другой стороны - требуешь от него знания и понимания очевидных для тебя вещей

tokuchu

Я так понимаю, что ты этот ответ даёшь касательно C#, Java, C++?
Т.к. этот вопрос не однозначен для всех платформ. Как я понимаю в Эрланге, зависшие процессы (ну не совсем треды, конечно) вполне можно прибивать.

kokoc88

так в этом вопрос и состоял: есть ли такие принципы..
Мне показалось, что вопрос состоял в том, как правильно решить некоторую задачу. И единственное уточнение было в том, что поток блокируется долгим запросом в базу данных. Очевидно, если в своём read-write вычислительном коде проверять какой-нибудь флаг, и есть возможность использовать один из перечисленных мной методов при выполнении запросов в БД, то это и будет решением поставленной задачи.
имхо, ты непоследователен: с одной стороны - обзываешь оппонента дилетантом, а с другой стороны - требуешь от него знания и понимания очевидных для тебя вещей
Щито?

kokoc88

Именно так! Да, да. Меня именно и только это интересует.
И при этом ты понимаешь разницу между while(true) и recv?

Dasar

Щито?
вот, например, ты считаешь очевидным, но при этом не проговариваешь ни разу это явно, что большинство задач можно свести к
своему вычислительному коду, в котором можно проверять флаг + код обращений к внешним херотеням, которые можно прерывать одним из способов, которые ты перечислил

kokoc88

вот, например, ты считаешь очевидным, но при этом не проговариваешь ни разу это явно, что большинство задач можно свести к
В каком смысле я не проговариваю это явно? Я даю информацию, которая требуется для аргументации в споре. Естественно, оппонент должен сам что-нибудь изучить и почитать, кроме моего поста. Естественно, некоторые вещи можно будет описать более детально, если вместо возражения "так не делается" будет вопрос "как это работает".

Dasar

В каком смысле я не проговариваю это явно?
в прямом.
ты действительно хочешь знать, почему твои посты в этом треде будут плохо восприниматься непрофессионалами? или просто хочешь продавить, что ты прав?

kokoc88

ты действительно хочешь знать, почему твои посты в этом треде будут плохо восприниматься непрофессионалами?
Причина конфликта была не в восприятии моих постов непрофессионалами. Поэтому мне всё равно.

tokuchu

И при этом ты понимаешь разницу между while(true) и recv?
Разница, конечно есть. Ты писал про то, что можно вызвать функцию "отключения от БД" из другого треда, которая приведёт к тому, что ОС закончит этот recv.
Этот способ возможно не всегда будет работать, мне кажется, т.к. зависит от реализации. Функции могут быть не thread-safe и мы можем покрешиться. Но попробовать, конечно можно, я это не отрицал.
Но а вот если у нас нет такой фунцкии в другом треде и мы не знаем что там происходит recv или что-то ещё и из какого вообще дескриптора. Тогда это всё равно отличается от while(true) или уже нет. Вот что интересно?

tokuchu

slonishka

Шесть! Девять!
"Лох! Пидр!"

Оставить комментарий
Имя или ник:
Комментарий: