/usr/share/doc/libcppnetlib-doc/examples/network/http/hello_world_async_server_with_work_queue.cpp is in libcppnetlib-doc 0.11.0-1.1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | /*
* sample application to show the usage of work queues along with async http server
*
* (C) Copyright Dino Korah 2013.
* Distributed under the Boost Software License, Version 1.0. (See copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/network/include/http/server.hpp>
#include <boost/network/uri.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <list>
#include <signal.h>
#define Log(line) \
do { std::cout << line << std::endl; } while(false)
struct handler;
typedef boost::network::http::async_server<handler> server;
/**
* request + connection encapsulation (work item)
*/
struct request_data
{
const server::request req;
server::connection_ptr conn;
typedef boost::shared_ptr< request_data > pointer;
request_data(server::request const& req, const server::connection_ptr& conn) :
req(req), conn(conn)
{
}
};
/**
* A basic work queue
*/
struct work_queue
{
typedef std::list<request_data::pointer> list;
list requests;
boost::mutex mutex;
inline void put(const request_data::pointer& p_rd)
{
boost::unique_lock< boost::mutex > lock(mutex);
requests.push_back(p_rd);
(void)lock;
}
inline request_data::pointer get()
{
boost::unique_lock< boost::mutex > lock(mutex);
request_data::pointer p_ret;
if (!requests.empty()) {
p_ret = requests.front();
requests.pop_front();
}
(void)lock;
return p_ret;
}
};
struct handler
{
work_queue& queue;
handler(work_queue& queue) : queue(queue) { }
/**
* Feed the work queue
*
* @param req
* @param conn
*/
void operator()(server::request const& req, const server::connection_ptr& conn)
{
queue.put(boost::make_shared<request_data>(req, conn));
}
};
/**
* Clean shutdown signal handler
*
* @param error
* @param signal
* @param p_server_instance
*/
void shut_me_down(
const boost::system::error_code& error
, int signal, boost::shared_ptr< server > p_server_instance)
{
if (!error)
p_server_instance->stop();
}
/**
* Process request; worker (thread)
*
* @param queue
*/
void process_request(work_queue& queue)
{
while(!boost::this_thread::interruption_requested()) {
request_data::pointer p_req(queue.get());
if (p_req) {
// some heavy work!
boost::this_thread::sleep(boost::posix_time::seconds(10));
p_req->conn->set_status(server::connection::ok);
p_req->conn->write("Hello, world!");
}
boost::this_thread::sleep(boost::posix_time::microseconds(1000));
}
}
int main(void) try
{
// the thread group
boost::shared_ptr< boost::thread_group > p_threads(
boost::make_shared< boost::thread_group>());
// setup asio::io_service
boost::shared_ptr< boost::asio::io_service > p_io_service(
boost::make_shared< boost::asio::io_service >());
boost::shared_ptr< boost::asio::io_service::work > p_work(
boost::make_shared< boost::asio::io_service::work >(
boost::ref(*p_io_service)));
// io_service threads
{
int n_threads = 5;
while(0 < n_threads--) {
p_threads->create_thread(
boost::bind(&boost::asio::io_service::run, p_io_service));
}
}
// the shared work queue
work_queue queue;
// worker threads that will process the request; off the queue
{
int n_threads = 5;
while(0 < n_threads--) {
p_threads->create_thread(
boost::bind(process_request, boost::ref(queue)));
}
}
// setup the async server
handler request_handler(queue);
boost::shared_ptr< server > p_server_instance(
boost::make_shared<server>(
server::options(request_handler).
address("0.0.0.0")
.port("8800")
.io_service(p_io_service)
.reuse_address(true)
.thread_pool(
boost::make_shared<boost::network::utils::thread_pool>(
2 , p_io_service, p_threads))));
// setup clean shutdown
boost::asio::signal_set signals(*p_io_service, SIGINT, SIGTERM);
signals.async_wait(boost::bind(shut_me_down, _1, _2, p_server_instance));
// run the async server
p_server_instance->run();
// we are stopped - shutting down
p_threads->interrupt_all();
p_work.reset();
p_io_service->stop();
p_threads->join_all();
Log("Terminated normally");
exit(EXIT_SUCCESS);
}
catch(const std::exception& e)
{
Log("Abnormal termination - exception:"<<e.what());
exit(EXIT_FAILURE);
}
|