Иногда обобщение проблемы помогает увидеть решение. Преобразование int
в void *
— это старый прием, позволяющий избежать выделения памяти. Иногда вы просто хотите настроить поток, который будет работать с чем-то большим, чем просто int.
Обычный подход, который я использую для настройки pthreads, состоит в том, чтобы calloc
некоторую структуру или даже пространство для одного значения (например, unsigned long long
), передать его аргументу pthread и использовать его в моей функции потока до while (1)
основной логики потока, затем free
.
Это позволяет вам передавать столько или меньше, сколько вы хотите, всегда в порядке, независимо от размера того, что вы передаете, и не пытается засунуть значения в указатели.
typedef struct {
unsigned long long large_serial_number;
const char *my_name;
pthread_t caller_thread;
} fun_thread_args_t;
static void* _fun_thread_run(void *arg) {
// Get our thread args from the dynamically allocated thread args passed-in
fun_thread_args_t *thread_args = (fun_thread_args_t *)arg;
bool done = false;
while (!done) {
// Use args here in your thread loop
...
}
// Free incoming args pointer before exiting the thread loop.
free(arg);
return NULL;
}
static pthread_t *_launch_fun_thread(pthread_t *thread, unsigned long long serial_number, const char *name) {
// TODO: Of course, error-handle all the return values properly ;)
// Allocate and prepare args for the thread
fun_thread_args_t *args = calloc(1, sizeof(args));
args->caller_thread = pthread_self();
args->large_serial_number = serial_number;
args->my_name = name;
// Create the thread, passing the args pointer from heap
int rc = pthread_create(thread, NULL, &_fun_thread_run, args);
if (0 == rc) {
// We return here, all is well, no stack data leak, args in heap
return thread;
} else {
free(args);
return NULL;
}
}
// ...
// Elsewhere, start some threads!
pthread_t fun_thread1;
pthread_t fun_thread2;
_launch_fun_thread(&fun_thread1, 0xABCDEF12345678ULL, "super FUN thread 1");
usleep(500UL * 1000UL);
_launch_fun_thread(&fun_thread2, 0xDEADBEEF55AA55ULL, "super FUN thread 2");
pthread_join(fun_thread1, NULL);
pthread_join(fun_thread2, NULL);
// ...
Для вашего конкретного примера unsigned long long
вы могли бы просто выделить его вместо структуры:
unsigned long long *thread_arg = calloc(1, sizeof(*thread_arg));
*thread_arg = 123456;
Затем передал:
pthread_create(thread, NULL, &_fun_thread_run, (void *)thread_arg);
free()
будет выполнено в том же месте, и вы можете преобразовать от void *
до unsigned long long *
в бегунке потоков.
См. https://gist.github.com/tcarmelveilleux/967728df33215d66e2e126637270901c. - компилируемый пример.
person
tennessee
schedule
08.05.2018
pthread_create
... Если это, например, переменная-итератор циклаfor
, которую вы меняете в цикле, то значение будет меняться во всех потоках, на которые вы передали указатель. Здесь есть хитрость, которая может передавать значения через умное приведение:(void *)(uintptr_t) i
. Тогда сделайте наоборот в треде:int i = (int)(uintptr_t) pi;
- person Some programmer dude   schedule 04.05.2018gettid()
возвращаетpid_t
, а неunsigned long long
. - person alk   schedule 05.05.2018