2015-06-20 96 views
0

有人可以解释在下面的lambda函数中创建线程的位置吗? 使用什么技术? 有人可以推荐一个参考来理解语义吗?使用lambda表达式构建线程

我现在张贴的全码:

class ThreadPool { 
public: 
    ThreadPool(size_t); 
    template<class F, class... Args> 
    auto enqueue(F&& f, Args&&... args) 
     ->std::future<typename std::result_of<F(Args...)>::type>; 
    ~ThreadPool(); 
private: 
    // need to keep track of threads so we can join them 
    std::vector<std::thread> workers_m; 
    // the task queue 
    std::queue< std::function<void()> > tasks_m; 

    // synchronization 
    std::mutex queue_mutex_m; 
    std::condition_variable condition_m; 
    bool stop_m; 
}; 

// the constructor just launches some amount of workers 
inline ThreadPool::ThreadPool(size_t threads) 
    : stop_m(false) 
{ 
    std::thread::id id = std::this_thread::get_id(); 
    for (size_t i = 0; i < threads; ++i) 
    { 
     workers_m.emplace_back(
      [this] 
     { 
      for (;;) 
      { 
       std::function<void()> task; 
       { 
        std::unique_lock<std::mutex> lock(this- >queue_mutex_m); 
        std::thread::id id1 = std::this_thread::get_id(); 
        this->condition_m.wait(lock, [this]{ return this->stop_m || !this->tasks_m.empty(); }); 
        std::thread::id id = std::this_thread::get_id(); 
        if (this->stop_m && this->tasks_m.empty()) 
         return; 
        task = std::move(this->tasks_m.front()); 
        this->tasks_m.pop(); 
       } 
       task(); 
      } 
     } 
     ); 
    } 
} 
+0

您没有在任何地方创建线程。 –

+0

感谢T.C.,我现在添加了完整的代码 – user2286810

+0

'emplace_back'函数被赋予了一个lambda,它在'workers_m'向量上构造了一个'std :: thread'。 – Alejandro

回答

0

ThreadPool的构造函数使用的std::vectoremplace_back功能构建std::threadworkers_m变量的后面。 emplace_backpush_back不同之处在于它通过转发传递给元素类型构造函数的参数(std::thread)直接构造元素类型。另一方面,另一方面,要求左值或临时元素类型,然后将其适当地复制或移动到矢量的后面。

ThreadPool的构造函数将在for循环中执行此操作,以创建适当数量的工作线程,如构造函数参数(threads)所指定。 std::threads constructors之一需要一个可调用的和任意数量的参数,并将在相应的线程上运行该函数。在这种情况下,传入的lambda被用来构造一个只要需要就运行的线程(由for(;;)给出),获取一个互斥体以授予对任务队列的独占访问权,并使用一个条件变量来等待要么设置停止标志,要么直到队列中有可用的东西。

一旦通知条件变量并且两个条件中的一个为真,该线程就可以继续。然而,这两个条件是真不知道,因此对于

if (this->stop_m && this->tasks_m.empty()) 
        return; 

这似乎有点瑕疵的,虽然检查,因为如果stop_m设置工作线程应该停止处理任务,即使队列仍包含要做的任务。但是这种检查只会触发这两种情况都是事实。

如果上面的检查是错误的,线程std::move的任务就是从队列中执行pop() s,然后释放由锁的析构函数决定的由unique_lock保存的互斥锁。线程然后通过调用它来执行任务。由于for(;;)循环,此过程重复执行

+0

谢谢亚历杭德罗,你的回答很棒 – user2286810

+0

太棒了!我很高兴我能帮忙=) – Alejandro