C++ 使用boostasio的线程池

C++ 使用boostasio的线程池,c++,threadpool,boost-asio,C++,Threadpool,Boost Asio,我正在尝试使用boost::asio创建一个有限的线程池类。但有一点我很困惑,有人能帮我吗 唯一的问题是我应该在哪里减少计数器 代码未按预期工作 问题是我不知道我的线程何时完成执行,以及如何知道它已返回池 #include <boost/asio.hpp> #include <iostream> #include <boost/thread/thread.hpp> #include <boost/bind.hpp> #include <boo

我正在尝试使用boost::asio创建一个有限的线程池类。但有一点我很困惑,有人能帮我吗

唯一的问题是我应该在哪里减少计数器

代码未按预期工作

问题是我不知道我的线程何时完成执行,以及如何知道它已返回池

#include <boost/asio.hpp>
#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <boost/thread/mutex.hpp>
#include <stack>

using namespace std;
using namespace boost;

class ThreadPool
{
    static int count;
    int NoOfThread;
    thread_group grp;
    mutex mutex_;
    asio::io_service io_service;
    int counter;
    stack<thread*> thStk ;

public:
    ThreadPool(int num)
    {   
        NoOfThread = num;
        counter = 0;
        mutex::scoped_lock lock(mutex_);

        if(count == 0)
            count++;
        else
            return;

        for(int i=0 ; i<num ; ++i)
        {
            thStk.push(grp.create_thread(boost::bind(&asio::io_service::run, &io_service)));
        }
    }
    ~ThreadPool()
    {
        io_service.stop();
        grp.join_all();
    }

    thread* getThread()
    {
        if(counter > NoOfThread)
        {
            cout<<"run out of threads \n";
            return NULL;
        }

        counter++;
        thread* ptr = thStk.top();
        thStk.pop();
        return ptr;
    }
};
int ThreadPool::count = 0;


struct callable
{
    void operator()()
    {
        cout<<"some task for thread \n";
    }
};

