如何在c ++中从pthread返回double值?

时间:2013-03-11 23:49:16

标签: c++ concurrency pthreads pthread-join

读完这个帖子:How to return a value from thread in C关于如何从我测试过的pthread返回一个整数值,看看它是否适用于double,但事实并非如此。有没有办法从pthread进程返回double,long或一个字符串,如原始线程中所描述的那样,而不是返回整数42?

如果是,如何?

如果我有一个10个位置的静态数组和每次修改不同位置的10个pthreads,我会遇到麻烦吗? 例如,“线程0仅修改数组[0],线程1仅修改数组[1],依此类推”。

3 个答案:

答案 0 :(得分:4)

线程只需为您希望它返回的结果动态分配内存:

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

   *result = 42.0;

   return result;
}

无论应该收集什么结果,取消引用使用适当的强制转换返回的指针(毕竟这是带有void*的C),然后释放内存:

// 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*参数中的指针(如果线程需要的不仅仅是那个位,那么可能作为结构的一部分)信息)。如果你有理由避免这种情况,这可能会让你避免动态内存分配,但它可能会使数据的所有权和生命周期变得更加复杂。

答案 1 :(得分:2)

这些只是将Steve Jessop's C solution改编成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个pthreads,我会遇到麻烦吗?

这是否会给您带来麻烦可能取决于数组元素类型和您的硬件架构。在实践中,我没有发现这是x86体系结构中存在的问题,因为数组元素在机器字边界上对齐。

答案 2 :(得分:1)

我认为这太难了。我不使用来自cstdlib的malloc(size_t),而只是新的。 以下示例将参数作为结构传递给线程,并返回另一个结构。要显示它可以采用任何变量类型我也使用字符串向量...

#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;
}