summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asio/src/tests/performance/server.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/asio/src/tests/performance/server.cpp')
-rw-r--r--3rdparty/asio/src/tests/performance/server.cpp233
1 files changed, 233 insertions, 0 deletions
diff --git a/3rdparty/asio/src/tests/performance/server.cpp b/3rdparty/asio/src/tests/performance/server.cpp
new file mode 100644
index 00000000000..374992178b3
--- /dev/null
+++ b/3rdparty/asio/src/tests/performance/server.cpp
@@ -0,0 +1,233 @@
+//
+// server.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2021 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 "asio.hpp"
+#include <algorithm>
+#include <boost/bind/bind.hpp>
+#include <iostream>
+#include <list>
+#include "handler_allocator.hpp"
+
+class session
+{
+public:
+ session(asio::io_context& ioc, size_t block_size)
+ : io_context_(ioc),
+ strand_(ioc.get_executor()),
+ socket_(ioc),
+ block_size_(block_size),
+ read_data_(new char[block_size]),
+ read_data_length_(0),
+ write_data_(new char[block_size]),
+ unsent_count_(0),
+ op_count_(0)
+ {
+ }
+
+ ~session()
+ {
+ delete[] read_data_;
+ delete[] write_data_;
+ }
+
+ asio::ip::tcp::socket& socket()
+ {
+ return socket_;
+ }
+
+ void start()
+ {
+ asio::error_code set_option_err;
+ asio::ip::tcp::no_delay no_delay(true);
+ socket_.set_option(no_delay, set_option_err);
+ if (!set_option_err)
+ {
+ ++op_count_;
+ socket_.async_read_some(asio::buffer(read_data_, block_size_),
+ asio::bind_executor(strand_,
+ make_custom_alloc_handler(read_allocator_,
+ boost::bind(&session::handle_read, this,
+ asio::placeholders::error,
+ asio::placeholders::bytes_transferred))));
+ }
+ else
+ {
+ asio::post(io_context_, boost::bind(&session::destroy, this));
+ }
+ }
+
+ void handle_read(const asio::error_code& err, size_t length)
+ {
+ --op_count_;
+
+ if (!err)
+ {
+ read_data_length_ = length;
+ ++unsent_count_;
+ if (unsent_count_ == 1)
+ {
+ op_count_ += 2;
+ std::swap(read_data_, write_data_);
+ async_write(socket_, asio::buffer(write_data_, read_data_length_),
+ asio::bind_executor(strand_,
+ make_custom_alloc_handler(write_allocator_,
+ boost::bind(&session::handle_write, this,
+ asio::placeholders::error))));
+ socket_.async_read_some(asio::buffer(read_data_, block_size_),
+ asio::bind_executor(strand_,
+ make_custom_alloc_handler(read_allocator_,
+ boost::bind(&session::handle_read, this,
+ asio::placeholders::error,
+ asio::placeholders::bytes_transferred))));
+ }
+ }
+
+ if (op_count_ == 0)
+ asio::post(io_context_, boost::bind(&session::destroy, this));
+ }
+
+ void handle_write(const asio::error_code& err)
+ {
+ --op_count_;
+
+ if (!err)
+ {
+ --unsent_count_;
+ if (unsent_count_ == 1)
+ {
+ op_count_ += 2;
+ std::swap(read_data_, write_data_);
+ async_write(socket_, asio::buffer(write_data_, read_data_length_),
+ asio::bind_executor(strand_,
+ make_custom_alloc_handler(write_allocator_,
+ boost::bind(&session::handle_write, this,
+ asio::placeholders::error))));
+ socket_.async_read_some(asio::buffer(read_data_, block_size_),
+ asio::bind_executor(strand_,
+ make_custom_alloc_handler(read_allocator_,
+ boost::bind(&session::handle_read, this,
+ asio::placeholders::error,
+ asio::placeholders::bytes_transferred))));
+ }
+ }
+
+ if (op_count_ == 0)
+ asio::post(io_context_, boost::bind(&session::destroy, this));
+ }
+
+ static void destroy(session* s)
+ {
+ delete s;
+ }
+
+private:
+ asio::io_context& io_context_;
+ asio::strand<asio::io_context::executor_type> strand_;
+ asio::ip::tcp::socket socket_;
+ size_t block_size_;
+ char* read_data_;
+ size_t read_data_length_;
+ char* write_data_;
+ int unsent_count_;
+ int op_count_;
+ handler_allocator read_allocator_;
+ handler_allocator write_allocator_;
+};
+
+class server
+{
+public:
+ server(asio::io_context& ioc, const asio::ip::tcp::endpoint& endpoint,
+ size_t block_size)
+ : io_context_(ioc),
+ acceptor_(ioc),
+ block_size_(block_size)
+ {
+ acceptor_.open(endpoint.protocol());
+ acceptor_.set_option(asio::ip::tcp::acceptor::reuse_address(1));
+ acceptor_.bind(endpoint);
+ acceptor_.listen();
+
+ start_accept();
+ }
+
+ void start_accept()
+ {
+ session* new_session = new session(io_context_, block_size_);
+ acceptor_.async_accept(new_session->socket(),
+ boost::bind(&server::handle_accept, this, new_session,
+ asio::placeholders::error));
+ }
+
+ void handle_accept(session* new_session, const asio::error_code& err)
+ {
+ if (!err)
+ {
+ new_session->start();
+ }
+ else
+ {
+ delete new_session;
+ }
+
+ start_accept();
+ }
+
+private:
+ asio::io_context& io_context_;
+ asio::ip::tcp::acceptor acceptor_;
+ size_t block_size_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 5)
+ {
+ std::cerr << "Usage: server <address> <port> <threads> <blocksize>\n";
+ return 1;
+ }
+
+ using namespace std; // For atoi.
+ asio::ip::address address = asio::ip::make_address(argv[1]);
+ short port = atoi(argv[2]);
+ int thread_count = atoi(argv[3]);
+ size_t block_size = atoi(argv[4]);
+
+ asio::io_context ioc;
+
+ server s(ioc, asio::ip::tcp::endpoint(address, port), block_size);
+
+ // Threads not currently supported in this test.
+ std::list<asio::thread*> threads;
+ while (--thread_count > 0)
+ {
+ asio::thread* new_thread = new asio::thread(
+ boost::bind(&asio::io_context::run, &ioc));
+ threads.push_back(new_thread);
+ }
+
+ ioc.run();
+
+ while (!threads.empty())
+ {
+ threads.front()->join();
+ delete threads.front();
+ threads.pop_front();
+ }
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}