Как вернуть двойное значение из pthread в C ++?

Прочитав эту ветку: Как вернуть значение из потока в C о том, как вернуть целочисленное значение из pthread, которое я тестировал, чтобы увидеть, может ли оно работать на удвоение, но это не сработало. Есть ли способ вернуть double, long или строку из процесса pthread, как описано в исходном потоке, вместо возврата целого числа 42?

Если да, то как?

И если у меня будет статический массив из 10 позиций и 10 потоков, каждый раз меняющий разные позиции, у меня будут проблемы?
Пример AN выглядит как «поток 0 изменяет только массив [0], поток 1 изменяет только массив [1] и т. Д.».

3

Решение

Это просто переформулировки Решение Стив Джессоп С в C ++. В этих игрушечных примерах (обратите внимание на отсутствие проверки ошибок) используются шаблоны, чтобы понять, как изменить код, чтобы использовать какой-либо другой тип, кроме double, Например, double может быть заменен на class введите, если более чем одно значение необходимо вернуть после выполнения работы. На практике базовый класс и шаблон, скорее всего, будут удалены, а work() метод MyWorker будет вызываться непосредственно вызывающим, а не через виртуальный метод.

Во-первых, используя pthread:

#include <iostream>
#include <pthread.h>

class WorkerBase {
protected: virtual ~WorkerBase () {}
public:    virtual void * work () = 0;
};

template <typename T>
struct Worker : public WorkerBase { T result; };

extern "C" void *invoke_worker (void *arg) {
return static_cast<WorkerBase *>(arg)->work();
}

struct MyWorker : public Worker<double> {
void * work () {
result = 4.2;
return 0;
}
};

int main () {
pthread_t t;
MyWorker w;
pthread_create(&t, 0, invoke_worker, &w);
pthread_join(t, 0);
std::cout << "result: " << w.result << std::endl;
return 0;
}

Во-вторых, используя C ++ 11 std::thread:

#include <iostream>
#include <thread>

class WorkerBase {
protected: virtual ~WorkerBase () {}
public:    virtual void work () = 0;
static void invoke (WorkerBase *w) { w->work(); }
};

template <typename T>
struct Worker : public WorkerBase { T result; };

class MyWorker : public Worker<double> {
void work () { result = 4.2; }
};

int main () {
MyWorker w;
std::thread t(MyWorker::invoke, &w);
t.join();
std::cout << "result: " << w.result << std::endl;
return 0;
}

У вас был другой вопрос в вашем посте, который я пропустил:

И если у меня будет статический массив из 10 позиций и 10 потоков, каждый раз меняющий разные позиции, у меня будут проблемы?

Будет ли это доставлять вам неприятности, скорее всего, будет зависеть от типа элемента массива и вашей аппаратной архитектуры. На практике я не заметил, чтобы это было проблемой в архитектурах x86 для элементов массива, которые выровнены по границам машинных слов.

2

Другие решения

Поток просто должен динамически распределять память для результата, который вы хотите вернуть:

void *myThread(void*)
{
double* result = (double*) malloc(sizeof(double));

*result = 42.0;

return result;
}

Что бы ни предполагалось собирать, этот результат разыменовывает указатель, возвращенный с использованием соответствующего преобразования (это C с void* в конце концов), то освободите память:

// calling thread (or whatever will collect the value)
void* thread_result;
int err = pthread_join( thread_handle, &thread_result);

double dbl = *(double*) thread_result;
free(thread_result);

В качестве альтернативы, все, что создает поток, может передать указатель туда, где поток должен поместить свой результат в void* параметр потока (возможно, как часть структуры, если потоку требуется больше, чем просто бит информации). Это может позволить вам избежать динамического выделения памяти, если у вас есть причина этого избежать, но это может сделать владение и время жизни данных несколько более сложным в управлении.

4

Я не думаю, что это слишком сложно. Я не использую malloc (size_t) из cstdlib, но только новый.
В следующем примере аргумент передается потоку как структура, а также возвращается другая структура. Чтобы показать это можно взять любой тип переменной, я также использовал векторы строк …

#include <iostream>
#include <pthread.h>
#include <vector>
#include <string.h>
#include <cstdlib>
using namespace std;

struct thread_data {
int number;
vector<string> strings;
thread_data (){}
thread_data(int nr) {
number = nr;
strings.push_back("aba\n");
}
};

struct thread_return_data {
int S;
vector<string> R;
};

void *Thread (void *threadarg) {
thread_return_data *R = new thread_return_data;
thread_data * Q;
Q = (thread_data *) threadarg;
cout << Q->number << endl;
R->S = 16; //random number
R->R.push_back("14fjnv"); //random string
R->R.push_back("28jfhn"); //random string
pthread_exit(R);
return 0;
}

int main() {
thread_data A(4444); //initialize with random int
thread_return_data *B; //is pointer
pthread_t aThread; //is variable

pthread_create(&aThread, NULL, Thread, (void *)&A);
pthread_join(aThread, (void **)&B);

cout << B->S << endl;
cout << B->R[0] << endl;
cout << B->R[1] << endl;
cout << A.strings[0];
delete B;

return 0;
}
1
По вопросам рекламы [email protected]