Закрыть поток на основе значения переменной из вызывающего потока
Я использую потоки posix в C. У меня есть две темы в моей программе, thread1 и thread2. поток1 начинает поток2.
thread1 поддерживает переменную var1, в зависимости от которой необходимо безопасно завершить работу thread2.
thread2 вызывает много длинных функций (время выполнения которых может достигать 5 секунд). Существует много распределений памяти с использованием malloc в thread2. Как только var1 становится истиной, мне нужно закрыть thread2, но только после освобождения всех выделенных ячеек памяти. Как это можно сделать?
Код выглядит так:
void * func1(void *arg)
{
pthread_create(&thread2, &attr, func2, NULL);
while(1)
{
// ...
var1 = func3();
if(var1 == true)
{
// Cancel thread2
}
// ...
}
}
void * func2(void *arg)
{
// ...
func4(); // runs for 2 sec
char* var2 = malloc(10);
func5(); // runs for 5 sec
char* var3 = malloc(20);
// ...
cleanup:
free(var2);
free(var3);
return (void*) 0;
}
2 ответа
Есть несколько способов сделать это. Вот один из них:
С точки зрения thread1 вы можете просто использовать pthread_cancel
на thread2, когда придет время. Но вам нужно соответствующим образом реструктурировать thread2, чтобы убедиться, что он имеет точки отмены в безопасных местах. Вам также необходимо изменить структуру хранения ваших данных, чтобы можно было вызывать обратный вызов отмены для thread2:
struct func2_data {
char *var2;
char *var3;
};
void func2_cleanup(void *vdata) {
struct func2_data *data = vdata;
free(data->var2);
free(data->var3);
}
void * func2(void *arg)
{
struct func2_data data = {
NULL, NULL
};
pthread_cleanup_push(func2_cleanup, &data);
// ....
func4();
data.var2 = malloc(10);
pthread_testcancel();
func5();
data.var3 = malloc(10);
pthread_testcancel();
// ....
pthread_cleanup_pop(1);
return NULL;
}
Так что здесь происходит?
Все указатели, которые необходимо освободить, являются связками и инициализируются в NULL. Это позволяет звонить
free
действовать на них как на запрет, если функция очистки вызывается до того, как назначена какая-либо одна переменная.Обратный звонок зарегистрирован, чтобы освободить указатели. Этот обратный вызов будет вызван в любой точке отмены. В том числе, когда поток возвращается из своей функции-обработчика. Так что вам не нужно заботиться об этом прямо там, кроме вызова поп.
Точки отмены добавляются с
pthread_testcancel
в разных "безопасных" местах. Таким образом, поток может преждевременно заканчиваться между вычислениями. Добавьте их, как считаете нужным.
Несмотря на то, что ваш вопрос не совсем понятен, в приведенном ниже коде я даю идею для решения этих проблем. использование ptread_join
для безопасного выхода из ниток
void * func1(void *arg)
{
pthread_create(&thread2, &attr, func2, (void*)&var1); /* Pass addr of var1 as argument to thread*/
while(1)
{
...
var1 = func3();
if(var1 == TRUE){
int *ret;
pthread_join(thread2,&ret);
}
...
}
}
void * func2(void *arg)
{
bool *check = (bool*)arg;
...
func4(); // runs for 2 sec
if(*check == TRUE)
goto end;
char* var2 = malloc(10);
func5(); // runs for 5 sec
if(*check == TRUE)
goto clean_var2;
char* var3 = malloc(20);
...
cleanup:
free(var3);
clean_var2:
free(var2);
end:
return (void*) 0;
}