提升线程池绑定错误 [英] boost thread pool bind errors
问题描述
我正在使用boost::asio
和boost::filesystem
来执行一些简单的异步文件系统操作.
只要在线程池中有要使用的线程,下面的代码段应该为在第一级中找到的每个目录生成一个新线程,该目录递归此类.依此类推.
似乎编译器无法识别我是通过引用传递boost::asio::io_service
,并抱怨:
main.cpp:51:51: Call to implicitly-deleted copy constructor of 'boost::asio::io_service'
我尝试了#define BOOST_ASIO_HAS_MOVE
,所以它会认为即使const &
确实通过了boost::asio::io_service
,也允许它移动boost::asio::io_service
,但无济于事.
包括:
#include <iostream>
#include <thread>
// Threadpool
#define BOOST_ASIO_HAS_MOVE
#include <boost/asio/io_service.hpp>
#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>
// Filesystem
#include <boost/filesystem.hpp>
主要:
int main(int argc, const char * argv[]) {
boost::asio::io_service ioservice;
boost::thread_group threadpool;
boost::asio::io_service::work work(ioservice);
unsigned int threads = std::thread::hardware_concurrency();
for(unsigned int i = 0; i < threads; ++i)
threadpool.create_thread(boost::bind(&boost::asio::io_service::run,
&ioservice));
ioservice.post(boost::bind(parallel_found_file,
ioservice, // Call to implicitly-deleted copy constructor of 'boost::asio::io_service'
APPS_DIR,
FILE_NAME));
threadpool.join_all();
ioservice.stop();
return 0;
}
功能:
static bool parallel_found_file(boost::asio::io_service & ioservice,
const boost::filesystem::path & dir_path,
const std::string & file_name)
{
if(!exists(dir_path))
return true;
boost::filesystem::directory_iterator end_itr;
for(boost::filesystem::directory_iterator itr(dir_path);
itr != end_itr;
++itr )
{
if(is_directory(itr->status()))
{
ioservice.post(boost::bind(parallel_found_file,
ioservice, // Call to implicitly-deleted copy constructor of 'boost::asio::io_service'
itr->path(),
file_name));
}
else
{
if(itr->path().filename().string().find(file_name)
!= std::string::npos)
{
return true;
}
}
}
return false;
}
ioservice.post(boost::bind(parallel_remove_file,
boost::ref(ioservice),
boost::ref(APPS_DIR),
boost::ref(FILE_NAME)));
io_service.hpp:102:3: Static_assert failed "CompletionHandler type requirements not met"
boost::asio::io_service::post
说:
处理程序的功能签名必须为:
void handler();
这是否意味着我无法通过该函数传递或返回值?由于所需的处理程序签名没有参数,也没有返回值?
现在可以使用,但是我真的很想知道为什么我不能传递参数或返回值,只能传递捕获的变量,或者不能传递作用域之外的变量:/
auto ioref = std::ref(ioservice);
ioservice.post([ioref]()
-> void
{ parallel_remove_file(ioref, APPS_DIR, FILE_NAME); });
boost::bind
与std::bind
类似,按值获取其模板参数.
最终将参数绑定到具有引用的函数并不重要.已尝试复制.
您可以通过以下方式解决此问题:使用 std::ref
.无论哪种方式,都将创建一个对象,即使复制时,该对象的行为也类似于对原始包装对象的引用.
result = ioservice.post(boost::bind(parallel_found_file,
boost::ref(ioservice),
itr->path(),
file_name));
然后,您有责任确保ioservice
与绑定函数一样长.
此外,不可能将参数传递给io_service::post
,而是必须通过lambda捕获列表或绑定来捕获变量. 请参阅此链接.
I'm using boost::asio
and boost::filesystem
to perform some simple asynchronous filesystem operations.
The following code snippet is supposed to spawn a new thread for every directory it finds in the first level that recurses such directory, and so on, as long as there are threads to use from the thread pool.
It seems that the compiler does not recognize that I am passing the boost::asio::io_service
by reference, and complains:
main.cpp:51:51: Call to implicitly-deleted copy constructor of 'boost::asio::io_service'
I tried #define BOOST_ASIO_HAS_MOVE
so it would think it is allowed to move the boost::asio::io_service
even though it is really being passed by const &
, but to no avail.
Includes:
#include <iostream>
#include <thread>
// Threadpool
#define BOOST_ASIO_HAS_MOVE
#include <boost/asio/io_service.hpp>
#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>
// Filesystem
#include <boost/filesystem.hpp>
Main:
int main(int argc, const char * argv[]) {
boost::asio::io_service ioservice;
boost::thread_group threadpool;
boost::asio::io_service::work work(ioservice);
unsigned int threads = std::thread::hardware_concurrency();
for(unsigned int i = 0; i < threads; ++i)
threadpool.create_thread(boost::bind(&boost::asio::io_service::run,
&ioservice));
ioservice.post(boost::bind(parallel_found_file,
ioservice, // Call to implicitly-deleted copy constructor of 'boost::asio::io_service'
APPS_DIR,
FILE_NAME));
threadpool.join_all();
ioservice.stop();
return 0;
}
Function:
static bool parallel_found_file(boost::asio::io_service & ioservice,
const boost::filesystem::path & dir_path,
const std::string & file_name)
{
if(!exists(dir_path))
return true;
boost::filesystem::directory_iterator end_itr;
for(boost::filesystem::directory_iterator itr(dir_path);
itr != end_itr;
++itr )
{
if(is_directory(itr->status()))
{
ioservice.post(boost::bind(parallel_found_file,
ioservice, // Call to implicitly-deleted copy constructor of 'boost::asio::io_service'
itr->path(),
file_name));
}
else
{
if(itr->path().filename().string().find(file_name)
!= std::string::npos)
{
return true;
}
}
}
return false;
}
Edit:
ioservice.post(boost::bind(parallel_remove_file,
boost::ref(ioservice),
boost::ref(APPS_DIR),
boost::ref(FILE_NAME)));
io_service.hpp:102:3: Static_assert failed "CompletionHandler type requirements not met"
boost::asio::io_service::post
says:
The function signature of the handler must be:
void handler();
Does this mean there's no way for me to pass or return values from the function? Since the required signature of the handler takes no parameters and has no return?
This works now, but I would really like to know why I can't pass parameters or a return value, only captured variables, or variables from outside the scope :/
auto ioref = std::ref(ioservice);
ioservice.post([ioref]()
-> void
{ parallel_remove_file(ioref, APPS_DIR, FILE_NAME); });
boost::bind
, like std::bind
, takes its template parameters by value.
It doesn't matter that the parameters will eventually be bound to a function taking references. The copy has already been attempted.
You can fix this by wrapping the parameter with boost::ref
. Or std::ref
. Either one will create an object that behaves like a reference to the original wrapped object, even when copied.
result = ioservice.post(boost::bind(parallel_found_file,
boost::ref(ioservice),
itr->path(),
file_name));
It will then be your responsibility to ensure that ioservice
lives as long as the bound function.
Also, it is not possible to pass parameters to io_service::post
rather, you must capture variables through a lambda capture list or bind. See this link.
这篇关于提升线程池绑定错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!