#include <boost/asio.hpp>
#include <functional>
#include <thread>
using boost::asio::io_service;
class active_object
{
public:
typedef std::function<void ()> completion_handler;
active_object()
: work_(nullptr), strand_(service_)
{
}
~active_object()
{
// Must call stop before destructor is called
assert(work_ == nullptr);
}
void start(completion_handler handle_start)
{
assert(work_ == nullptr);
work_ = new io_service::work(service_);
runner_ = std::thread(&active_object::run_service, &service_);
post(handle_start);
}
void stop(completion_handler handle_stop)
{
// Cannot stop unless already started
assert(work_ != nullptr);
delete work_;
work_ = nullptr;
// Remaining jobs should complete
// Add completion handler for stop to end of queue
post(handle_stop);
}
template <typename HandlerFunction>
void post(HandlerFunction perform_operation)
{
strand_.post(perform_operation);
}
private:
static void run_service(io_service* service)
{
service->run();
}
io_service service_;
io_service::work* work_;
io_service::strand strand_;
std::thread runner_;
};
#include <iostream>
active_object* s = new active_object;
// Executed in this order
void handle_start();
void foo();
void bar();
void do_stop();
void handle_stop();
void handle_start()
{
s->post(foo);
s->post(bar);
s->post(do_stop);
}
void foo()
{
std::cout << "foo called" << std::endl;
}
void bar()
{
std::cout << "bar called" << std::endl;
}
void do_stop()
{
std::cout << "stop called" << std::endl;
s->stop(handle_stop);
}
void handle_stop()
{
delete s;
}
int main()
{
s->start(handle_start);
std::cin.get();
return 0;
}