summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asio/src/examples/cpp03/tutorial
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/asio/src/examples/cpp03/tutorial')
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/daytime1/.gitignore10
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/daytime1/client.cpp57
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/daytime2/.gitignore10
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/daytime2/server.cpp50
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/daytime3/.gitignore10
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/daytime3/server.cpp117
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/daytime4/.gitignore10
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/daytime4/client.cpp52
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/daytime5/.gitignore10
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/daytime5/server.cpp58
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/daytime6/.gitignore10
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/daytime6/server.cpp89
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/daytime7/.gitignore10
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/daytime7/server.cpp158
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/daytime_dox.txt502
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/index_dox.txt48
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/timer1/.gitignore10
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/timer1/timer.cpp25
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/timer2/.gitignore10
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/timer2/timer.cpp30
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/timer3/.gitignore10
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/timer3/timer.cpp44
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/timer4/.gitignore10
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/timer4/timer.cpp55
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/timer5/.gitignore10
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/timer5/timer.cpp81
-rw-r--r--3rdparty/asio/src/examples/cpp03/tutorial/timer_dox.txt383
27 files changed, 1869 insertions, 0 deletions
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/daytime1/.gitignore b/3rdparty/asio/src/examples/cpp03/tutorial/daytime1/.gitignore
new file mode 100644
index 00000000000..2926eaf9bf6
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/daytime1/.gitignore
@@ -0,0 +1,10 @@
+client
+.deps
+.dirstamp
+*.o
+*.obj
+*.exe
+*.ilk
+*.manifest
+*.pdb
+*.tds
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/daytime1/client.cpp b/3rdparty/asio/src/examples/cpp03/tutorial/daytime1/client.cpp
new file mode 100644
index 00000000000..9784d48a6fb
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/daytime1/client.cpp
@@ -0,0 +1,57 @@
+//
+// client.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2016 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 <iostream>
+#include <boost/array.hpp>
+#include <asio.hpp>
+
+using asio::ip::tcp;
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: client <host>" << std::endl;
+ return 1;
+ }
+
+ asio::io_context io_context;
+
+ tcp::resolver resolver(io_context);
+ tcp::resolver::results_type endpoints =
+ resolver.resolve(argv[1], "daytime");
+
+ tcp::socket socket(io_context);
+ asio::connect(socket, endpoints);
+
+ for (;;)
+ {
+ boost::array<char, 128> buf;
+ asio::error_code error;
+
+ size_t len = socket.read_some(asio::buffer(buf), error);
+
+ if (error == asio::error::eof)
+ break; // Connection closed cleanly by peer.
+ else if (error)
+ throw asio::system_error(error); // Some other error.
+
+ std::cout.write(buf.data(), len);
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+
+ return 0;
+}
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/daytime2/.gitignore b/3rdparty/asio/src/examples/cpp03/tutorial/daytime2/.gitignore
new file mode 100644
index 00000000000..7f06efb3296
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/daytime2/.gitignore
@@ -0,0 +1,10 @@
+server
+.deps
+.dirstamp
+*.o
+*.obj
+*.exe
+*.ilk
+*.manifest
+*.pdb
+*.tds
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/daytime2/server.cpp b/3rdparty/asio/src/examples/cpp03/tutorial/daytime2/server.cpp
new file mode 100644
index 00000000000..f662ed246c4
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/daytime2/server.cpp
@@ -0,0 +1,50 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2016 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 <ctime>
+#include <iostream>
+#include <string>
+#include <asio.hpp>
+
+using asio::ip::tcp;
+
+std::string make_daytime_string()
+{
+ using namespace std; // For time_t, time and ctime;
+ time_t now = time(0);
+ return ctime(&now);
+}
+
+int main()
+{
+ try
+ {
+ asio::io_context io_context;
+
+ tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), 13));
+
+ for (;;)
+ {
+ tcp::socket socket(io_context);
+ acceptor.accept(socket);
+
+ std::string message = make_daytime_string();
+
+ asio::error_code ignored_error;
+ asio::write(socket, asio::buffer(message), ignored_error);
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+
+ return 0;
+}
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/daytime3/.gitignore b/3rdparty/asio/src/examples/cpp03/tutorial/daytime3/.gitignore
new file mode 100644
index 00000000000..7f06efb3296
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/daytime3/.gitignore
@@ -0,0 +1,10 @@
+server
+.deps
+.dirstamp
+*.o
+*.obj
+*.exe
+*.ilk
+*.manifest
+*.pdb
+*.tds
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/daytime3/server.cpp b/3rdparty/asio/src/examples/cpp03/tutorial/daytime3/server.cpp
new file mode 100644
index 00000000000..cb2c9480594
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/daytime3/server.cpp
@@ -0,0 +1,117 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2016 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 <ctime>
+#include <iostream>
+#include <string>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <asio.hpp>
+
+using asio::ip::tcp;
+
+std::string make_daytime_string()
+{
+ using namespace std; // For time_t, time and ctime;
+ time_t now = time(0);
+ return ctime(&now);
+}
+
+class tcp_connection
+ : public boost::enable_shared_from_this<tcp_connection>
+{
+public:
+ typedef boost::shared_ptr<tcp_connection> pointer;
+
+ static pointer create(asio::io_context& io_context)
+ {
+ return pointer(new tcp_connection(io_context));
+ }
+
+ tcp::socket& socket()
+ {
+ return socket_;
+ }
+
+ void start()
+ {
+ message_ = make_daytime_string();
+
+ asio::async_write(socket_, asio::buffer(message_),
+ boost::bind(&tcp_connection::handle_write, shared_from_this(),
+ asio::placeholders::error,
+ asio::placeholders::bytes_transferred));
+ }
+
+private:
+ tcp_connection(asio::io_context& io_context)
+ : socket_(io_context)
+ {
+ }
+
+ void handle_write(const asio::error_code& /*error*/,
+ size_t /*bytes_transferred*/)
+ {
+ }
+
+ tcp::socket socket_;
+ std::string message_;
+};
+
+class tcp_server
+{
+public:
+ tcp_server(asio::io_context& io_context)
+ : acceptor_(io_context, tcp::endpoint(tcp::v4(), 13))
+ {
+ start_accept();
+ }
+
+private:
+ void start_accept()
+ {
+ tcp_connection::pointer new_connection =
+ tcp_connection::create(acceptor_.get_executor().context());
+
+ acceptor_.async_accept(new_connection->socket(),
+ boost::bind(&tcp_server::handle_accept, this, new_connection,
+ asio::placeholders::error));
+ }
+
+ void handle_accept(tcp_connection::pointer new_connection,
+ const asio::error_code& error)
+ {
+ if (!error)
+ {
+ new_connection->start();
+ }
+
+ start_accept();
+ }
+
+ tcp::acceptor acceptor_;
+};
+
+int main()
+{
+ try
+ {
+ asio::io_context io_context;
+ tcp_server server(io_context);
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+
+ return 0;
+}
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/daytime4/.gitignore b/3rdparty/asio/src/examples/cpp03/tutorial/daytime4/.gitignore
new file mode 100644
index 00000000000..2926eaf9bf6
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/daytime4/.gitignore
@@ -0,0 +1,10 @@
+client
+.deps
+.dirstamp
+*.o
+*.obj
+*.exe
+*.ilk
+*.manifest
+*.pdb
+*.tds
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/daytime4/client.cpp b/3rdparty/asio/src/examples/cpp03/tutorial/daytime4/client.cpp
new file mode 100644
index 00000000000..da3b651d56d
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/daytime4/client.cpp
@@ -0,0 +1,52 @@
+//
+// client.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2016 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 <iostream>
+#include <boost/array.hpp>
+#include <asio.hpp>
+
+using asio::ip::udp;
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: client <host>" << std::endl;
+ return 1;
+ }
+
+ asio::io_context io_context;
+
+ udp::resolver resolver(io_context);
+ udp::endpoint receiver_endpoint =
+ *resolver.resolve(udp::v4(), argv[1], "daytime").begin();
+
+ udp::socket socket(io_context);
+ socket.open(udp::v4());
+
+ boost::array<char, 1> send_buf = {{ 0 }};
+ socket.send_to(asio::buffer(send_buf), receiver_endpoint);
+
+ boost::array<char, 128> recv_buf;
+ udp::endpoint sender_endpoint;
+ size_t len = socket.receive_from(
+ asio::buffer(recv_buf), sender_endpoint);
+
+ std::cout.write(recv_buf.data(), len);
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+
+ return 0;
+}
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/daytime5/.gitignore b/3rdparty/asio/src/examples/cpp03/tutorial/daytime5/.gitignore
new file mode 100644
index 00000000000..7f06efb3296
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/daytime5/.gitignore
@@ -0,0 +1,10 @@
+server
+.deps
+.dirstamp
+*.o
+*.obj
+*.exe
+*.ilk
+*.manifest
+*.pdb
+*.tds
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/daytime5/server.cpp b/3rdparty/asio/src/examples/cpp03/tutorial/daytime5/server.cpp
new file mode 100644
index 00000000000..fdf452562d2
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/daytime5/server.cpp
@@ -0,0 +1,58 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2016 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 <ctime>
+#include <iostream>
+#include <string>
+#include <boost/array.hpp>
+#include <asio.hpp>
+
+using asio::ip::udp;
+
+std::string make_daytime_string()
+{
+ using namespace std; // For time_t, time and ctime;
+ time_t now = time(0);
+ return ctime(&now);
+}
+
+int main()
+{
+ try
+ {
+ asio::io_context io_context;
+
+ udp::socket socket(io_context, udp::endpoint(udp::v4(), 13));
+
+ for (;;)
+ {
+ boost::array<char, 1> recv_buf;
+ udp::endpoint remote_endpoint;
+ asio::error_code error;
+ socket.receive_from(asio::buffer(recv_buf),
+ remote_endpoint, 0, error);
+
+ if (error && error != asio::error::message_size)
+ throw asio::system_error(error);
+
+ std::string message = make_daytime_string();
+
+ asio::error_code ignored_error;
+ socket.send_to(asio::buffer(message),
+ remote_endpoint, 0, ignored_error);
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+
+ return 0;
+}
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/daytime6/.gitignore b/3rdparty/asio/src/examples/cpp03/tutorial/daytime6/.gitignore
new file mode 100644
index 00000000000..7f06efb3296
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/daytime6/.gitignore
@@ -0,0 +1,10 @@
+server
+.deps
+.dirstamp
+*.o
+*.obj
+*.exe
+*.ilk
+*.manifest
+*.pdb
+*.tds
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/daytime6/server.cpp b/3rdparty/asio/src/examples/cpp03/tutorial/daytime6/server.cpp
new file mode 100644
index 00000000000..d67045ff990
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/daytime6/server.cpp
@@ -0,0 +1,89 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2016 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 <ctime>
+#include <iostream>
+#include <string>
+#include <boost/array.hpp>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <asio.hpp>
+
+using asio::ip::udp;
+
+std::string make_daytime_string()
+{
+ using namespace std; // For time_t, time and ctime;
+ time_t now = time(0);
+ return ctime(&now);
+}
+
+class udp_server
+{
+public:
+ udp_server(asio::io_context& io_context)
+ : socket_(io_context, udp::endpoint(udp::v4(), 13))
+ {
+ start_receive();
+ }
+
+private:
+ void start_receive()
+ {
+ socket_.async_receive_from(
+ asio::buffer(recv_buffer_), remote_endpoint_,
+ boost::bind(&udp_server::handle_receive, this,
+ asio::placeholders::error,
+ asio::placeholders::bytes_transferred));
+ }
+
+ void handle_receive(const asio::error_code& error,
+ std::size_t /*bytes_transferred*/)
+ {
+ if (!error || error == asio::error::message_size)
+ {
+ boost::shared_ptr<std::string> message(
+ new std::string(make_daytime_string()));
+
+ socket_.async_send_to(asio::buffer(*message), remote_endpoint_,
+ boost::bind(&udp_server::handle_send, this, message,
+ asio::placeholders::error,
+ asio::placeholders::bytes_transferred));
+
+ start_receive();
+ }
+ }
+
+ void handle_send(boost::shared_ptr<std::string> /*message*/,
+ const asio::error_code& /*error*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ }
+
+ udp::socket socket_;
+ udp::endpoint remote_endpoint_;
+ boost::array<char, 1> recv_buffer_;
+};
+
+int main()
+{
+ try
+ {
+ asio::io_context io_context;
+ udp_server server(io_context);
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+
+ return 0;
+}
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/daytime7/.gitignore b/3rdparty/asio/src/examples/cpp03/tutorial/daytime7/.gitignore
new file mode 100644
index 00000000000..7f06efb3296
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/daytime7/.gitignore
@@ -0,0 +1,10 @@
+server
+.deps
+.dirstamp
+*.o
+*.obj
+*.exe
+*.ilk
+*.manifest
+*.pdb
+*.tds
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/daytime7/server.cpp b/3rdparty/asio/src/examples/cpp03/tutorial/daytime7/server.cpp
new file mode 100644
index 00000000000..b9dc60558c9
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/daytime7/server.cpp
@@ -0,0 +1,158 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2016 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 <ctime>
+#include <iostream>
+#include <string>
+#include <boost/array.hpp>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <asio.hpp>
+
+using asio::ip::tcp;
+using asio::ip::udp;
+
+std::string make_daytime_string()
+{
+ using namespace std; // For time_t, time and ctime;
+ time_t now = time(0);
+ return ctime(&now);
+}
+
+class tcp_connection
+ : public boost::enable_shared_from_this<tcp_connection>
+{
+public:
+ typedef boost::shared_ptr<tcp_connection> pointer;
+
+ static pointer create(asio::io_context& io_context)
+ {
+ return pointer(new tcp_connection(io_context));
+ }
+
+ tcp::socket& socket()
+ {
+ return socket_;
+ }
+
+ void start()
+ {
+ message_ = make_daytime_string();
+
+ asio::async_write(socket_, asio::buffer(message_),
+ boost::bind(&tcp_connection::handle_write, shared_from_this()));
+ }
+
+private:
+ tcp_connection(asio::io_context& io_context)
+ : socket_(io_context)
+ {
+ }
+
+ void handle_write()
+ {
+ }
+
+ tcp::socket socket_;
+ std::string message_;
+};
+
+class tcp_server
+{
+public:
+ tcp_server(asio::io_context& io_context)
+ : acceptor_(io_context, tcp::endpoint(tcp::v4(), 13))
+ {
+ start_accept();
+ }
+
+private:
+ void start_accept()
+ {
+ tcp_connection::pointer new_connection =
+ tcp_connection::create(acceptor_.get_executor().context());
+
+ acceptor_.async_accept(new_connection->socket(),
+ boost::bind(&tcp_server::handle_accept, this, new_connection,
+ asio::placeholders::error));
+ }
+
+ void handle_accept(tcp_connection::pointer new_connection,
+ const asio::error_code& error)
+ {
+ if (!error)
+ {
+ new_connection->start();
+ }
+
+ start_accept();
+ }
+
+ tcp::acceptor acceptor_;
+};
+
+class udp_server
+{
+public:
+ udp_server(asio::io_context& io_context)
+ : socket_(io_context, udp::endpoint(udp::v4(), 13))
+ {
+ start_receive();
+ }
+
+private:
+ void start_receive()
+ {
+ socket_.async_receive_from(
+ asio::buffer(recv_buffer_), remote_endpoint_,
+ boost::bind(&udp_server::handle_receive, this,
+ asio::placeholders::error));
+ }
+
+ void handle_receive(const asio::error_code& error)
+ {
+ if (!error || error == asio::error::message_size)
+ {
+ boost::shared_ptr<std::string> message(
+ new std::string(make_daytime_string()));
+
+ socket_.async_send_to(asio::buffer(*message), remote_endpoint_,
+ boost::bind(&udp_server::handle_send, this, message));
+
+ start_receive();
+ }
+ }
+
+ void handle_send(boost::shared_ptr<std::string> /*message*/)
+ {
+ }
+
+ udp::socket socket_;
+ udp::endpoint remote_endpoint_;
+ boost::array<char, 1> recv_buffer_;
+};
+
+int main()
+{
+ try
+ {
+ asio::io_context io_context;
+ tcp_server server1(io_context);
+ udp_server server2(io_context);
+ io_context.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+
+ return 0;
+}
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/daytime_dox.txt b/3rdparty/asio/src/examples/cpp03/tutorial/daytime_dox.txt
new file mode 100644
index 00000000000..1bf591a43a8
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/daytime_dox.txt
@@ -0,0 +1,502 @@
+//
+// Copyright (c) 2003-2016 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)
+//
+
+/**
+\page tutdaytime1 Daytime.1 - A synchronous TCP daytime client
+
+This tutorial program shows how to use asio to implement a client application
+with TCP.
+
+\dontinclude daytime1/client.cpp
+\skip #include
+
+We start by including the necessary header files.
+
+\until asio.hpp
+
+The purpose of this application is to access a daytime service,
+so we need the user to specify the server.
+
+\until }
+
+All programs that use asio need to have at least one asio::io_service
+object.
+
+\until asio::io_service
+
+We need to turn the server name that was specified as a parameter to the
+application, into a TCP endpoint. To do this we use an
+asio::ip::tcp::resolver object.
+
+\until tcp::resolver
+
+A resolver takes a query object and turns it into a list of endpoints. We
+construct a query using the name of the server, specified in <tt>argv[1]</tt>,
+and the name of the service, in this case <tt>"daytime"</tt>.
+
+\until tcp::resolver::query
+
+The list of endpoints is returned using an iterator of type
+asio::ip::tcp::resolver::iterator. (Note that a default constructed
+asio::ip::tcp::resolver::iterator object can be used as an end iterator.)
+
+\until tcp::resolver::iterator
+
+Now we create and connect the socket. The list of endpoints obtained above may
+contain both IPv4 and IPv6 endpoints, so we need to try each of them until we
+find one that works. This keeps the client program independent of a specific IP
+version. The asio::connect() function does this for us automatically.
+
+\until asio::connect
+
+The connection is open. All we need to do now is read the response from the
+daytime service.
+
+We use a <tt>boost::array</tt> to hold the received data. The asio::buffer()
+function automatically determines the size of the array to help prevent buffer
+overruns. Instead of a <tt>boost::array</tt>, we could have used a <tt>char
+[]</tt> or <tt>std::vector</tt>.
+
+\until read_some
+
+When the server closes the connection, the asio::ip::tcp::socket::read_some()
+function will exit with the asio::error::eof error, which is how we know to
+exit the loop.
+
+\until }
+
+Finally, handle any exceptions that may have been thrown.
+
+\until }
+\until }
+
+See the \ref tutdaytime1src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Next: \ref tutdaytime2
+
+*/
+
+/**
+\page tutdaytime1src Source listing for Daytime.1
+\include daytime1/client.cpp
+Return to \ref tutdaytime1
+*/
+
+/**
+\page tutdaytime2 Daytime.2 - A synchronous TCP daytime server
+
+This tutorial program shows how to use asio to implement a server application
+with TCP.
+
+\dontinclude daytime2/server.cpp
+\skip #include
+
+\until using
+
+We define the function <tt>make_daytime_string()</tt> to create the string to
+be sent back to the client. This function will be reused in all of our daytime
+server applications.
+
+\until asio::io_service
+
+A asio::ip::tcp::acceptor object needs to be created to listen
+for new connections. It is initialised to listen on TCP port 13, for IP version 4.
+
+\until tcp::acceptor
+
+This is an iterative server, which means that it will handle one
+connection at a time. Create a socket that will represent the connection to the
+client, and then wait for a connection.
+
+\until acceptor.accept
+
+A client is accessing our service. Determine the current time
+and transfer this information to the client.
+
+\until }
+\until }
+
+Finally, handle any exceptions.
+
+\until }
+\until }
+
+See the \ref tutdaytime2src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tutdaytime1 \n
+Next: \ref tutdaytime3
+
+*/
+
+/**
+\page tutdaytime2src Source listing for Daytime.2
+\include daytime2/server.cpp
+Return to \ref tutdaytime2
+*/
+
+/**
+\page tutdaytime3 Daytime.3 - An asynchronous TCP daytime server
+
+\section tutdaytime3funcmain The main() function
+
+\dontinclude daytime3/server.cpp
+\skip int main()
+\until try
+\until {
+
+We need to create a server object to accept incoming client connections. The
+asio::io_service object provides I/O services, such as sockets, that the
+server object will use.
+
+\until tcp_server
+
+Run the asio::io_service object so that it will perform asynchronous operations
+on your behalf.
+
+\until return 0;
+\until }
+
+\section tutdaytime3classtcp_server The tcp_server class
+
+\dontinclude daytime3/server.cpp
+\skip class tcp_server
+\until public:
+
+The constructor initialises an acceptor to listen on TCP port 13.
+
+\until private:
+
+The function <tt>start_accept()</tt> creates a socket and initiates an
+asynchronous accept operation to wait for a new connection.
+
+\until }
+
+The function <tt>handle_accept()</tt> is called when the asynchronous accept
+operation initiated by <tt>start_accept()</tt> finishes. It services the client
+request, and then calls <tt>start_accept()</tt> to initiate the next accept
+operation.
+
+\until }
+\until }
+
+\section tutdaytime3classtcp_connection The tcp_connection class
+
+We will use <tt>shared_ptr</tt> and <tt>enable_shared_from_this</tt> because we
+want to keep the <tt>tcp_connection</tt> object alive as long as there is an
+operation that refers to it.
+
+\dontinclude daytime3/server.cpp
+\skip class tcp_connection
+\until shared_ptr
+\until }
+\until }
+
+In the function <tt>start()</tt>, we call asio::async_write() to serve the data
+to the client. Note that we are using asio::async_write(), rather than
+asio::ip::tcp::socket::async_write_some(), to ensure that the entire block of
+data is sent.
+
+\until {
+
+The data to be sent is stored in the class member <tt>message_</tt> as we need
+to keep the data valid until the asynchronous operation is complete.
+
+\until message_
+
+When initiating the asynchronous operation, and if using \ref boost_bind, you
+must specify only the arguments that match the handler's parameter list. In
+this program, both of the argument placeholders (asio::placeholders::error and
+asio::placeholders::bytes_transferred) could potentially have been removed,
+since they are not being used in <tt>handle_write()</tt>.
+
+\until placeholders::bytes_transferred
+
+Any further actions for this client connection are now the responsibility of
+<tt>handle_write()</tt>.
+
+\until };
+
+\section tutdaytime3remunused Removing unused handler parameters
+
+You may have noticed that the <tt>error</tt>, and <tt>bytes_transferred</tt>
+parameters are not used in the body of the <tt>handle_write()</tt> function. If
+parameters are not needed, it is possible to remove them from the function so
+that it looks like:
+
+\code
+ void handle_write()
+ {
+ }
+\endcode
+
+The asio::async_write() call used to initiate the call can then be changed to
+just:
+
+\code
+ asio::async_write(socket_, asio::buffer(message_),
+ boost::bind(&tcp_connection::handle_write, shared_from_this()));
+\endcode
+
+See the \ref tutdaytime3src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tutdaytime2 \n
+Next: \ref tutdaytime4
+
+*/
+
+/**
+\page tutdaytime3src Source listing for Daytime.3
+\include daytime3/server.cpp
+Return to \ref tutdaytime3
+*/
+
+/**
+\page tutdaytime4 Daytime.4 - A synchronous UDP daytime client
+
+This tutorial program shows how to use asio to implement a client application
+with UDP.
+
+\dontinclude daytime4/client.cpp
+\skip #include
+\until using asio::ip::udp;
+
+The start of the application is essentially the same as for the TCP daytime
+client.
+
+\until asio::io_service
+
+We use an asio::ip::udp::resolver object to find the correct remote endpoint to
+use based on the host and service names. The query is restricted to return only
+IPv4 endpoints by the asio::ip::udp::v4() argument.
+
+\until udp::v4
+
+The asio::ip::udp::resolver::resolve() function is guaranteed to return at
+least one endpoint in the list if it does not fail. This means it is safe to
+dereference the return value directly.
+
+\until udp::endpoint
+
+Since UDP is datagram-oriented, we will not be using a stream socket. Create an
+asio::ip::udp::socket and initiate contact with the remote endpoint.
+
+\until receiver_endpoint
+
+Now we need to be ready to accept whatever the server sends back to us. The
+endpoint on our side that receives the server's response will be initialised by
+asio::ip::udp::socket::receive_from().
+
+\until }
+
+Finally, handle any exceptions that may have been thrown.
+
+\until }
+\until }
+See the \ref tutdaytime4src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tutdaytime3 \n
+Next: \ref tutdaytime5
+
+*/
+
+/**
+\page tutdaytime4src Source listing for Daytime.4
+\include daytime4/client.cpp
+Return to \ref tutdaytime4
+*/
+
+/**
+\page tutdaytime5 Daytime.5 - A synchronous UDP daytime server
+
+This tutorial program shows how to use asio to implement a server application
+with UDP.
+
+\dontinclude daytime5/server.cpp
+\skip int main()
+\until asio::io_service
+
+Create an asio::ip::udp::socket object to receive requests on UDP port 13.
+
+\until udp::socket
+
+Wait for a client to initiate contact with us. The remote_endpoint object will
+be populated by asio::ip::udp::socket::receive_from().
+
+\until throw
+
+Determine what we are going to send back to the client.
+
+\until std::string message
+
+Send the response to the remote_endpoint.
+
+\until }
+\until }
+
+Finally, handle any exceptions.
+
+\until }
+\until }
+
+See the \ref tutdaytime5src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tutdaytime4 \n
+Next: \ref tutdaytime6
+
+*/
+
+/**
+\page tutdaytime5src Source listing for Daytime.5
+\include daytime5/server.cpp
+Return to \ref tutdaytime5
+*/
+
+/**
+\page tutdaytime6 Daytime.6 - An asynchronous UDP daytime server
+
+\section tutdaytime6funcmain The main() function
+
+\dontinclude daytime6/server.cpp
+\skip int main()
+\until try
+\until {
+
+Create a server object to accept incoming client requests, and run
+the asio::io_service object.
+
+\until return 0;
+\until }
+
+\section tutdaytime6classudp_server The udp_server class
+
+\dontinclude daytime6/server.cpp
+\skip class udp_server
+\until public:
+
+The constructor initialises a socket to listen on UDP port 13.
+
+\until private:
+\until {
+
+The function asio::ip::udp::socket::async_receive_from() will cause the
+application to listen in the background for a new request. When such a request
+is received, the asio::io_service object will invoke the
+<tt>handle_receive()</tt> function with two arguments: a value of type
+asio::error_code indicating whether the operation succeeded or failed, and a
+<tt>size_t</tt> value <tt>bytes_transferred</tt> specifying the number of bytes
+received.
+
+\until }
+
+The function <tt>handle_receive()</tt> will service the client request.
+
+\until {
+
+The <tt>error</tt> parameter contains the result of the asynchronous operation.
+Since we only provide the 1-byte <tt>recv_buffer_</tt> to contain the client's
+request, the asio::io_service object would return an error if the client sent
+anything larger. We can ignore such an error if it comes up.
+
+\until {
+
+Determine what we are going to send.
+
+\until make_daytime_string()
+
+We now call asio::ip::udp::socket::async_send_to() to serve the data to the
+client.
+
+\until asio::placeholders::bytes_transferred
+
+When initiating the asynchronous operation, and if using \ref boost_bind, you
+must specify only the arguments that match the handler's parameter list. In
+this program, both of the argument placeholders (asio::placeholders::error and
+asio::placeholders::bytes_transferred) could potentially have been removed.
+
+Start listening for the next client request.
+
+\until start_receive
+
+Any further actions for this client request are now the responsibility of
+<tt>handle_send()</tt>.
+
+\until }
+\until }
+
+The function <tt>handle_send()</tt> is invoked after the service request has
+been completed.
+
+\until }
+\until }
+
+See the \ref tutdaytime6src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tutdaytime5 \n
+Next: \ref tutdaytime7
+
+*/
+
+/**
+\page tutdaytime6src Source listing for Daytime.6
+\include daytime6/server.cpp
+Return to \ref tutdaytime6
+*/
+
+/**
+\page tutdaytime7 Daytime.7 - A combined TCP/UDP asynchronous server
+
+This tutorial program shows how to combine the two asynchronous servers that we
+have just written, into a single server application.
+
+\section tutdaytime7funcmain The main() function
+
+\dontinclude daytime7/server.cpp
+\skip int main()
+\until asio::io_service
+
+We will begin by creating a server object to accept a TCP client connection.
+
+\until tcp_server
+
+We also need a server object to accept a UDP client request.
+
+\until udp_server
+
+We have created two lots of work for the asio::io_service object to do.
+
+\until return 0;
+\until }
+
+\section tutdaytime7classtcp The tcp_connection and tcp_server classes
+
+The following two classes are taken from \ref tutdaytime3 "Daytime.3".
+
+\dontinclude daytime7/server.cpp
+\skip class tcp_connection
+\until };
+\until };
+
+\section tutdaytime7classudp The udp_server class
+
+Similarly, this next class is taken from the
+\ref tutdaytime6 "previous tutorial step".
+
+\dontinclude daytime7/server.cpp
+\skip class udp_server
+\until };
+
+See the \ref tutdaytime7src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tutdaytime6
+
+*/
+
+/**
+\page tutdaytime7src Source listing for Daytime.7
+\include daytime7/server.cpp
+Return to \ref tutdaytime7
+*/
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/index_dox.txt b/3rdparty/asio/src/examples/cpp03/tutorial/index_dox.txt
new file mode 100644
index 00000000000..7d3bd1a2912
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/index_dox.txt
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2003-2016 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)
+//
+
+/**
+\mainpage asio Tutorial
+
+\section tuttimer Basic Skills
+
+The tutorial programs in this first section introduce the fundamental concepts
+required to use the asio toolkit. Before plunging into the complex world of
+network programming, these tutorial programs illustrate the basic skills using
+simple asynchronous timers.
+
+\li \ref tuttimer1
+\li \ref tuttimer2
+\li \ref tuttimer3
+\li \ref tuttimer4
+\li \ref tuttimer5
+
+\section tutdaytime Introduction to Sockets
+
+The tutorial programs in this section show how to use asio to develop simple
+client and server programs. These tutorial programs are based around the <a
+href="http://www.ietf.org/rfc/rfc867.txt">daytime</a> protocol, which supports
+both TCP and UDP.
+
+The first three tutorial programs implement the daytime protocol using TCP.
+
+\li \ref tutdaytime1
+\li \ref tutdaytime2
+\li \ref tutdaytime3
+
+The next three tutorial programs implement the daytime protocol using UDP.
+
+\li \ref tutdaytime4
+\li \ref tutdaytime5
+\li \ref tutdaytime6
+
+The last tutorial program in this section demonstrates how asio allows the TCP
+and UDP servers to be easily combined into a single program.
+
+\li \ref tutdaytime7
+
+*/
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/timer1/.gitignore b/3rdparty/asio/src/examples/cpp03/tutorial/timer1/.gitignore
new file mode 100644
index 00000000000..1d47ca67c43
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/timer1/.gitignore
@@ -0,0 +1,10 @@
+timer
+.deps
+.dirstamp
+*.o
+*.obj
+*.exe
+*.ilk
+*.manifest
+*.pdb
+*.tds
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/timer1/timer.cpp b/3rdparty/asio/src/examples/cpp03/tutorial/timer1/timer.cpp
new file mode 100644
index 00000000000..79ddf918261
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/timer1/timer.cpp
@@ -0,0 +1,25 @@
+//
+// timer.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2016 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 <iostream>
+#include <asio.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+int main()
+{
+ asio::io_context io;
+
+ asio::deadline_timer t(io, boost::posix_time::seconds(5));
+ t.wait();
+
+ std::cout << "Hello, world!" << std::endl;
+
+ return 0;
+}
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/timer2/.gitignore b/3rdparty/asio/src/examples/cpp03/tutorial/timer2/.gitignore
new file mode 100644
index 00000000000..1d47ca67c43
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/timer2/.gitignore
@@ -0,0 +1,10 @@
+timer
+.deps
+.dirstamp
+*.o
+*.obj
+*.exe
+*.ilk
+*.manifest
+*.pdb
+*.tds
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/timer2/timer.cpp b/3rdparty/asio/src/examples/cpp03/tutorial/timer2/timer.cpp
new file mode 100644
index 00000000000..3275c22c2f6
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/timer2/timer.cpp
@@ -0,0 +1,30 @@
+//
+// timer.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2016 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 <iostream>
+#include <asio.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+void print(const asio::error_code& /*e*/)
+{
+ std::cout << "Hello, world!" << std::endl;
+}
+
+int main()
+{
+ asio::io_context io;
+
+ asio::deadline_timer t(io, boost::posix_time::seconds(5));
+ t.async_wait(&print);
+
+ io.run();
+
+ return 0;
+}
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/timer3/.gitignore b/3rdparty/asio/src/examples/cpp03/tutorial/timer3/.gitignore
new file mode 100644
index 00000000000..1d47ca67c43
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/timer3/.gitignore
@@ -0,0 +1,10 @@
+timer
+.deps
+.dirstamp
+*.o
+*.obj
+*.exe
+*.ilk
+*.manifest
+*.pdb
+*.tds
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/timer3/timer.cpp b/3rdparty/asio/src/examples/cpp03/tutorial/timer3/timer.cpp
new file mode 100644
index 00000000000..dfbf7d660a0
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/timer3/timer.cpp
@@ -0,0 +1,44 @@
+//
+// timer.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2016 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 <iostream>
+#include <asio.hpp>
+#include <boost/bind.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+void print(const asio::error_code& /*e*/,
+ asio::deadline_timer* t, int* count)
+{
+ if (*count < 5)
+ {
+ std::cout << *count << std::endl;
+ ++(*count);
+
+ t->expires_at(t->expires_at() + boost::posix_time::seconds(1));
+ t->async_wait(boost::bind(print,
+ asio::placeholders::error, t, count));
+ }
+}
+
+int main()
+{
+ asio::io_context io;
+
+ int count = 0;
+ asio::deadline_timer t(io, boost::posix_time::seconds(1));
+ t.async_wait(boost::bind(print,
+ asio::placeholders::error, &t, &count));
+
+ io.run();
+
+ std::cout << "Final count is " << count << std::endl;
+
+ return 0;
+}
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/timer4/.gitignore b/3rdparty/asio/src/examples/cpp03/tutorial/timer4/.gitignore
new file mode 100644
index 00000000000..1d47ca67c43
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/timer4/.gitignore
@@ -0,0 +1,10 @@
+timer
+.deps
+.dirstamp
+*.o
+*.obj
+*.exe
+*.ilk
+*.manifest
+*.pdb
+*.tds
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/timer4/timer.cpp b/3rdparty/asio/src/examples/cpp03/tutorial/timer4/timer.cpp
new file mode 100644
index 00000000000..cbea70d26fa
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/timer4/timer.cpp
@@ -0,0 +1,55 @@
+//
+// timer.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2016 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 <iostream>
+#include <asio.hpp>
+#include <boost/bind.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+class printer
+{
+public:
+ printer(asio::io_context& io)
+ : timer_(io, boost::posix_time::seconds(1)),
+ count_(0)
+ {
+ timer_.async_wait(boost::bind(&printer::print, this));
+ }
+
+ ~printer()
+ {
+ std::cout << "Final count is " << count_ << std::endl;
+ }
+
+ void print()
+ {
+ if (count_ < 5)
+ {
+ std::cout << count_ << std::endl;
+ ++count_;
+
+ timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));
+ timer_.async_wait(boost::bind(&printer::print, this));
+ }
+ }
+
+private:
+ asio::deadline_timer timer_;
+ int count_;
+};
+
+int main()
+{
+ asio::io_context io;
+ printer p(io);
+ io.run();
+
+ return 0;
+}
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/timer5/.gitignore b/3rdparty/asio/src/examples/cpp03/tutorial/timer5/.gitignore
new file mode 100644
index 00000000000..1d47ca67c43
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/timer5/.gitignore
@@ -0,0 +1,10 @@
+timer
+.deps
+.dirstamp
+*.o
+*.obj
+*.exe
+*.ilk
+*.manifest
+*.pdb
+*.tds
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/timer5/timer.cpp b/3rdparty/asio/src/examples/cpp03/tutorial/timer5/timer.cpp
new file mode 100644
index 00000000000..a798e85aacf
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/timer5/timer.cpp
@@ -0,0 +1,81 @@
+//
+// timer.cpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2016 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 <iostream>
+#include <asio.hpp>
+#include <boost/bind.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+class printer
+{
+public:
+ printer(asio::io_context& io)
+ : strand_(io),
+ timer1_(io, boost::posix_time::seconds(1)),
+ timer2_(io, boost::posix_time::seconds(1)),
+ count_(0)
+ {
+ timer1_.async_wait(asio::bind_executor(strand_,
+ boost::bind(&printer::print1, this)));
+
+ timer2_.async_wait(asio::bind_executor(strand_,
+ boost::bind(&printer::print2, this)));
+ }
+
+ ~printer()
+ {
+ std::cout << "Final count is " << count_ << std::endl;
+ }
+
+ void print1()
+ {
+ if (count_ < 10)
+ {
+ std::cout << "Timer 1: " << count_ << std::endl;
+ ++count_;
+
+ timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(1));
+
+ timer1_.async_wait(asio::bind_executor(strand_,
+ boost::bind(&printer::print1, this)));
+ }
+ }
+
+ void print2()
+ {
+ if (count_ < 10)
+ {
+ std::cout << "Timer 2: " << count_ << std::endl;
+ ++count_;
+
+ timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(1));
+
+ timer2_.async_wait(asio::bind_executor(strand_,
+ boost::bind(&printer::print2, this)));
+ }
+ }
+
+private:
+ asio::io_context::strand strand_;
+ asio::deadline_timer timer1_;
+ asio::deadline_timer timer2_;
+ int count_;
+};
+
+int main()
+{
+ asio::io_context io;
+ printer p(io);
+ asio::thread t(boost::bind(&asio::io_context::run, &io));
+ io.run();
+ t.join();
+
+ return 0;
+}
diff --git a/3rdparty/asio/src/examples/cpp03/tutorial/timer_dox.txt b/3rdparty/asio/src/examples/cpp03/tutorial/timer_dox.txt
new file mode 100644
index 00000000000..7c5a0a099a6
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp03/tutorial/timer_dox.txt
@@ -0,0 +1,383 @@
+//
+// Copyright (c) 2003-2016 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)
+//
+
+/**
+\page tuttimer1 Timer.1 - Using a timer synchronously
+
+This tutorial program introduces asio by showing how to perform a blocking
+wait on a timer.
+
+\dontinclude timer1/timer.cpp
+\skip #include
+
+We start by including the necessary header files.
+
+All of the asio classes can be used by simply including the <tt>"asio.hpp"</tt>
+header file.
+
+\until asio.hpp
+
+Since this example uses timers, we need to include the appropriate
+Boost.Date_Time header file for manipulating times.
+
+\until posix_time.hpp
+
+All programs that use asio need to have at least one asio::io_service object.
+This class provides access to I/O functionality. We declare an object of this
+type first thing in the main function.
+
+\until asio::io_service
+
+Next we declare an object of type asio::deadline_timer. The core asio classes
+that provide I/O functionality (or as in this case timer functionality) always
+take a reference to an io_service as their first constructor argument. The
+second argument to the constructor sets the timer to expire 5 seconds from now.
+
+\until asio::deadline_timer
+
+In this simple example we perform a blocking wait on the timer.
+That is, the call to asio::deadline_timer::wait() will not return until the
+timer has expired, 5 seconds after it was created (i.e. <b>not</b> from when the
+wait starts).
+
+A deadline timer is always in one of two states: "expired" or "not expired". If
+the asio::deadline_timer::wait() function is called on an expired timer, it
+will return immediately.
+
+\until wait
+
+Finally we print the obligatory <tt>"Hello, world!"</tt>
+message to show when the timer has expired.
+
+\until }
+
+See the \ref tuttimer1src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Next: \ref tuttimer2
+
+*/
+
+/**
+\page tuttimer1src Source listing for Timer.1
+\include timer1/timer.cpp
+Return to \ref tuttimer1
+*/
+
+/**
+\page tuttimer2 Timer.2 - Using a timer asynchronously
+
+This tutorial program demonstrates how to use asio's asynchronous callback
+functionality by modifying the program from tutorial Timer.1 to perform an
+asynchronous wait on the timer.
+
+\dontinclude timer2/timer.cpp
+\skip #include
+
+\until posix_time.hpp
+
+Using asio's asynchronous functionality means having a callback
+function that will be called when an asynchronous operation completes. In this
+program we define a function called <tt>print</tt> to be called when the
+asynchronous wait finishes.
+
+\until asio::deadline_timer
+
+Next, instead of doing a blocking wait as in tutorial Timer.1,
+we call the asio::deadline_timer::async_wait() function to perform an
+asynchronous wait. When calling this function we pass the <tt>print</tt>
+callback handler that was defined above.
+
+\skipline async_wait
+
+Finally, we must call the asio::io_service::run() member function
+on the io_service object.
+
+The asio library provides a guarantee that callback handlers will <b>only</b>
+be called from threads that are currently calling asio::io_service::run().
+Therefore unless the asio::io_service::run() function is called the callback for
+the asynchronous wait completion will never be invoked.
+
+The asio::io_service::run() function will also continue to run while there is
+still "work" to do. In this example, the work is the asynchronous wait on the
+timer, so the call will not return until the timer has expired and the
+callback has completed.
+
+It is important to remember to give the io_service some work to do before
+calling asio::io_service::run(). For example, if we had omitted the above call
+to asio::deadline_timer::async_wait(), the io_service would not have had any
+work to do, and consequently asio::io_service::run() would have returned
+immediately.
+
+\skip run
+\until }
+
+See the \ref tuttimer2src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tuttimer1 \n
+Next: \ref tuttimer3
+
+*/
+
+/**
+\page tuttimer2src Source listing for Timer.2
+\include timer2/timer.cpp
+Return to \ref tuttimer2
+*/
+
+/**
+\page tuttimer3 Timer.3 - Binding arguments to a handler
+
+In this tutorial we will modify the program from tutorial Timer.2 so that the
+timer fires once a second. This will show how to pass additional parameters to
+your handler function.
+
+\dontinclude timer3/timer.cpp
+\skip #include
+
+\until posix_time.hpp
+
+To implement a repeating timer using asio you need to change
+the timer's expiry time in your callback function, and to then start a new
+asynchronous wait. Obviously this means that the callback function will need
+to be able to access the timer object. To this end we add two new parameters
+to the <tt>print</tt> function:
+
+\li A pointer to a timer object.
+
+\li A counter so that we can stop the program when the timer fires for the
+sixth time.
+
+\until {
+
+As mentioned above, this tutorial program uses a counter to
+stop running when the timer fires for the sixth time. However you will observe
+that there is no explicit call to ask the io_service to stop. Recall that in
+tutorial Timer.2 we learnt that the asio::io_service::run() function completes
+when there is no more "work" to do. By not starting a new asynchronous wait on
+the timer when <tt>count</tt> reaches 5, the io_service will run out of work and
+stop running.
+
+\until ++
+
+Next we move the expiry time for the timer along by one second
+from the previous expiry time. By calculating the new expiry time relative to
+the old, we can ensure that the timer does not drift away from the
+whole-second mark due to any delays in processing the handler.
+
+\until expires_at
+
+Then we start a new asynchronous wait on the timer. As you can
+see, the \ref boost_bind function is used to associate the extra parameters
+with your callback handler. The asio::deadline_timer::async_wait() function
+expects a handler function (or function object) with the signature
+<tt>void(const asio::error_code&)</tt>. Binding the additional parameters
+converts your <tt>print</tt> function into a function object that matches the
+signature correctly.
+
+See the <a href="http://www.boost.org/libs/bind/bind.html">Boost.Bind
+documentation</a> for more information on how to use \ref boost_bind.
+
+In this example, the asio::placeholders::error argument to \ref boost_bind is a
+named placeholder for the error object passed to the handler. When initiating
+the asynchronous operation, and if using \ref boost_bind, you must specify only
+the arguments that match the handler's parameter list. In tutorial Timer.4 you
+will see that this placeholder may be elided if the parameter is not needed by
+the callback handler.
+
+\until asio::io_service
+
+A new <tt>count</tt> variable is added so that we can stop the
+program when the timer fires for the sixth time.
+
+\until asio::deadline_timer
+
+As in Step 4, when making the call to
+asio::deadline_timer::async_wait() from <tt>main</tt> we bind the additional
+parameters needed for the <tt>print</tt> function.
+
+\until run
+
+Finally, just to prove that the <tt>count</tt> variable was
+being used in the <tt>print</tt> handler function, we will print out its new
+value.
+
+\until }
+
+See the \ref tuttimer3src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tuttimer2 \n
+Next: \ref tuttimer4
+
+*/
+
+/**
+\page tuttimer3src Source listing for Timer.3
+\include timer3/timer.cpp
+Return to \ref tuttimer3
+*/
+
+/**
+\page tuttimer4 Timer.4 - Using a member function as a handler
+
+In this tutorial we will see how to use a class member function as a callback
+handler. The program should execute identically to the tutorial program from
+tutorial Timer.3.
+
+\dontinclude timer4/timer.cpp
+\skip #include
+
+\until posix_time.hpp
+
+Instead of defining a free function <tt>print</tt> as the
+callback handler, as we did in the earlier tutorial programs, we now define a
+class called <tt>printer</tt>.
+
+\until public
+
+The constructor of this class will take a reference to the
+io_service object and use it when initialising the <tt>timer_</tt> member. The
+counter used to shut down the program is now also a member of the class.
+
+\until {
+
+The \ref boost_bind function works just as well with class
+member functions as with free functions. Since all non-static class member
+functions have an implicit <tt>this</tt> parameter, we need to bind
+<tt>this</tt> to the function. As in tutorial Timer.3, \ref boost_bind
+converts our callback handler (now a member function) into a function object
+that can be invoked as though it has the signature <tt>void(const
+asio::error_code&)</tt>.
+
+You will note that the asio::placeholders::error placeholder is not specified
+here, as the <tt>print</tt> member function does not accept an error object as
+a parameter.
+
+\until }
+
+In the class destructor we will print out the final value of
+the counter.
+
+\until }
+
+The <tt>print</tt> member function is very similar to the
+<tt>print</tt> function from tutorial Timer.3, except that it now operates on
+the class data members instead of having the timer and counter passed in as
+parameters.
+
+\until };
+
+The <tt>main</tt> function is much simpler than before, as it
+now declares a local <tt>printer</tt> object before running the io_service as
+normal.
+
+\until }
+
+See the \ref tuttimer4src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tuttimer3 \n
+Next: \ref tuttimer5 \n
+
+*/
+
+/**
+\page tuttimer4src Source listing for Timer.4
+\include timer4/timer.cpp
+Return to \ref tuttimer4
+*/
+
+/**
+\page tuttimer5 Timer.5 - Synchronising handlers in multithreaded programs
+
+This tutorial demonstrates the use of the asio::io_service::strand class to
+synchronise callback handlers in a multithreaded program.
+
+The previous four tutorials avoided the issue of handler synchronisation by
+calling the asio::io_service::run() function from one thread only. As you
+already know, the asio library provides a guarantee that callback handlers will
+<b>only</b> be called from threads that are currently calling
+asio::io_service::run(). Consequently, calling asio::io_service::run() from
+only one thread ensures that callback handlers cannot run concurrently.
+
+The single threaded approach is usually the best place to start when
+developing applications using asio. The downside is the limitations it places
+on programs, particularly servers, including:
+
+<ul>
+<li>Poor responsiveness when handlers can take a long time to complete.</li>
+<li>An inability to scale on multiprocessor systems.</li>
+</ul>
+
+If you find yourself running into these limitations, an alternative approach
+is to have a pool of threads calling asio::io_service::run(). However, as this
+allows handlers to execute concurrently, we need a method of synchronisation
+when handlers might be accessing a shared, thread-unsafe resource.
+
+\dontinclude timer5/timer.cpp
+\skip #include
+
+\until posix_time.hpp
+
+We start by defining a class called <tt>printer</tt>, similar
+to the class in the previous tutorial. This class will extend the previous
+tutorial by running two timers in parallel.
+
+\until public
+
+In addition to initialising a pair of asio::deadline_timer members, the
+constructor initialises the <tt>strand_</tt> member, an object of type
+asio::io_service::strand.
+
+An asio::io_service::strand is an executor that guarantees that, for those
+handlers that are dispatched through it, an executing handler will be allowed
+to complete before the next one is started. This is guaranteed irrespective of
+the number of threads that are calling asio::io_service::run(). Of course, the
+handlers may still execute concurrently with other handlers that were
+<b>not</b> dispatched through an asio::io_service::strand, or were dispatched
+through a different asio::io_service::strand object.
+
+\until {
+
+When initiating the asynchronous operations, each callback handler is "bound"
+to an asio::io_service::strand object. The
+asio::io_service::strand::bind_executor() function returns a new handler that
+automatically dispatches its contained handler through the
+asio::io_service::strand object. By binding the handlers to the same
+asio::io_service::strand, we are ensuring that they cannot execute
+concurrently.
+
+\until }
+\until }
+
+In a multithreaded program, the handlers for asynchronous
+operations should be synchronised if they access shared resources. In this
+tutorial, the shared resources used by the handlers (<tt>print1</tt> and
+<tt>print2</tt>) are <tt>std::cout</tt> and the <tt>count_</tt> data member.
+
+\until };
+
+The <tt>main</tt> function now causes asio::io_service::run() to
+be called from two threads: the main thread and one additional thread. This is
+accomplished using an asio::thread object.
+
+Just as it would with a call from a single thread, concurrent calls to
+asio::io_service::run() will continue to execute while there is "work" left to
+do. The background thread will not exit until all asynchronous operations have
+completed.
+
+\until }
+
+See the \ref tuttimer5src "full source listing" \n
+Return to the \ref index "tutorial index" \n
+Previous: \ref tuttimer4 \n
+
+*/
+
+/**
+\page tuttimer5src Source listing for Timer.5
+\include timer5/timer.cpp
+Return to \ref tuttimer5
+*/