をいただければ幸いです。このSO questionは、既存の実装を扱います。
考えられるのは、いくつかのスレッドインスタンス用のコンテナを用意することです。各インスタンスはタスクキューをポーリングする関数に関連付けられ、タスクが使用可能になると、それをプルして実行します。タスクが終了すると(終了しても別の問題です)、スレッドは単にタスクキューにループオーバーします。
同期されたキュー、キュー上のループを実装するスレッドクラス、タスクオブジェクト用のインターフェイス、そしてすべてを駆動するクラス(プールクラス)が必要です。
また、実行する必要があるタスク(非常に特殊なメモリ領域をパラメータとして持つ)に対して非常に特殊なスレッドクラスを作成することもできます。これには、スレッドが現在の繰り返しで完了したことを示すための通知メカニズムが必要です。
スレッドのメイン関数は、その特定のタスクのループであり、1回の反復の最後に、スレッドはその終了を通知し、次のループを開始するための条件変数を待ちます。本質的には、スレッド内のタスクコードをインライン展開し、キューの必要性を完全になくします。
using namespace std;
// semaphore class based on C++11 features
class semaphore {
private:
mutex mMutex;
condition_variable v;
int mV;
public:
semaphore(int v): mV(v){}
void signal(int count=1){
unique_lock lock(mMutex);
mV+=count;
if (mV > 0) mCond.notify_all();
}
void wait(int count = 1){
unique_lock lock(mMutex);
mV-= count;
while (mV < 0)
mCond.wait(lock);
}
};
template <typename Task>
class TaskThread {
thread mThread;
Task *mTask;
semaphore *mSemStarting, *mSemFinished;
volatile bool mRunning;
public:
TaskThread(Task *task, semaphore *start, semaphore *finish):
mTask(task), mRunning(true),
mSemStart(start), mSemFinished(finish),
mThread(&TaskThread<Task>::psrun){}
~TaskThread(){ mThread.join(); }
void run(){
do {
(*mTask)();
mSemFinished->signal();
mSemStart->wait();
} while (mRunning);
}
void finish() { // end the thread after the current loop
mRunning = false;
}
private:
static void psrun(TaskThread<Task> *self){ self->run();}
};
classcMyTask {
public:
MyTask(){}
void operator()(){
// some code here
}
};
int main(){
MyTask task1;
MyTask task2;
semaphore start(2), finished(0);
TaskThread<MyTask> t1(&task1, &start, &finished);
TaskThread<MyTask> t2(&task2, &start, &finished);
for (int i = 0; i < 10; i++){
finished.wait(2);
start.signal(2);
}
t1.finish();
t2.finish();
}
提案(粗製)の実装は、上記operator()
(クラスなどすなわちファンクタ)を提供しなければならないTask
タイプに依存しています。私はあなたが以前にスレッド関数本体に直接タスクコードを組み込むことができると言ったが、私はそれを知らないので、私はできるだけ抽象的に保った。スレッドの開始には1つの条件変数があり、終了のための1つの条件変数があり、どちらもセマフォインスタンスにカプセル化されています。 boost::barrier
の使用を提案し、他の答えを見て
、私はこの考えを支持することができます可能であれば、そのクラスで私のセマフォクラスを交換してください、十分にテスト頼りにする方が良いということであることの理由と同じ機能セットに対して自己実装されたソリューションではなく、外部コードを維持していました。
いずれのアプローチも有効ですが、前者は柔軟性のためにわずかなパフォーマンスを放棄します。実行されるタスクが十分に長い時間を要する場合、管理および待ち行列同期コストは無視できる程度になります。
更新:コードが修正され、テストされました。単純条件変数をセマフォに置き換えました。
正確にデッドロックですか。それは 'mythread [i] .join();にありますか? –
いいえ、これはデッドロックできないコードの例です。 デッドロックしないより優れた実装(結合しているスレッドを削除しない)が見つかりません。 – DarioP
あなたはおそらく[スレッドプール](http://stackoverflow.com/questions/3988128/c-thread-pool)を探していますか? – us2012