2016-10-29 6 views
2

私はスレッドとスレッドの並行性を実践しています。私は自分のスレッドプールを作りたいと思います。私はスレッドのベクトルを持っているため、これらのスレッドは次の関数を別のベクトルから実行するために条件変数で待機します。スレッドプールに関数を渡します。

しかし、未知の引数を持つ関数の格納/渡し/実行に問題があります。誰かが私にこれを行う方法やこれに必要なことをヒントを与えることができますか?

ThreadPool tp(10); 
tp.execute(std::bind(print, i)); 

void print(int i) { 
    std::cout << i << std::endl; 
} 

void ThreadPool::execute(const std::function<void()> function) { 
    l.lock(); 
    if (running) { 
     queue.push_back(function); 
     cv.notify_one(); 
    } else { 
     // TODO error 
     std::cout << "err execute()\n";  
    } 
    l.unlock(); 
} 

糸ループ:

// set up threads in constructor 
for (int i = 0; i < size; i++) { 
    threads.push_back(std::thread(&ThreadPool::thread_loop, std::ref(*this), i)); 
} 

static void ThreadPool::thread_loop(ThreadPool &pool, int id) { 
    pool.o.lock(); 
    std::cout << "pool-" << pool.id << "-thread-" << id << " started\n"; 
    pool.o.unlock(); 
    std::function<void()> function; 
    std::unique_lock<std::mutex> ul(pool.m, std::defer_lock); 

    while (pool.running || pool.queue.size() > 0) { 
     ul.lock(); 
     while (pool.queue.size() == 0) { 
      pool.cv.wait(ul); 
     } 
     pool.l.lock(); 
     if (pool.queue.size() == 0) { 
      pool.l.unlock(); 
      continue; 
     } 
     function = pool.queue.at(0); 
     pool.queue.erase(pool.queue.begin()); 
     pool.l.unlock(); 
     ul.unlock(); 
     function(); 
    } 
} 
+0

これは 'のstd ::機能'を頼みます。これで、0引数の呼び出し可能なもの(関数、関数オブジェクト、ラムダ、 'std :: bind'の結果、あなたの名前)をスレッドプールに渡すことができます。 –

+0

m_threads.push_back(std :: thread(&InitThreadsFoo、m_threads.size()));を実行できます。既存のスレッドをベクトルから再割り当てして別の関数を引き継ぐ方法や、すでに使用されている既存のスレッドに関数を割り当てる方法も知っています。 – ReturnVoid

+0

@Andrey Turkinありがとう、これは素晴らしい作品です! – Pali

答えて

0

あなたは可変引数テンプレートとして機能+その引数を追加する必要があります。

template<class Task, class ...Args> 
void ThreadPool::execute(Task&& task, Args&& ... args) { 
    l.lock(); 
    if (running) { 
     queue.emplace_back(std::bind(std::forward<Task>(task),std::forward<Args>(args)...)); 
     cv.notify_one(); 
    } else { 
     // TODO error 
     std::cout << "err execute()\n";  
    } 
    l.unlock(); 
} 
タスクを追加する

:EDIT作業

使用例:

ThreadPool tp(/*whatever you pass the thread pool constructor*/); 
tp.execute(printf,"hello from the threadpool."); 
関連する問題