Здравствуйте, zaufi, Вы писали:
Z>Здравствуйте, k732, Вы писали:
K>>мне кажется что объект-поток должен отвечать только за корректный запуск и остановку потока. А "чтоб при его убийстве у тя не было ликов (памяти, дескрипторов, и еще черт знает чего)" это не его проблеммы, а проблеммы разработчика самой потоковой функции. Ведь системной _beginthreadex это тоже по барабану
Z>корректный с чьей точки зрения? -- системы наплевавшей на кучу объектов нуждающихся в нетривиальном удалении?
поймите же, что это лишь вспомогательный объект, который ничего не должен знать что происходит у него внутри потоковой функции. От лишь должен быть безопасен и нейстрален.
Z>такой подход тоже имеет право на существование -- вот поэтому мне и не нравятся бустерные threadы (и многие другие библы по сути являющиеся wapperами (разной степени корявости) над системными Сишными функциями)
ну я думаю вы согласитесь с тем, что даже обкатанный STL имеет множетсво органичений и рекомендаций. Обобщенный ког я считаю нельзя написать впринципе
Z>разумееца программер должен следить за кучей всего в своей проге (вместа того чтоб сконцентрироватся над задачей ) -- но это не наш way
Z>в эру когда на нас надвигаются multicorные камни проги просто обязаны уметь пользовать все доступные CPU при этом если написание таких прог останется на текущем уровне то это буит ПРОГРАММЕРСКИЙ АД -- ну согласись кодя на С++ ты должен помнить и следить еще за такими тривиальными вещами как вызов деструкторов, отслеживать последовательность создания/удаления оберток над mutex/condition/thread в дадамемберах своего класса (помня о том кто и как это использует) -- все это требует упрощения!
Z>я для себя лична выбрал way когда эти проблемы максимально переносятся с плеч прогаммера на плечи компилятора + threads implementation -- и на протяжении 3х лет успешно этим решением пользуюсь
ну я считаю, что вызов деструкторов в исключительной ситуации — это проблеммы самого C++ и компилятора. А в остальных случаях — разработчика (не считая платформ .NET и Java — где за это отвечает сборщик мусора)
Поэтому мне кажется — это не совсем суть темы
Что касается самого класса
1. Я правильно реализовал Impl — или может boost::function универсальнее передать прям в Thread
2. Кто отвечает за выход из потоковой функции (когда Thread просит его остановиться)- код разработчика, или сам Thread
Здравствуйте, k732, Вы писали:
K>>>мне кажется что объект-поток должен отвечать только за корректный запуск и остановку потока. А "чтоб при его убийстве у тя не было ликов (памяти, дескрипторов, и еще черт знает чего)" это не его проблеммы, а проблеммы разработчика самой потоковой функции. Ведь системной _beginthreadex это тоже по барабану
Z>>корректный с чьей точки зрения? -- системы наплевавшей на кучу объектов нуждающихся в нетривиальном удалении?
K>поймите же, что это лишь вспомогательный объект, который ничего не должен знать что происходит у него внутри потоковой функции. От лишь должен быть безопасен и нейстрален.
чего уж тут не понятного -- враппер он и есь враппер
дык о какой безопастности threadного враппера мы говорим? -- он нарушает все что только можно нарушить в C++ -- начиная от безопастности типов и заканчивая exceptions safety
Z>>такой подход тоже имеет право на существование -- вот поэтому мне и не нравятся бустерные threadы (и многие другие библы по сути являющиеся wapperами (разной степени корявости) над системными Сишными функциями)
K>ну я думаю вы согласитесь с тем, что даже обкатанный STL имеет множетсво органичений и рекомендаций. Обобщенный ког я считаю нельзя написать впринципе
безусловно органичения на типы в STL есть -- но эти ограничения всеже позволяют писать довольно genericовые алгоритмы -- и думаю нет смысла спорить что STLный код можно считать высокореюзабельным (это следствие genericoвости
в случае с threadами все тоже самое -- можно постоянно изобретать велосипеды сращивая несращиваемое (я про threads + C++) делая каждый раз новое customное решение или попытаться заgeneralizить этот код и реюзать -- второе разумеется сложнее
Z>>разумееца программер должен следить за кучей всего в своей проге (вместа того чтоб сконцентрироватся над задачей ) -- но это не наш way
K>ну я считаю, что вызов деструкторов в исключительной ситуации — это проблеммы самого C++ и компилятора. А в остальных случаях — разработчика (не считая платформ .NET и Java — где за это отвечает сборщик мусора)
мы про исключительные ситуации еще и не говорили!
кроме исключительных ситуаций когда компилятор обязан вызвать деструктор есть еще и такие простые вещи как выход переменной из области видимости
K>Что касается самого класса K>1. Я правильно реализовал Impl — или может boost::function универсальнее передать прям в Thread
передать то можно и эот даже хорошо! но есть одна маленькая проблемка: в функтор еще нужно передеать параметры -- подумай вот над чем:
как реализовать start?
K>2. Кто отвечает за выход из потоковой функции (когда Thread просит его остановиться)- код разработчика, или сам Thread
ну это зависит от реализации -- причем ТВОЕЙ
постарайся ответить для себя вот еще на какой вопрос:
представь что получить lock неудается долгое время и тут в другом thread'e тебе приспичивает сдалать thr.join()...
какаябы обертка не была над mutex гдето это все равно должно уперется в системный вызов зависящий от реализации, который будучи cancellation pointом замочит твой thread без вопросов и управление туда попросту больше не вернется! -- в результате имеем wrapper над mutexом в непонятном состоянии и неубитый obj...
Здравствуйте, k732, Вы писали:
K>Здравствуйте, zaufi, Вы писали:
Z>>ты в стандарте денить видел описание того как вызываются деструкторы в thread'ах?? Z>>можешь не листать -- там этого НЕТ Z>>как правило (исключения таки есть реализация threadов (системнозависимая надо заметить) НИЧЕГО не знает о твоих объектах С++!
K>так как тогда правильно сделать
постаряйся сначала найти хоть какоенить решение -- а правильное оно или нет покажет опыт его применения
K>>Что касается самого класса K>>1. Я правильно реализовал Impl — или может boost::function универсальнее передать прям в Thread Z>передать то можно и эот даже хорошо! но есть одна маленькая проблемка: в функтор еще нужно передеать параметры -- подумай вот над чем: Z>
только уйти от
unsigned (*func)(void *)
уже не получится. Но впринципе и этого пока достаточно (через void* можно многое отдать
K>>2. Кто отвечает за выход из потоковой функции (когда Thread просит его остановиться)- код разработчика, или сам Thread Z>ну это зависит от реализации -- причем ТВОЕЙ
Z>постарайся ответить для себя вот еще на какой вопрос: Z>
Z>представь что получить lock неудается долгое время и тут в другом thread'e тебе приспичивает сдалать thr.join()... Z>какаябы обертка не была над mutex гдето это все равно должно уперется в системный вызов зависящий от реализации, который будучи cancellation pointом замочит твой thread без вопросов и управление туда попросту больше не вернется! -- в результате имеем wrapper над mutexом в непонятном состоянии и неубитый obj...
Здравствуйте, zaufi, Вы писали:
Z>Здравствуйте, k732, Вы писали:
K>>Здравствуйте, zaufi, Вы писали:
Z>>>ты в стандарте денить видел описание того как вызываются деструкторы в thread'ах?? Z>>>можешь не листать -- там этого НЕТ Z>>>как правило (исключения таки есть реализация threadов (системнозависимая надо заметить) НИЧЕГО не знает о твоих объектах С++!
K>>так как тогда правильно сделать Z>постаряйся сначала найти хоть какоенить решение -- а правильное оно или нет покажет опыт его применения
решение было, но встала проблемма ожидания завершения потока в деструкторе порожденного класса, если он сам в базовом классе
тоесть проблемма вызова виртуальных функций из конструктора и деструктора
K>только уйти от K>unsigned (*func)(void *) K>уже не получится. Но впринципе и этого пока достаточно (через void* можно многое отдать
и это говорит тот кто мечтает о мифической "безопастности" своей обертки!!?
--
ты прости мя за прямоту конечно (ничо личного ) -- но ты нагородил такой overhead вокруг threadов и недобился НИКАКОГО СУЩЕСТВЕННОГО улучшения по сравнению с сишным API! И даже более того внес кучу ограничений заставляющих пользователя твоего класса делать противоестественные вещи
K>то проблемма снимется если правда поток не terminated
никто никкуда не снимается! добавление еще бльшего overhead'a не отменяет вызов системнозависимого lock(&mutex) -- ты просто убрал его с глаз долой (закопав в очередной уровень оберток) и думаешь что проблема решена?
Z>и это говорит тот кто мечтает о мифической "безопастности" своей обертки!!? Z>-- Z>ты прости мя за прямоту конечно (ничо личного ) -- но ты нагородил такой overhead вокруг threadов и недобился НИКАКОГО СУЩЕСТВЕННОГО улучшения по сравнению с сишным API! И даже более того внес кучу ограничений заставляющих пользователя твоего класса делать противоестественные вещи
ну на самом деле этот клас нужен просто для удобства. Внутри себя естественно он сожержит WinAPI функции.
K>>я думаю если зделать так
K>>
K>>то проблемма снимется если правда поток не terminated
Z>никто никкуда не снимается! добавление еще бльшего overhead'a не отменяет вызов системнозависимого lock(&mutex) -- ты просто убрал его с глаз долой (закопав в очередной уровень оберток) и думаешь что проблема решена?
наверное я тогда не совсем понял что Вы мы имеете ввиду под безопасностью. Я понимаю это как откат в предыдущее состояние.
в приведенном примере деструктор всегда будет вызван, а значит mutex разлочен
Здравствуйте, k732, Вы писали:
K>Здравствуйте, zaufi, Вы писали:
Z>>и это говорит тот кто мечтает о мифической "безопастности" своей обертки!!? Z>>-- Z>>ты прости мя за прямоту конечно (ничо личного ) -- но ты нагородил такой overhead вокруг threadов и недобился НИКАКОГО СУЩЕСТВЕННОГО улучшения по сравнению с сишным API! И даже более того внес кучу ограничений заставляющих пользователя твоего класса делать противоестественные вещи
K>ну на самом деле этот клас нужен просто для удобства. Внутри себя естественно он сожержит WinAPI функции.
тотвоему это "удобно" заставлять юзера наследоваться от какогото там интерфейса провайдя странную функцию первые действия которой всегда заключаются в вытаскивании неизвестно чего (и сколько) из воидного поинтера? и это все только лишь для того чтоб скрыть (инкапсулировать) 1(!!!) параметр (thread handler) и введя объекты туда где и без них все сложно ???
K>наверное я тогда не совсем понял что Вы мы имеете ввиду под безопасностью. Я понимаю это как откат в предыдущее состояние. K>в приведенном примере деструктор всегда будет вызван, а значит mutex разлочен
интересно ктойта тебе пообещал вызвать деструктор??
твой thread умрет (!!) еще в конструкторе твоего Locker'a! -- и как уже было сказано не получит управления в зад (чтобы вызвать какиебы то ни было деструкторы!
Здравствуйте, k732, Вы писали:
K>так как тогда правильно сделать
постараюсь описать тебе как это могло бы быть:
[list]
threadом можно сделать любую пользовательскую функцию
int foo(int, const std::string&, double) {...}
class some_class
{
...
void bar() {...}
};
int main(void)
{
thread<int(int, const std::string&, double)> foo_thr(&foo);
foo_thr.spawn(10, "my_string", 3.14);
...
int foo_result = foo_thr.join();
...
thread<void(some_class* const)> bar_thr(&some_class::bar);
some_class s;
bar_thr.spawn(&s);
...
}
-- не нужно ограничивать юзеру свободу в этом и заставлять его чтото делать (например наследовать чтолибо) -- это на сам деле излишне
проблемы с убиением рашаются если суметь преобразовать событие убиения в exception вылетающий в targetном thread'e:
void threded_func(...)
{
try
{
MyMegaObjectWithDestructor obj(...);
...
}
catch (const thread_exception::thread_canceled&)
{
// это значит что нас вежливо (пока) просят умереть
// если не делать ничего то все само собой поуничтожается... :)
// просто выходим из функции...
}
}
Здравствуйте, zaufi, Вы писали:
Z>Здравствуйте, k732, Вы писали:
K>>так как тогда правильно сделать
Z>постараюсь описать тебе как это могло бы быть:
Z>[list] Z> threadом можно сделать любую пользовательскую функцию
-- не нужно ограничивать юзеру свободу в этом и заставлять его чтото делать (например наследовать чтолибо) -- это на сам деле излишне Z> проблемы с убиением рашаются если суметь преобразовать событие убиения в exception вылетающий в targetном thread'e:
Z>void threded_func(...)
Z>{
Z> try
Z> {
Z> MyMegaObjectWithDestructor obj(...);
Z> ...
Z> }
Z> catch (const thread_exception::thread_canceled&)
Z> {
Z> // это значит что нас вежливо (пока) просят умереть
Z> // если не делать ничего то все само собой поуничтожается... :)
Z> // просто выходим из функции...
Z> }
Z>}
Z>
что-то не совсем понял. Но что-то очень похоже на .NET Thread, для которого чтоб остановить выбрасывают исключение.
Можно здесь подробнее немного
Здравствуйте, zaufi, Вы писали:
Z>Здравствуйте, k732, Вы писали:
K>>Здравствуйте, zaufi, Вы писали:
Z>>>и это говорит тот кто мечтает о мифической "безопастности" своей обертки!!? Z>>>-- Z>>>ты прости мя за прямоту конечно (ничо личного ) -- но ты нагородил такой overhead вокруг threadов и недобился НИКАКОГО СУЩЕСТВЕННОГО улучшения по сравнению с сишным API! И даже более того внес кучу ограничений заставляющих пользователя твоего класса делать противоестественные вещи
K>>ну на самом деле этот клас нужен просто для удобства. Внутри себя естественно он сожержит WinAPI функции.
Z>тотвоему это "удобно" заставлять юзера наследоваться от какогото там интерфейса провайдя странную функцию первые действия которой всегда заключаются в вытаскивании неизвестно чего (и сколько) из воидного поинтера? и это все только лишь для того чтоб скрыть (инкапсулировать) 1(!!!) параметр (thread handler) и введя объекты туда где и без них все сложно ???
K>>наверное я тогда не совсем понял что Вы мы имеете ввиду под безопасностью. Я понимаю это как откат в предыдущее состояние. K>>в приведенном примере деструктор всегда будет вызван, а значит mutex разлочен
Z>
Z>интересно ктойта тебе пообещал вызвать деструктор?? Z>твой thread умрет (!!) еще в конструкторе твоего Locker'a! -- и как уже было сказано не получит управления в зад (чтобы вызвать какиебы то ни было деструкторы!
ну чесно говоря — это спорный вопрос. Если система захотела убить вообще весь процес — аминь (это уж Билл пусть заботиться о безопасности)
а если это делают шаловливые руки разработчика — по рукам ему (Terminate просто настоятельно не рекомендуют вызывать)
Здравствуйте, k732, Вы писали:
K>тоесть не нужны нафиг никакие обертки — boost::thread все решает ?
типа того! -- кроме того что это более кроссплатформенно чем твое доморощеное решение оно я думаю немнго более профессионально написано -- хотя как показывает баглист бустерный и не без грешков
однако приводя пример я не имел вввввиду конкретно boost (если и получилоось какоето сходство с boost то это не нарочно! ) -- как я уже говорил boostерные threadы я не использую -- приведенный код следует рассмартивать как "псевдокод" весьма близкий к тому что хотелось бы видеть лично мне столкнись я с твоей проблемой...
Z>>[/ccode] -- не нужно ограничивать юзеру свободу в этом и заставлять его чтото делать (например наследовать чтолибо) -- это на сам деле излишне Z>> проблемы с убиением рашаются если суметь преобразовать событие убиения в exception вылетающий в targetном thread'e:
Z>>void threded_func(...)
Z>>{
Z>> try
Z>> {
Z>> MyMegaObjectWithDestructor obj(...);
Z>> ...
Z>> }
Z>> catch (const thread_exception::thread_canceled&)
Z>> {
Z>> // это значит что нас вежливо (пока) просят умереть
Z>> // если не делать ничего то все само собой поуничтожается... :)
Z>> // просто выходим из функции...
Z>> }
Z>>}
Z>>
K>что-то не совсем понял. Но что-то очень похоже на .NET Thread, для которого чтоб остановить выбрасывают исключение. K>Можно здесь подробнее немного
приведенный псевдокод выражает идею как можно было бы зарамсить проблему с cancellation pointами и вызовом деструкторов... (всякое сходство с чем быто ни было СЛУЧАЙНО -- я вааще под *nix все делаю и знать не знаю ничо про .net & etc )
если быть побдробнее в данном месте то те нада разобраться с тем как обучить свой thread (в данном случае не класс а поток управления) понимать что пришло время умирать (обычно этого хотят другие (внешние по отношению к текущему) threadы) и выкидывать внутри себя исключение, таким образом программер сможет его поймать и поуничтожать все корректно... (ну или компилятор в большенстве случаем все сам сделает
Здравствуйте, k732, Вы писали:
Z>>интересно ктойта тебе пообещал вызвать деструктор?? Z>>твой thread умрет (!!) еще в конструкторе твоего Locker'a! -- и как уже было сказано не получит управления в зад (чтобы вызвать какиебы то ни было деструкторы!
K>ну чесно говоря — это спорный вопрос. Если система захотела убить вообще весь процес — аминь (это уж Билл пусть заботиться о безопасности)
ничо тут спорного нет -- ты видима не догоняешь тему -- попробуем в более жизненном примере рссмотреть происходящее:
void worker_thread(...)
{
MyObjectWithDestructor obj(...);
...
// в этой функции чтото долго и упорно вычисляется (или просто ктото притормаживает)
// таким образом возникает timeout и worker_scheduler решает ее замочить...
very_long_time_calculations_here();
...
}
void worker_scheduler(...)
{
while (ходим по списку запущеных обработчиков)
{
...
if (текущий обработчик задержатся с вычислениями)
// убиваем голубчика! результат уже никому не нужен...
worker_threads[i].join();
...
}
}
тоесь када шедулер мочит worker_thread, тот находится гдето в глубине функции very_long_time_calculations_here() которая в процессе выполнения достигла cancellation point'a -- т.е. отдала управление ядру, и то видя что thread зашедулен на убиение (из worker_scheduler был вызван join) с чистой совестью убивает соответствующий entry в своих шедулерских табличках и УПС! -- твоего thread'а будто никада и не было! -- больше управление в него не вернется!!! ибо нет уже никакого thread'a! даже воспоминания о нем...
--
внимание вопрос... КТО ТУТ вызовет деструктор для obj (и прочих несчастных локеров-шмокеров & etc ???
Здравствуйте, zaufi, Вы писали:
Z>Здравствуйте, k732, Вы писали:
Z>>>интересно ктойта тебе пообещал вызвать деструктор?? Z>>>твой thread умрет (!!) еще в конструкторе твоего Locker'a! -- и как уже было сказано не получит управления в зад (чтобы вызвать какиебы то ни было деструкторы!
K>>ну чесно говоря — это спорный вопрос. Если система захотела убить вообще весь процес — аминь (это уж Билл пусть заботиться о безопасности)
Z>ничо тут спорного нет -- ты видима не догоняешь тему -- попробуем в более жизненном примере рссмотреть происходящее: Z>
Z>void worker_thread(...)
Z>{
Z> MyObjectWithDestructor obj(...);
Z> ...
Z> // в этой функции чтото долго и упорно вычисляется (или просто ктото притормаживает)
Z> // таким образом возникает timeout и worker_scheduler решает ее замочить...
Z> very_long_time_calculations_here();
Z> ...
Z>}
Z>void worker_scheduler(...)
Z>{
Z> while (ходим по списку запущеных обработчиков)
Z> {
Z> ...
Z> if (текущий обработчик задержатся с вычислениями)
Z> // убиваем голубчика! результат уже никому не нужен...
Z> worker_threads[i].join();
Z> ...
Z> }
Z>}
Z>
Z>тоесь када шедулер мочит worker_thread, тот находится гдето в глубине функции very_long_time_calculations_here() которая в процессе выполнения достигла cancellation point'a -- т.е. отдала управление ядру, и то видя что thread зашедулен на убиение (из worker_scheduler был вызван join) с чистой совестью убивает соответствующий entry в своих шедулерских табличках и УПС! -- твоего thread'а будто никада и не было! -- больше управление в него не вернется!!! ибо нет уже никакого thread'a! даже воспоминания о нем... Z>-- Z>внимание вопрос... КТО ТУТ вызовет деструктор для obj (и прочих несчастных локеров-шмокеров & etc ???
ОК — убедил. Но мне не совсем понятно как можно поток заставить бросить исключение в своей потоковой функции.
похоже нужно создавать новый топик по boost::thread (никогда не использовал)
> void worker_scheduler(...) > { > while (ходим по списку запущеных обработчиков) > { > ... > if (текущий обработчик задержатся с вычислениями) > // убиваем голубчика! результат уже никому не нужен... > worker_threads[i].join(); > ... > } > } > [/ccode] > тоесь када шедулер мочит worker_thread, тот находится гдето в глубине функции very_long_time_calculations_here() которая в процессе выполнения достигла cancellation point'a -- т.е. отдала управление ядру, и то видя что thread зашедулен на убиение (из worker_scheduler был вызван join) с чистой совестью убивает соответствующий entry в своих шедулерских табличках и УПС! -- твоего thread'а будто никада и не было! -- больше управление в него не вернется!!! ибо нет уже никакого thread'a! даже воспоминания о нем... > -- > внимание вопрос... КТО ТУТ вызовет деструктор для obj (и прочих несчастных локеров-шмокеров & etc ???
Интересно, а join тут у вас обсуждается бустовый или какой-то другой? Просто boost::thread::join() под виндой никого не убивает, а ждет завершения потока. Та же ситуация, которую вы описали, равнозначна вызову виндовой TerminаteThread и в общем не должна возникать при отсутствии в программе фатальных ошибок. Не знаю, как под другими операционками, но под виндой так завершать нити не следует.
Posted via RSDN NNTP Server 2.0
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, zaufi, Вы писали:
Z>Здравствуйте, k732, Вы писали:
K>>ОК — убедил. Но мне не совсем понятно как можно поток заставить бросить исключение в своей потоковой функции.
Z>а это также тема для отдельного топика
Всё довольно очевидно — без callbacka тут не обойтись ну никак, просто потому что никак
Я когда-то постил тему насчет как перенести однозадачное досовое приложение (допустим некий конвертор) на многопоточность.
Думали мы думали и надумали то же, что и zaufi — а конкретно, бросать исключение из колбека, который вызывается для показания прогресса.
Оказались и овцы целы, и волки сыты ... (касаемо удаления используемой памяти и тд)
Как оказалось, довольно работоспособное решение, кроме некоторых тонких для винды моментов (если кому интересно, то тут
Здравствуйте, Sergey, Вы писали:
S>Интересно, а join тут у вас обсуждается бустовый или какой-то другой? Просто boost::thread::join() под виндой никого не убивает, а ждет завершения потока. Та же ситуация, которую вы описали, равнозначна вызову виндовой TerminаteThread и в общем не должна возникать при отсутствии в программе фатальных ошибок. Не знаю, как под другими операционками, но под виндой так завершать нити не следует.
Может недописано всё?
У меня в доморошенном потоке в joine стоит некое разумное время завершения, после чего прога поток заверщает и ругается на мои кривые руки правда это токо в дебаг режиме ...
> S>Интересно, а join тут у вас обсуждается бустовый или какой-то другой? Просто boost::thread::join() под виндой никого не убивает, а ждет завершения потока. Та же ситуация, которую вы описали, равнозначна вызову виндовой TerminаteThread и в общем не должна возникать при отсутствии в программе фатальных ошибок. Не знаю, как под другими операционками, но под виндой так завершать нити не следует. > > Может недописано всё? > У меня в доморошенном потоке в joine стоит некое разумное время завершения, после чего прога поток заверщает и ругается на мои кривые руки правда это токо в дебаг режиме ...
Чего не дописано? Под виндой нет ни одного безопасного способа остановить нить извне. Потому что никто не гарантирует, что при вызове той же TerminateThread операционка озаботится отпусканием захваченных этой нитью объектов синхронизации или выполнит еще какие-либо post mortem действия в контексте прерванной нити. Так что все там сделано правильно.
Posted via RSDN NNTP Server 2.0
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Sergey, Вы писали:
>> S>Интересно, а join тут у вас обсуждается бустовый или какой-то другой? Просто boost::thread::join() под виндой никого не убивает, а ждет завершения потока. Та же ситуация, которую вы описали, равнозначна вызову виндовой TerminаteThread и в общем не должна возникать при отсутствии в программе фатальных ошибок. Не знаю, как под другими операционками, но под виндой так завершать нити не следует. >> >> Может недописано всё? >> У меня в доморошенном потоке в joine стоит некое разумное время завершения, после чего прога поток заверщает и ругается на мои кривые руки правда это токо в дебаг режиме ...
S>Чего не дописано? Под виндой нет ни одного безопасного способа остановить нить извне. Потому что никто не гарантирует, что при вызове той же TerminateThread операционка озаботится отпусканием захваченных этой нитью объектов синхронизации или выполнит еще какие-либо post mortem действия в контексте прерванной нити. Так что все там сделано правильно.
PPL! читаем внимательно: все мои листинги в этом топике ПСЕВДОКОД таких вызовов и классов не существует! -- всем расслабица...
ЗЫ: я и вправду немного ступил насчет join'a -- конечно же он не убивает thread... чтобы эстетам стало легче вообразите перед вызовом join'a такой псевдокод:
...
thr.cancel(); // say 'DIE' to thread...
thr.join(); // wait for thread death...
...