int main( int argc, char * argv[] )
{

    callable x;
    ThreadPool pool(10);
    thread* p = pool.getThread();
    cout<<p->get_id();

    //how i can assign some function to thread pointer ?
    //how i can return thread pointer after work done so i can add 
//it back to stack?


    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
使用名称空间boost;
类线程池
{
静态整数计数;
int NoOfThread;
螺纹组;
互斥互斥;
asio::io_服务io_服务;
整数计数器;
堆栈thStk;
公众:
线程池(int num)
{   
NoOfThread=num;
计数器=0;
互斥锁::作用域锁定锁(互斥锁);
如果(计数=0)
计数++;
其他的
返回;
for(int i=0;i NoOfThread)
{

cout简而言之,您需要用另一个函数包装用户提供的任务,该函数将:

  • 调用用户函数或可调用对象
  • 锁定互斥锁并减小计数器

我可能不理解这个线程池的所有要求。因此,为了清楚起见,这里有一个关于我认为的要求的明确列表:

  • 池管理线程的生存期。用户不能删除驻留在池中的线程
  • 用户可以以非侵入性的方式向池分配任务
  • 分配任务时,如果池中的所有线程当前正在运行其他任务,则该任务将被丢弃
在提供实现之前,我想强调以下几点:

  • 一旦启动线程,它将一直运行到完成、取消或终止。线程正在执行的函数无法重新分配。为了允许单个线程在其生命周期内执行多个函数,线程将希望使用从队列读取的函数启动,例如
    io_service::run()
    ,可调用类型被发布到事件队列中,例如从
    io\u服务::post()
  • io\u服务::run()
    如果
    io\u服务中没有挂起的工作,则返回
    io\u服务
    ,或者从线程正在运行的处理程序中引发异常。要防止
    io\u服务::run()
    当没有未完成的工作时返回,可以使用
    io\u service::work
  • 定义任务的类型要求(即任务的类型必须可以通过
    object()
    语法调用),而不需要类型(即任务必须从
    进程
    继承),为用户提供了更大的灵活性。它允许用户将任务作为函数指针或提供空
    运算符()的类型提供
使用boost::asio实现

#include <boost/asio.hpp>
#include <boost/thread.hpp>

class thread_pool
{
private:
  boost::asio::io_service io_service_;
  boost::asio::io_service::work work_;
  boost::thread_group threads_;
  std::size_t available_;
  boost::mutex mutex_;
public:

  /// @brief Constructor.
  thread_pool( std::size_t pool_size )
    : work_( io_service_ ),
      available_( pool_size )
  {
    for ( std::size_t i = 0; i < pool_size; ++i )
    {
      threads_.create_thread( boost::bind( &boost::asio::io_service::run,
                                           &io_service_ ) );
    }
  }

  /// @brief Destructor.
  ~thread_pool()
  {
    // Force all threads to return from io_service::run().
    io_service_.stop();

    // Suppress all exceptions.
    try
    {
      threads_.join_all();
    }
    catch ( const std::exception& ) {}
  }

  /// @brief Adds a task to the thread pool if a thread is currently available.
  template < typename Task >
  void run_task( Task task )
  {
    boost::unique_lock< boost::mutex > lock( mutex_ );

    // If no threads are available, then return.
    if ( 0 == available_ ) return;

    // Decrement count, indicating thread is no longer available.
    --available_;

    // Post a wrapped task into the queue.
    io_service_.post( boost::bind( &thread_pool::wrap_task, this,
                                   boost::function< void() >( task ) ) );
  }

private:
  /// @brief Wrap a task so that the available count can be increased once
  ///        the user provided task has completed.
  void wrap_task( boost::function< void() > task )
  {
    // Run the user supplied task.
    try
    {
      task();
    }
    // Suppress all exceptions.
    catch ( const std::exception& ) {}

    // Task has finished, so increment count of available threads.
    boost::unique_lock< boost::mutex > lock( mutex_ );
    ++available_;
  }
};
线程池可以在没有Boost.Asio的情况下创建,对于维护人员来说可能会稍微容易一些,因为他们不再需要了解
Boost.Asio
行为,例如
io\u service::run()
何时返回,以及
io\u service::work
对象是什么:

#include <queue>
#include <boost/bind.hpp>
#include <boost/thread.hpp>

class thread_pool
{
private:
  std::queue< boost::function< void() > > tasks_;
  boost::thread_group threads_;
  std::size_t available_;
  boost::mutex mutex_;
  boost::condition_variable condition_;
  bool running_;
public:

  /// @brief Constructor.
  thread_pool( std::size_t pool_size )
    : available_( pool_size ),
      running_( true )
  {
    for ( std::size_t i = 0; i < pool_size; ++i )
    {
      threads_.create_thread( boost::bind( &thread_pool::pool_main, this ) ) ;
    }
  }

  /// @brief Destructor.
  ~thread_pool()
  {
    // Set running flag to false then notify all threads.
    {
      boost::unique_lock< boost::mutex > lock( mutex_ );
      running_ = false;
      condition_.notify_all();
    }

    try
    {
      threads_.join_all();
    }
    // Suppress all exceptions.
    catch ( const std::exception& ) {}
  }

  /// @brief Add task to the thread pool if a thread is currently available.
  template < typename Task >
  void run_task( Task task )
  {
    boost::unique_lock< boost::mutex > lock( mutex_ );

    // If no threads are available, then return.
    if ( 0 == available_ ) return;

    // Decrement count, indicating thread is no longer available.
    --available_;

    // Set task and signal condition variable so that a worker thread will
    // wake up andl use the task.
    tasks_.push( boost::function< void() >( task ) );
    condition_.notify_one();
  }

private:
  /// @brief Entry point for pool threads.
  void pool_main()
  {
    while( running_ )
    {
      // Wait on condition variable while the task is empty and the pool is
      // still running.
      boost::unique_lock< boost::mutex > lock( mutex_ );
      while ( tasks_.empty() && running_ )
      {
        condition_.wait( lock );
      }
      // If pool is no longer running, break out.
      if ( !running_ ) break;

      // Copy task locally and remove from the queue.  This is done within
      // its own scope so that the task object is destructed immediately
      // after running the task.  This is useful in the event that the
      // function contains shared_ptr arguments bound via bind.
      {
        boost::function< void() > task = tasks_.front();
        tasks_.pop();

        lock.unlock();

        // Run the task.
        try
        {
          task();
        }
        // Suppress all exceptions.
        catch ( const std::exception& ) {}
      }

      // Task has finished, so increment count of available threads.
      lock.lock();
      ++available_;
    } // while running_
  }
};
#包括
#包括
#包括
类线程池
{
私人:
std::queue>任务;
boost::线程组线程组;
标准::尺寸\u t可用\u;
boost::mutex mutex;
boost::条件u可变条件u;
布尔跑步;
公众:
///@brief构造函数。
线程池(标准::大小池大小)
:可用(池大小),
正在运行(真)
{
对于(std::size\u t i=0;ilock(互斥锁);
运行=错误;
条件通知所有人();
}
尝试
{
线程。连接所有线程();
}
//抑制所有异常。
catch(const std::exception&){
}
///@brief如果线程当前可用,则将任务添加到线程池。
模板
无效运行任务(任务任务)
{
boost::unique_locklock(互斥锁);
//如果没有可用的线程,则返回。
如果(0==可用),返回;
//递减计数,表示线程不再可用。
--可用的;
//设置任务和信号条件变量,以便工作线程
//醒醒,我来完成任务。
任务推送(boost::function(任务));
条件u.通知u one();
}
私人:
///@池线程的简短入口点。
空池_main()
{
当(运行时)
{
//任务为空且池为空时等待条件变量
//还在跑。
boost::unique_locklock(互斥锁);
while(tasks.empty()&&running)
{
条件等待(锁定);
}
//如果游泳池不再运行,请跳出。
如果(!running_)中断;
//本地复制任务并从队列中删除。此操作在
//它自己的作用域,以便立即销毁任务对象
//在运行任务之后。如果
//函数包含通过bind绑定的共享_ptr参数。
{
boost::functiontask=tasks\uuu.front();
tasks_uu.pop();
lock.unlock();
//运行任务。
尝试
{
任务();
}
//抑制所有异常。
catch(const std::exception&){
}
//任务已完成,因此增加可用线程的计数。
lock.lock();
++可用的;
}//运行时_
}
};

@jupiter感谢您的编辑,但这不是最终代码,请通过链接,直到底部您将看到修改后的代码@end.ple
#include <queue>
#include <boost/bind.hpp>
#include <boost/thread.hpp>

class thread_pool
{
private:
  std::queue< boost::function< void() > > tasks_;
  boost::thread_group threads_;
  std::size_t available_;
  boost::mutex mutex_;
  boost::condition_variable condition_;
  bool running_;
public:

  /// @brief Constructor.
  thread_pool( std::size_t pool_size )
    : available_( pool_size ),
      running_( true )
  {
    for ( std::size_t i = 0; i < pool_size; ++i )
    {
      threads_.create_thread( boost::bind( &thread_pool::pool_main, this ) ) ;
    }
  }

  /// @brief Destructor.
  ~thread_pool()
  {
    // Set running flag to false then notify all threads.
    {
      boost::unique_lock< boost::mutex > lock( mutex_ );
      running_ = false;
      condition_.notify_all();
    }

    try
    {
      threads_.join_all();
    }
    // Suppress all exceptions.
    catch ( const std::exception& ) {}
  }

  /// @brief Add task to the thread pool if a thread is currently available.
  template < typename Task >
  void run_task( Task task )
  {
    boost::unique_lock< boost::mutex > lock( mutex_ );

    // If no threads are available, then return.
    if ( 0 == available_ ) return;

    // Decrement count, indicating thread is no longer available.
    --available_;

    // Set task and signal condition variable so that a worker thread will
    // wake up andl use the task.
    tasks_.push( boost::function< void() >( task ) );
    condition_.notify_one();
  }

private:
  /// @brief Entry point for pool threads.
  void pool_main()
  {
    while( running_ )
    {
      // Wait on condition variable while the task is empty and the pool is
      // still running.
      boost::unique_lock< boost::mutex > lock( mutex_ );
      while ( tasks_.empty() && running_ )
      {
        condition_.wait( lock );
      }
      // If pool is no longer running, break out.
      if ( !running_ ) break;

      // Copy task locally and remove from the queue.  This is done within
      // its own scope so that the task object is destructed immediately
      // after running the task.  This is useful in the event that the
      // function contains shared_ptr arguments bound via bind.
      {
        boost::function< void() > task = tasks_.front();
        tasks_.pop();

        lock.unlock();

        // Run the task.
        try
        {
          task();
        }
        // Suppress all exceptions.
        catch ( const std::exception& ) {}
      }

      // Task has finished, so increment count of available threads.
      lock.lock();
      ++available_;
    } // while running_
  }
};