2015-03-31 2 views
1

Я использую 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 так что было бы думать, что это позволило переместить boost::asio::io_service даже хотя это на самом деле проходит const &, но безрезультатно.

Включает:

#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; 
} 

Функция:

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: Функция подписи обработчика должна быть: void handler();

Означает ли это, что нет никакого способа для меня, чтобы передать или возвращать значения из функции? Поскольку требуемая подпись обработчика не принимает параметров и не имеет возврата?

Это работает, но я действительно хотел бы знать, почему я не могу передать параметры или возвращаемое значение, только захватили переменные или переменные из вне сферы:/

auto ioref = std::ref(ioservice); 
ioservice.post([ioref]() 
       -> void 
       { parallel_remove_file(ioref, APPS_DIR, FILE_NAME); }); 

ответ

1

boost::bind, как std::bind , принимает параметры шаблона по значению.

Не имеет значения, что в конечном итоге параметры будут связаны с функцией, принимающей ссылки. Копия уже выполнена.

Вы можете исправить это, обернув параметр boost::ref. Или std::ref. Любой из них будет создавать объект, который ведет себя как ссылка на исходный обернутый объект, даже при копировании.

result = ioservice.post(boost::bind(parallel_found_file, 
            boost::ref(ioservice), 
            itr->path(), 
            file_name)); 

тогда это будет ваша ответственность, чтобы гарантировать, что ioservice жизнь до тех пор, как связанной функции.

Кроме того, невозможно передать параметры на io_service::post, вместо этого вы должны захватить переменные через список захвата лямбда или связать. See this link.

+0

Интересно, в чем была проблема. Итак, 'boost :: ref()' передает копию ссылки на переменную? Кроме того, связь продолжает давать мне головные боли: 'main.cpp: 68: 10: Variable имеет неполный тип 'void'' –

+0

@FranciscoAguilera, если вы можете использовать' auto', вы используете C++ 11 или позже. Я бы рекомендовал использовать лямбда здесь вместо 'boost :: bind', поскольку люди, похоже, считают, что лямбда намного менее запутанны. –

+0

Да, я, честно говоря, даже не знаю, что такое 'boost :: bind' или' std :: bind', я новичок в C++ и ушел от примеров. Я попробовал использовать лямбду и задумался. См. Редактирование. –

Смежные вопросы