4

このスレッドを読んだ後:pthreadから整数値を返す方法についてCのスレッドから値を返す方法doubleで機能するかどうかを確認するためにテストしましたが、機能しませんでした。整数42を返す代わりに、元のスレッドで説明されているように、pthreadプロセスからdouble、long、または文字列を返す方法はありますか?

はいの場合、どのように?

また、10個の位置と10個のpthreadの静的配列が毎回異なる位置を変更している場合、問題が発生しますか?たとえば、「スレッド0は配列[0]のみを変更し、スレッド1は配列[1]のみを変更するなど」のようになります。

4

3 に答える 3

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*スレッドへのパラメーターになります(スレッドがそのビット以上の情報を必要とする場合は、おそらく構造体の一部として)。これを回避する理由がある場合は、動的メモリ割り当てを回避できる可能性がありますが、データの所有権と存続期間の管理がやや複雑になる可能性があります。

于 2013-03-12T05:26:52.213 に答える
2

これらは、SteveJessopのCソリューションを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個のpthreadの静的配列が毎回異なる位置を変更している場合、問題が発生しますか?

これで問題が発生するかどうかは、配列要素のタイプとハードウェアアーキテクチャによって異なります。実際には、これがマシンワードの境界に配置された配列要素のx86アーキテクチャで問題になることは確認していません。

于 2013-03-12T03:31:37.797 に答える
1

これは難しいことではないと思います。cstdlibのmalloc(size_t)は使用していませんが、新しいものです。次の例では、引数をstructとしてスレッドに渡し、別のstructも返します。それが任意の変数タイプを取ることができることを示すために、私は文字列のベクトルも使用しました...

#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;
}    
于 2013-05-09T13:48:38.970 に答える