1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
//
// prioritised_handlers.cpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/asio.hpp>
#include <boost/function.hpp>
#include <iostream>
#include <queue>
using boost::asio::ip::tcp;
class handler_priority_queue
{
public:
void add(int priority, boost::function<void()> function)
{
handlers_.push(queued_handler(priority, function));
}
void execute_all()
{
while (!handlers_.empty())
{
queued_handler handler = handlers_.top();
handler.execute();
handlers_.pop();
}
}
// A generic wrapper class for handlers to allow the invocation to be hooked.
template <typename Handler>
class wrapped_handler
{
public:
wrapped_handler(handler_priority_queue& q, int p, Handler h)
: queue_(q), priority_(p), handler_(h)
{
}
void operator()()
{
handler_();
}
template <typename Arg1>
void operator()(Arg1 arg1)
{
handler_(arg1);
}
template <typename Arg1, typename Arg2>
void operator()(Arg1 arg1, Arg2 arg2)
{
handler_(arg1, arg2);
}
//private:
handler_priority_queue& queue_;
int priority_;
Handler handler_;
};
template <typename Handler>
wrapped_handler<Handler> wrap(int priority, Handler handler)
{
return wrapped_handler<Handler>(*this, priority, handler);
}
private:
class queued_handler
{
public:
queued_handler(int p, boost::function<void()> f)
: priority_(p), function_(f)
{
}
void execute()
{
function_();
}
friend bool operator<(const queued_handler& a,
const queued_handler& b)
{
return a.priority_ < b.priority_;
}
private:
int priority_;
boost::function<void()> function_;
};
std::priority_queue<queued_handler> handlers_;
};
// Custom invocation hook for wrapped handlers.
template <typename Function, typename Handler>
void asio_handler_invoke(Function f,
handler_priority_queue::wrapped_handler<Handler>* h)
{
h->queue_.add(h->priority_, f);
}
//----------------------------------------------------------------------
void high_priority_handler(const boost::system::error_code& /*ec*/)
{
std::cout << "High priority handler\n";
}
void middle_priority_handler(const boost::system::error_code& /*ec*/)
{
std::cout << "Middle priority handler\n";
}
void low_priority_handler()
{
std::cout << "Low priority handler\n";
}
int main()
{
boost::asio::io_service io_service;
handler_priority_queue pri_queue;
// Post a completion handler to be run immediately.
io_service.post(pri_queue.wrap(0, low_priority_handler));
// Start an asynchronous accept that will complete immediately.
tcp::endpoint endpoint(boost::asio::ip::address_v4::loopback(), 0);
tcp::acceptor acceptor(io_service, endpoint);
tcp::socket server_socket(io_service);
acceptor.async_accept(server_socket,
pri_queue.wrap(100, high_priority_handler));
tcp::socket client_socket(io_service);
client_socket.connect(acceptor.local_endpoint());
// Set a deadline timer to expire immediately.
boost::asio::deadline_timer timer(io_service);
timer.expires_at(boost::posix_time::neg_infin);
timer.async_wait(pri_queue.wrap(42, middle_priority_handler));
while (io_service.run_one())
{
// The custom invocation hook adds the handlers to the priority queue
// rather than executing them from within the poll_one() call.
while (io_service.poll_one())
;
pri_queue.execute_all();
}
return 0;
}
|