2017-01-23 2 views
-1

Unten ist ein Code, der eine einfache und kurze Implementierung eines Thread-Pools zeigt.C++ 11 Thread-Pool-Beispiel mit Fehler

Der Code ist inspiriert von this post.

ich kompilieren es mit clang++ -std=c++11 threadpool.cpp -o threadpool -lpthread

Wenn er ausgeführt wird Ich habe folgende:

./threadpool 
terminate called without an active exception 

Wie ich sehe, ist das Problem aus der Funktion bekommen pool_t::pop() und seine unendliche Schleife.

Meine Frage ist, wie elegant aus der Schleife zu bekommen?

den vergessenen Code - meine Entschuldigung -

#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

Sieht so aus, als hätten Sie den Code vergessen – NathanOliver

Antwort

0

In einem Fall wie diesem ist der einfachste Weg, eine Aufgabe einzureihen, die einfach eine bestimmte Art von Ausnahme wirft, als auf gefangen werden können und gehandelt ...

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

Wenn Sie brauchen nur aus der Schleife brechen tun ...

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

Abhängig von der genauen Verwendung möchten Sie vielleicht quit_exception einen privaten Typ machen, so dass nur pool_t selbst die Schleife auf diese Weise verlassen kann - in ihrem Destruktor zum Beispiel.