LINUX.ORG.RU

> Существует ли функция, которая делает pthread_join всех дочерних pthread`ов?

нет. да и зачем, если можно последовательно вызвать pthread_join() столько раз, сколько нужно?

> Или которая посылает им всем какой-нибудь сигнал?

нет. впрочем, аналогично pthread_join() но уже с pthread_kill().

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

> да и зачем, если можно последовательно вызвать pthread_join() столько раз, сколько нужно?

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

kmeaw ★★★
() автор топика
Ответ на: комментарий от kmeaw

> А как узнать, для чего его нужно вызывать? Хранить список всех тредов, а при завершении удалять их оттуда?

да

> Или есть более нормальный способ? (Треды создаются в результате ввода пользователем некоторой комманды)

чем не устраивает предложенный способ с хранением списка запущенных потоков?

// wbr

klalafuda ★☆☆
()

Лучше для остановки пользовать pthread_cancel()(снаружи), pthread_testcancel()(внутки останвливаемого потока)

sf ★★★
()
Ответ на: комментарий от klalafuda

> чем не устраивает предложенный способ с хранением списка запущенных потоков?

Тем, что из списка придется иногда удалять. Мне нужно вызывать join в конце работы программы, сразу перед освобождением всех ресурсов, которыми треды могут пользоваться. Я уже придумал другой способ: завести глобальную volatile переменную, увеличивать её при запуске треда и уменьшать при останове; в конце программы есть примерно такой код:

while (ThreadPool)

sleep (1);

Теперь возникла другая проблема: все треды находятся в deferred state, точки выхода (pthread_testcancel()) расставлены правильным образом. Но иногда выход присходит совсем в другом месте. Из man`ов я понял, что некоторые системные вызовы создают неявные точки выхода, а это происходит в тех местах, где это мне совсем не нужно. Я подавляю это путем запрета на выход (PTHREAD_CANCEL_DISABLE) и разрешения (PTHREAD_CANCEL_ENABLE) только в тех функциях, где это необходимо. Т.е. у меня есть такой код:

main() { pthread_t worker; pthread_create (worker, NULL, &cancel_unsafe_proc, NULL); ... pthread_cancel (worker); ... }

void cancel_unsafe_proc(void* ptr) { pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL); pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); while(1) { ... // тут нет выделения ресурсов, просто ... // какой-то код, делающий вычисления cancel_safe_proc (ptr); ... } }

void cancel_safe_proc (void* ptr) { pthread_cleanup_push (&cleanup_func, ptr); pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); ... // тут выделяются ресурсы pthread_testcancel(); /* [точка выхода] */ ... pthread_cleanup_pop (1); pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); }

В результате pthread_cancel (worker) в main() не срабатывает, не смотря на то, что я делаю pthread_testcancel() и ставлю PTHREAD_CANCEL_ENABLE.

kmeaw ★★★
() автор топика
Ответ на: комментарий от kmeaw

Простите за кривое форматирование...

main() { 
  pthread_t worker;
  pthread_create (worker, NULL, &cancel_unsafe_proc, NULL);
  ...
  pthread_cancel (worker);
  ... 
}

void cancel_unsafe_proc(void* ptr) {
  pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL);
  pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
  while(1) 
  { 
    ... // тут нет выделения ресурсов, просто
    ... // какой-то код, делающий вычисления
    cancel_safe_proc (ptr);
    ...
    write (0, "BUSY...\n", 8); // это не точка выхода,
    // т.к. я сделал PTHREAD_CANCEL_DISABLE выше.
    ... 
  } 
}

void cancel_safe_proc (void* ptr) {
  pthread_cleanup_push (&cleanup_func, ptr);
  pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
  ... // тут выделяются ресурсы
  pthread_testcancel(); /* [точка выхода] */
  ... 
  pthread_cleanup_pop (1);
  pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); 
}

kmeaw ★★★
() автор топика
Ответ на: комментарий от kmeaw

> Тем, что из списка придется иногда удалять.

hm.. ну и что? разве это так сложно?

> Мне нужно вызывать join в конце работы программы, сразу перед освобождением всех ресурсов, которыми треды могут пользоваться.

ну и прекрасно. join-ите их по однму по мере завершения и освобождайте соотв. ресурсы.

> Я уже придумал другой способ: завести глобальную volatile переменную, увеличивать её при запуске треда и уменьшать при останове; в конце программы есть примерно такой код:

[snip]

IMHO это, мягко говоря, суровое переусложнение системы. все может быть сделано заметно проще и надежнее.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

Спасибо, буду переделывать так, чтобы у меня хранился список всех активных тредов.

kmeaw ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.