Cancel handlers feature: replaced readers-writer lock with a spinlock implementation

This commit is contained in:
eidheim 2017-07-19 13:03:48 +02:00
commit 35f835a67b
6 changed files with 138 additions and 231 deletions

View file

@ -91,12 +91,10 @@ namespace SimpleWeb {
class Connection : public std::enable_shared_from_this<Connection> {
public:
template <typename... Args>
Connection(std::shared_ptr<bool> cancel_handlers, std::shared_ptr<SharedMutex> cancel_handlers_mutex, long timeout, Args &&... args)
: cancel_handlers(std::move(cancel_handlers)), cancel_handlers_mutex(std::move(cancel_handlers_mutex)), timeout(timeout),
socket(new socket_type(std::forward<Args>(args)...)) {}
Connection(std::shared_ptr<ContinueScopes> continue_handlers, long timeout, Args &&... args)
: continue_handlers(std::move(continue_handlers)), timeout(timeout), socket(new socket_type(std::forward<Args>(args)...)) {}
std::shared_ptr<bool> cancel_handlers;
std::shared_ptr<SharedMutex> cancel_handlers_mutex;
std::shared_ptr<ContinueScopes> continue_handlers;
long timeout;
std::unique_ptr<socket_type> socket; // Socket must be unique_ptr since asio::ssl::stream<asio::ip::tcp::socket> is not movable
@ -127,13 +125,6 @@ namespace SimpleWeb {
if(timer)
timer->cancel();
}
std::pair<bool, std::unique_ptr<SharedMutex::SharedLock>> cancel_handlers_bool_and_lock() {
if(!cancel_handlers)
return {false, nullptr};
auto lock = cancel_handlers_mutex->shared_lock();
return {*cancel_handlers, std::move(lock)};
}
};
class Session {
@ -337,12 +328,7 @@ namespace SimpleWeb {
}
virtual ~ClientBase() {
{
if(!internal_io_service) {
auto lock = cancel_handlers_mutex->unique_lock();
*cancel_handlers = true;
}
}
continue_handlers->stop();
stop();
}
@ -357,13 +343,12 @@ namespace SimpleWeb {
std::unordered_set<std::shared_ptr<Connection>> connections;
std::mutex connections_mutex;
std::shared_ptr<bool> cancel_handlers;
std::shared_ptr<SharedMutex> cancel_handlers_mutex;
std::shared_ptr<ContinueScopes> continue_handlers;
size_t concurrent_synchronous_requests = 0;
std::mutex concurrent_synchronous_requests_mutex;
ClientBase(const std::string &host_port, unsigned short default_port) : cancel_handlers(new bool(false)), cancel_handlers_mutex(new SharedMutex()) {
ClientBase(const std::string &host_port, unsigned short default_port) : continue_handlers(new ContinueScopes()) {
auto parsed_host_port = parse_host_port(host_port, default_port);
host = parsed_host_port.first;
port = parsed_host_port.second;
@ -376,8 +361,6 @@ namespace SimpleWeb {
if(!io_service) {
io_service = std::make_shared<asio::io_service>();
internal_io_service = true;
cancel_handlers = nullptr;
cancel_handlers_mutex = nullptr;
}
for(auto it = connections.begin(); it != connections.end(); ++it) {
@ -442,8 +425,8 @@ namespace SimpleWeb {
session->connection->set_timeout();
asio::async_write(*session->connection->socket, session->request_buffer->data(), [this, session](const error_code &ec, size_t /*bytes_transferred*/) {
session->connection->cancel_timeout();
auto cancel_pair = session->connection->cancel_handlers_bool_and_lock();
if(cancel_pair.first)
auto lock = session->connection->continue_handlers->shared_lock();
if(!lock)
return;
if(!ec)
this->read(session);
@ -456,8 +439,8 @@ namespace SimpleWeb {
session->connection->set_timeout();
asio::async_read_until(*session->connection->socket, session->response->content_buffer, "\r\n\r\n", [this, session](const error_code &ec, size_t bytes_transferred) {
session->connection->cancel_timeout();
auto cancel_pair = session->connection->cancel_handlers_bool_and_lock();
if(cancel_pair.first)
auto lock = session->connection->continue_handlers->shared_lock();
if(!lock)
return;
if(!ec) {
session->connection->attempt_reconnect = true;
@ -476,8 +459,8 @@ namespace SimpleWeb {
session->connection->set_timeout();
asio::async_read(*session->connection->socket, session->response->content_buffer, asio::transfer_exactly(content_length - num_additional_bytes), [this, session](const error_code &ec, size_t /*bytes_transferred*/) {
session->connection->cancel_timeout();
auto cancel_pair = session->connection->cancel_handlers_bool_and_lock();
if(cancel_pair.first)
auto lock = session->connection->continue_handlers->shared_lock();
if(!lock)
return;
if(!ec)
session->callback(session->connection, ec);
@ -496,8 +479,8 @@ namespace SimpleWeb {
session->connection->set_timeout();
asio::async_read(*session->connection->socket, session->response->content_buffer, [this, session](const error_code &ec, size_t /*bytes_transferred*/) {
session->connection->cancel_timeout();
auto cancel_pair = session->connection->cancel_handlers_bool_and_lock();
if(cancel_pair.first)
auto lock = session->connection->continue_handlers->shared_lock();
if(!lock)
return;
if(!ec)
session->callback(session->connection, ec);
@ -536,8 +519,8 @@ namespace SimpleWeb {
session->connection->set_timeout();
asio::async_read_until(*session->connection->socket, session->response->content_buffer, "\r\n", [this, session, tmp_streambuf](const error_code &ec, size_t bytes_transferred) {
session->connection->cancel_timeout();
auto cancel_pair = session->connection->cancel_handlers_bool_and_lock();
if(cancel_pair.first)
auto lock = session->connection->continue_handlers->shared_lock();
if(!lock)
return;
if(!ec) {
std::string line;
@ -574,8 +557,8 @@ namespace SimpleWeb {
session->connection->set_timeout();
asio::async_read(*session->connection->socket, session->response->content_buffer, asio::transfer_exactly(2 + length - num_additional_bytes), [this, session, post_process](const error_code &ec, size_t /*bytes_transferred*/) {
session->connection->cancel_timeout();
auto cancel_pair = session->connection->cancel_handlers_bool_and_lock();
if(cancel_pair.first)
auto lock = session->connection->continue_handlers->shared_lock();
if(!lock)
return;
if(!ec)
post_process();
@ -604,7 +587,7 @@ namespace SimpleWeb {
protected:
std::shared_ptr<Connection> create_connection() override {
return std::make_shared<Connection>(cancel_handlers, cancel_handlers_mutex, config.timeout, *io_service);
return std::make_shared<Connection>(continue_handlers, config.timeout, *io_service);
}
void connect(const std::shared_ptr<Session> &session) override {
@ -613,15 +596,15 @@ namespace SimpleWeb {
session->connection->set_timeout(config.timeout_connect);
resolver->async_resolve(*query, [this, session, resolver](const error_code &ec, asio::ip::tcp::resolver::iterator it) {
session->connection->cancel_timeout();
auto cancel_pair = session->connection->cancel_handlers_bool_and_lock();
if(cancel_pair.first)
auto lock = session->connection->continue_handlers->shared_lock();
if(!lock)
return;
if(!ec) {
session->connection->set_timeout(config.timeout_connect);
asio::async_connect(*session->connection->socket, it, [this, session, resolver](const error_code &ec, asio::ip::tcp::resolver::iterator /*it*/) {
session->connection->cancel_timeout();
auto cancel_pair = session->connection->cancel_handlers_bool_and_lock();
if(cancel_pair.first)
auto lock = session->connection->continue_handlers->shared_lock();
if(!lock)
return;
if(!ec) {
asio::ip::tcp::no_delay option(true);