From cc5147ad72a1846f6bed63b05cd26aa85cd121eb Mon Sep 17 00:00:00 2001 From: Snape3058 Date: Thu, 15 Oct 2020 20:09:11 +0800 Subject: [PATCH] Replace shared_ptr with unique_ptr for better performance (#695) * Backport std::make_unique from C++14. * Replace shared_ptr with unique_ptr for better performance. Co-authored-by: Ella --- httplib.h | 107 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 43 deletions(-) diff --git a/httplib.h b/httplib.h index e362719..c72fcbc 100644 --- a/httplib.h +++ b/httplib.h @@ -237,6 +237,27 @@ namespace httplib { namespace detail { +/* + * Backport std::make_unique from C++14. + * + * NOTE: This code came up with the following stackoverflow post: + * https://stackoverflow.com/questions/10149840/c-arrays-and-make-unique + * + */ + +template +typename std::enable_if::value, std::unique_ptr>::type +make_unique(Args &&... args) { + return std::unique_ptr(new T(std::forward(args)...)); +} + +template +typename std::enable_if::value, std::unique_ptr>::type +make_unique(std::size_t n) { + typedef typename std::remove_extent::type RT; + return std::unique_ptr(new RT[n]); +} + struct ci { bool operator()(const std::string &s1, const std::string &s2) const { return std::lexicographical_compare( @@ -713,8 +734,8 @@ enum Error { class Result { public: - Result(const std::shared_ptr &res, Error err) - : res_(res), err_(err) {} + Result(std::unique_ptr res, Error err) + : res_(std::move(res)), err_(err) {} operator bool() const { return res_ != nullptr; } bool operator==(std::nullptr_t) const { return res_ == nullptr; } bool operator!=(std::nullptr_t) const { return res_ != nullptr; } @@ -724,7 +745,7 @@ public: Error error() const { return err_; } private: - std::shared_ptr res_; + std::unique_ptr res_; Error err_; }; @@ -950,7 +971,7 @@ private: bool handle_request(Stream &strm, const Request &req, Response &res, bool close_connection); void stop_core(); - std::shared_ptr send_with_content_provider( + std::unique_ptr send_with_content_provider( const char *method, const char *path, const Headers &headers, const std::string &body, size_t content_length, ContentProvider content_provider, const char *content_type); @@ -1108,7 +1129,7 @@ public: #endif private: - std::shared_ptr cli_; + std::unique_ptr cli_; #ifdef CPPHTTPLIB_OPENSSL_SUPPORT bool is_ssl_ = false; @@ -2584,19 +2605,19 @@ bool prepare_content_receiver(T &x, int &status, ContentReceiver receiver, bool decompress, U callback) { if (decompress) { std::string encoding = x.get_header_value("Content-Encoding"); - std::shared_ptr decompressor; + std::unique_ptr decompressor; if (encoding.find("gzip") != std::string::npos || encoding.find("deflate") != std::string::npos) { #ifdef CPPHTTPLIB_ZLIB_SUPPORT - decompressor = std::make_shared(); + decompressor = detail::make_unique(); #else status = 415; return false; #endif } else if (encoding.find("br") != std::string::npos) { #ifdef CPPHTTPLIB_BROTLI_SUPPORT - decompressor = std::make_shared(); + decompressor = detail::make_unique(); #else status = 415; return false; @@ -4066,16 +4087,16 @@ inline bool Server::write_response(Stream &strm, bool close_connection, } if (type != detail::EncodingType::None) { - std::shared_ptr compressor; + std::unique_ptr compressor; if (type == detail::EncodingType::Gzip) { #ifdef CPPHTTPLIB_ZLIB_SUPPORT - compressor = std::make_shared(); + compressor = detail::make_unique(); res.set_header("Content-Encoding", "gzip"); #endif } else if (type == detail::EncodingType::Brotli) { #ifdef CPPHTTPLIB_BROTLI_SUPPORT - compressor = std::make_shared(); + compressor = detail::make_unique(); res.set_header("Content-Encoding", "brotli"); #endif } @@ -4157,17 +4178,17 @@ Server::write_content_with_provider(Stream &strm, const Request &req, if (res.is_chunked_content_provider) { auto type = detail::encoding_type(req, res); - std::shared_ptr compressor; + std::unique_ptr compressor; if (type == detail::EncodingType::Gzip) { #ifdef CPPHTTPLIB_ZLIB_SUPPORT - compressor = std::make_shared(); + compressor = detail::make_unique(); #endif } else if (type == detail::EncodingType::Brotli) { #ifdef CPPHTTPLIB_BROTLI_SUPPORT - compressor = std::make_shared(); + compressor = detail::make_unique(); #endif } else { - compressor = std::make_shared(); + compressor = detail::make_unique(); } assert(compressor != nullptr); @@ -5001,7 +5022,7 @@ inline bool ClientImpl::write_request(Stream &strm, const Request &req, return true; } -inline std::shared_ptr ClientImpl::send_with_content_provider( +inline std::unique_ptr ClientImpl::send_with_content_provider( const char *method, const char *path, const Headers &headers, const std::string &body, size_t content_length, ContentProvider content_provider, const char *content_type) { @@ -5070,9 +5091,9 @@ inline std::shared_ptr ClientImpl::send_with_content_provider( } } - auto res = std::make_shared(); + auto res = detail::make_unique(); - return send(req, *res) ? res : nullptr; + return send(req, *res) ? std::move(res) : nullptr; } inline bool ClientImpl::process_request(Stream &strm, const Request &req, @@ -5168,9 +5189,9 @@ inline Result ClientImpl::Get(const char *path, const Headers &headers, req.headers.insert(headers.begin(), headers.end()); req.progress = std::move(progress); - auto res = std::make_shared(); + auto res = detail::make_unique(); auto ret = send(req, *res); - return Result{ret ? res : nullptr, get_last_error()}; + return Result{ret ? std::move(res) : nullptr, get_last_error()}; } inline Result ClientImpl::Get(const char *path, @@ -5232,9 +5253,9 @@ inline Result ClientImpl::Get(const char *path, const Headers &headers, req.content_receiver = std::move(content_receiver); req.progress = std::move(progress); - auto res = std::make_shared(); + auto res = detail::make_unique(); auto ret = send(req, *res); - return Result{ret ? res : nullptr, get_last_error()}; + return Result{ret ? std::move(res) : nullptr, get_last_error()}; } inline Result ClientImpl::Head(const char *path) { @@ -5248,9 +5269,9 @@ inline Result ClientImpl::Head(const char *path, const Headers &headers) { req.headers.insert(headers.begin(), headers.end()); req.path = path; - auto res = std::make_shared(); + auto res = detail::make_unique(); auto ret = send(req, *res); - return Result{ret ? res : nullptr, get_last_error()}; + return Result{ret ? std::move(res) : nullptr, get_last_error()}; } inline Result ClientImpl::Post(const char *path) { @@ -5267,7 +5288,7 @@ inline Result ClientImpl::Post(const char *path, const Headers &headers, const char *content_type) { auto ret = send_with_content_provider("POST", path, headers, body, 0, nullptr, content_type); - return Result{ret, get_last_error()}; + return Result{std::move(ret), get_last_error()}; } inline Result ClientImpl::Post(const char *path, const Params ¶ms) { @@ -5289,7 +5310,7 @@ inline Result ClientImpl::Post(const char *path, const Headers &headers, content_length, std::move(content_provider), content_type); - return Result{ret, get_last_error()}; + return Result{std::move(ret), get_last_error()}; } inline Result ClientImpl::Post(const char *path, const Headers &headers, @@ -5354,7 +5375,7 @@ inline Result ClientImpl::Put(const char *path, const Headers &headers, const char *content_type) { auto ret = send_with_content_provider("PUT", path, headers, body, 0, nullptr, content_type); - return Result{ret, get_last_error()}; + return Result{std::move(ret), get_last_error()}; } inline Result ClientImpl::Put(const char *path, size_t content_length, @@ -5372,7 +5393,7 @@ inline Result ClientImpl::Put(const char *path, const Headers &headers, content_length, std::move(content_provider), content_type); - return Result{ret, get_last_error()}; + return Result{std::move(ret), get_last_error()}; } inline Result ClientImpl::Put(const char *path, const Params ¶ms) { @@ -5395,7 +5416,7 @@ inline Result ClientImpl::Patch(const char *path, const Headers &headers, const char *content_type) { auto ret = send_with_content_provider("PATCH", path, headers, body, 0, nullptr, content_type); - return Result{ret, get_last_error()}; + return Result{std::move(ret), get_last_error()}; } inline Result ClientImpl::Patch(const char *path, size_t content_length, @@ -5413,7 +5434,7 @@ inline Result ClientImpl::Patch(const char *path, const Headers &headers, content_length, std::move(content_provider), content_type); - return Result{ret, get_last_error()}; + return Result{std::move(ret), get_last_error()}; } inline Result ClientImpl::Delete(const char *path) { @@ -5441,9 +5462,9 @@ inline Result ClientImpl::Delete(const char *path, const Headers &headers, if (content_type) { req.headers.emplace("Content-Type", content_type); } req.body = body; - auto res = std::make_shared(); + auto res = detail::make_unique(); auto ret = send(req, *res); - return Result{ret ? res : nullptr, get_last_error()}; + return Result{ret ? std::move(res) : nullptr, get_last_error()}; } inline Result ClientImpl::Options(const char *path) { @@ -5457,9 +5478,9 @@ inline Result ClientImpl::Options(const char *path, const Headers &headers) { req.headers.insert(headers.begin(), headers.end()); req.path = path; - auto res = std::make_shared(); + auto res = detail::make_unique(); auto ret = send(req, *res); - return Result{ret ? res : nullptr, get_last_error()}; + return Result{ret ? std::move(res) : nullptr, get_last_error()}; } inline size_t ClientImpl::is_socket_open() const { @@ -6234,28 +6255,28 @@ inline Client::Client(const char *scheme_host_port, if (is_ssl) { #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - cli_ = std::make_shared(host.c_str(), port, client_cert_path, - client_key_path); + cli_ = detail::make_unique(host.c_str(), port, + client_cert_path, client_key_path); is_ssl_ = is_ssl; #endif } else { - cli_ = std::make_shared(host.c_str(), port, client_cert_path, - client_key_path); + cli_ = detail::make_unique(host.c_str(), port, + client_cert_path, client_key_path); } } else { - cli_ = std::make_shared(scheme_host_port, 80, client_cert_path, - client_key_path); + cli_ = detail::make_unique(scheme_host_port, 80, + client_cert_path, client_key_path); } } inline Client::Client(const std::string &host, int port) - : cli_(std::make_shared(host, port)) {} + : cli_(detail::make_unique(host, port)) {} inline Client::Client(const std::string &host, int port, const std::string &client_cert_path, const std::string &client_key_path) - : cli_(std::make_shared(host, port, client_cert_path, - client_key_path)) {} + : cli_(detail::make_unique(host, port, client_cert_path, + client_key_path)) {} inline Client::~Client() {}