C++ 使用boostasio的线程池
我正在尝试使用boost::asio创建一个有限的线程池类。但有一点我很困惑,有人能帮我吗 唯一的问题是我应该在哪里减少计数器 代码未按预期工作 问题是我不知道我的线程何时完成执行,以及如何知道它已返回池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
#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_
}
};