提升线程池绑定错误 [英] boost thread pool bind errors

查看:145
本文介绍了提升线程池绑定错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用boost::asioboost::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::bindstd::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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