2017-01-23 74 views
-1

下面是一些代碼,顯示了線程池的簡單和短的實現。C++ 11帶線程的線程池示例

該代碼的靈感來源於this post

clang++ -std=c++11 threadpool.cpp -o threadpool -lpthread

編譯執行時我得到了以下幾點:

./threadpool 
terminate called without an active exception 

依我之見,問題是失控的功能pool_t::pop()及其無限循環。

我的問題是,如何優雅地退出循環?

被遺忘的代碼 - 我的歉意 -

#include <vector> 
#include <queue> 
#include <thread> 
#include <mutex> 
#include <functional> 
#include <condition_variable> 

struct tasks_t 
{ 
    std::queue<std::function<void()>> queue; 

    std::mutex mutex; 
}; 

struct threads_t 
{ 
    std::vector<std::thread> vector; 

    std::condition_variable condition; 
}; 

struct pool_t 
{ 
    tasks_t tasks; 

    threads_t threads; 

    void pop() 
    { 
    while(true) 
    { 
     std::function<void()> task; 
     { 
     std::unique_lock<std::mutex> lock(tasks.mutex); 

     threads.condition.wait(lock,[this]{return !tasks.queue.empty();}); 

     task = tasks.queue.front(); 

     tasks.queue.pop(); 
     } 
     task(); 
    } 
    } 

    void push(std::function<void()> function) 
    { 
    { 
     std::unique_lock<std::mutex> lock(tasks.mutex); 

     tasks.queue.push(function); 
    } 
    threads.condition.notify_one(); 
    } 

    void start() 
    { 
    for (int i=0,j=std::thread::hardware_concurrency(); i!=j; ++i) 
    { 
     threads.vector.push_back(std::thread(&pool_t::pop,this)); 
    } 
    } 
}; 

#include <chrono> 
#include <iostream> 

std::function<void()> t0 = [] 
{ 
    std::cout << "t0" << std::endl; 
    std::this_thread::sleep_for(std::chrono::seconds(1)); 
    return; 
}; 

std::function<void()> t1 = [] 
{ 
    std::cout << "t1" << std::endl; 
    std::this_thread::sleep_for(std::chrono::seconds(2)); 
    return; 
}; 

int main() 
{ 
    pool_t pool; 

    pool.start(); 

    pool.push(t0); 

    pool.push(t1); 
} 
+6

看起來像忘了包含代碼 – NathanOliver

回答

0

的情況下,例如最簡單的辦法往往是排隊,簡單地拋出一個特定類型的異常相比,可以捕獲並採取行動任務...

struct pool_t { 
    class quit_exception {}; 
    tasks_t tasks; 
    threads_t threads; 

    void pop() 
    { 
    while (true) { 
     std::function<void()> task; 
     { 
     std::unique_lock<std::mutex> lock(tasks.mutex); 
     threads.condition.wait(lock, [this]{ return !tasks.queue.empty(); }); 
     task = tasks.queue.front(); 
     tasks.queue.pop(); 
     } 
     try { 
     task(); 
     } 
     catch (quit_exception &ex) { 
     return; 
     } 
    } 
    } 

當你需要跳出循環只是做的......

pool.push([](){ throw pool::quit_exception(); }); 

根據具體使用情況,您可能希望使quit_exception爲私有類型,以便只有pool_t本身才能以此方式退出循環 - 例如在其析構函數中。