2016-08-05 10 views
-1

Я бегу 32 bits ОС. Теперь созданный мной поток вернет значение int, которое может быть больше 4G. Как я могу получить это значение от моей функции main() на pthread_join()? . Похоже, в 32 bits системе, (void *) - 4 байта.Linux, C: как я могу получить возвращаемое значение из потока, который greate чем 4G в 32-битной ОС?

#include<stdio.h> 
#include<pthread.h> 
#include<stdlib.h> 

void* thread_function(void) 
{ 
    uint64_t nbytes = 0; 
    //assign values to nbytes, it could be larger than 4G. 
    return (void *)nbytes; 
} 

int main() 
{ 
    pthread_t thread_id; 
    uint64_t nbytes; 

    pthread_create (&thread_id, NULL, &thread_function, NULL); 
    pthread_join(thread_id,(void**)&nbytes); 
} 
+1

Почему бы не отправить '& nbytes' в качестве вашего текущего NULL аргумента в' pthread_create' и просто указать и установить значение через адрес в вашей функции? – WhozCraig

+4

Прежде всего, ваш 'thread_function' имеет неправильный тип. Он должен принимать аргументы. Теперь угадайте, что? Вы можете использовать эти аргументы для передачи значений взад и вперед. И возвращаемый тип 'void *' на самом деле не предназначен для использования в типах без указателей. –

ответ

2

Как это:

void* thread_function(void *) 
{ 
    uint64_t nbytes = 0; 
    //assign values to nbytes, it could be larger than 4G. 

    void *retval = malloc (sizeof (nbytes)); 
    memcpy (retval, &nbytes, sizeof (nbytes)); 
    return retval; 
} 

int main() 
{ 
    pthread_t thread_id; 
    uint64_t nbytes; 

    pthread_create (&thread_id, NULL, &thread_function, NULL); 

    void *ret; 
    pthread_join(thread_id, &ret); 
    memcpy (nbytes, ret, sizeof (nbytes)); 
    free (ret); 
} 

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

+0

Подпись 'thread_function' недопустима. В качестве альтернативы (и, я бы сказал, более безопасный) подход, он может взять указатель на предварительно выделенный буфер из принимающего потока и просто заполнить его. Гораздо лучше иметь код выделения и освобождения на одном уровне. –

+0

@EugeneSh. Спасибо, исправлено. Это очень стандартный шаблон, поскольку он работает даже тогда, когда принимающий поток не знает, насколько велик объект и даже когда создание и объединение потока находятся в самых разных местах. Я думаю, что в этом случае хуже привязывать выделение к созданию потока, потому что это не логически связано с тем, где результат создается или потребляется. –

+0

Ну, да. Вариант использования неизвестного размера объекта имеет смысл. –

2

Решение Дэвида Шварца хорошо известно, но слишком много, чтобы передать простое целое число; malloc() является дорогостоящим и не обязательно потокобезопасным (очень маловероятным, но со всеми вложенными материалами сегодня и hellip;).

Подхватив идею первых двух комментаторам на OP (WhozCraig и Евгений Ш..)

#include <stdio.h> 
#include <stdint.h> 
#include <pthread.h> 
#include <stdlib.h> 

void *thread_function(void *arg) 
{ 
    /* 
    No direct dereferencing 
     *arg = 0xdeadbeefcafe; 
    would give a compile error. With GCC it would be 

    threadargs.c:8:5: warning: dereferencing ‘void *’ pointer [enabled by default] 

    */ 
    uint64_t *nbytes = arg; 
    *nbytes = 0xdeadbeefcafe; 
    // you can return a simple status here, for example an error 
    return 0; 
} 

int main() 
{ 
    pthread_t thread_id; 
    uint64_t nbytes; 

    pthread_create(&thread_id, NULL, &thread_function, &nbytes); 
    pthread_join(thread_id, NULL); 
#define __STDC_FORMAT_MACROS 
#include <inttypes.h> 
    printf("nbytes = %" PRIx64 "\n", nbytes); 

    return 0; 
} 

Если делать эту работу по-другому, может быть, лучше один для этого вида использования.

Недостаток: каждый поток хочет, чтобы его собственная переменная заполнялась, поэтому она лучше подходит для фиксированного небольшого количества потоков, иначе вы выделяете из кучи и ничего не выигрываете, просто наоборот: это будет больше сложно удерживать все malloc()/free(). В этом случае метод Дэвида Шварца будет гораздо более уместным.

+0

Если вы используете потоки POSIX, тогда 'malloc()' будет потокобезопасным. –

+0

Также GlibC> = 2.2 (по крайней мере, я думаю, еще раньше), но меня слишком часто сжигали, чтобы не дать подсказку «лучше сначала проверить, независимо от того, насколько вы уверены». – deamentiaemundi