feeling_lonely
feeling_lonely

Reputation: 6853

boost:bind and io_service in two different classes

I am kind'a new to Boost.

I would like to know how to construct an io_service in one class and send it tasks from another class.

My problem is BOOST_ASIO_COMPLETION_HANDLER_CHECK complains and wont let the code compile.

He is a skeleton of my code:

type_defs.h (this has the function to be wrapped and sent to the io_service)

#include "boost/filesystem.hpp"

namespace fs = ::boost::filesystem;

typedef boost::function<void(const fs::path path)> parse_and_aggregate_fun_t;

io_service_processors.h (this is the class that will construct the io_service and wait for job posts).

namespace asio = boost::asio;

typedef std::unique_ptr<asio::io_service::work> work_ptr;

class io_service_processors {
public:
    io_service_processors(int tc);
    virtual ~io_service_processors();

    void init();
    void post_job(parse_and_aggregate_fun_t file_job);

private:
    int thread_count;
    asio::io_service* service;
    boost::mutex mtx;
    work_ptr * work;
    boost::thread_group workers;
};

io_service_processors.cpp

namespace asio = boost::asio;   

io_service_processors::io_service_processors(int tc):thread_count(tc) {

}

io_service_processors::~io_service_processors() {
       // clean up code here removed.
}

void io_service_processors::init() {
    this->service = new asio::io_service();
    this->work = new work_ptr(new asio::io_service::work(*(this->service)));
    for(int i = 0; i < this->thread_count; ++i)
        this->workers.create_thread(boost::bind(&asio::io_service::run, this->service));
}

void io_service_processors::post_job(parse_and_aggregate_fun_t file_job) {
    this->service->post(file_job);
}

job_discoverer.cpp (this one will discover files and send their paths to to the io_service, the function parse_and_aggregate will the actual work for opening the file and processing it, process will simply post the wrapped function to the io_service, this->processor is simply a pointer to the io_service wrapper class above).

void job_discoverer::process(const fs::path path){
    std::cout << "Posting file: " << path.string() << std::endl;
    if(this->processor)
        this->processor->post_job(
                boost::bind(&job_discoverer::parse_and_aggregate, this, path)
                );
}

void job_discoverer::parse_and_aggregate(const fs::path path) {
    std::cout << "Parsing and aggregating file: " << path.string() << std::endl;
}

Upvotes: 1

Views: 236

Answers (2)

sehe
sehe

Reputation: 392911

this->service->post(file_job);

tries to post a job, but it's not a nullary function. Of course this can't work. Did you mean to bind a value to the path parameter?

Even more interesting, that function (io_service_processors::post_job) is never used. If we - for humor sake - assume that post_job was actually meant where post_file_job was written, then you'll find that you actually pass a nullary bind-expression. So, fix it:

typedef boost::function<void()> any_job;

Live On Coliru

#include <boost/filesystem.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/function.hpp>

namespace fs = ::boost::filesystem;

typedef boost::function<void()> any_job;

#include <boost/asio.hpp>
namespace asio = boost::asio;

typedef std::unique_ptr<asio::io_service::work> work_ptr;

class io_service_processors {
public:
    io_service_processors(int tc);
    virtual ~io_service_processors();

    void init();
    void post_job(any_job file_job);

private:
    int thread_count;
    asio::io_service* service;
    boost::mutex mtx;
    work_ptr * work;
    boost::thread_group workers;
};

io_service_processors::io_service_processors(int tc):thread_count(tc) {

}

io_service_processors::~io_service_processors() {
       // clean up code here removed.
}

void io_service_processors::init() {
    this->service = new asio::io_service();
    this->work = new work_ptr(new asio::io_service::work(*(this->service)));
    for(int i = 0; i < this->thread_count; ++i)
        this->workers.create_thread(boost::bind(&asio::io_service::run, this->service));
}

void io_service_processors::post_job(any_job file_job) {
    std::cout << __PRETTY_FUNCTION__ << "\n";
    this->service->post(file_job);
}

struct job_discoverer {

    boost::optional<io_service_processors> processor;

    void process(const fs::path path){
        std::cout << "Posting file: " << path.string() << std::endl;
        if(this->processor)
            this->processor->post_job(
                    boost::bind(&job_discoverer::parse_and_aggregate, this, path)
                    );
    }

    void parse_and_aggregate(const fs::path path) {
        std::cout << "Parsing and aggregating file: " << path.string() << std::endl;
    }
};

int main() {
}

Upvotes: 1

Slyps
Slyps

Reputation: 607

In io_service_processors::post_job you put parse_and_aggregate_fun_t to io_service::post. The function signature for handler in io_service::post must be void(). Yours is void(const fs::path)

Upvotes: 1

Related Questions