Browse Source

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 <[email protected]>
Snape3058 5 years ago
parent
commit
cc5147ad72
1 changed files with 64 additions and 43 deletions
  1. 64 43
      httplib.h

+ 64 - 43
httplib.h

@@ -237,6 +237,27 @@ namespace httplib {
 
 
 namespace detail {
 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 <class T, class... Args>
+typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
+make_unique(Args &&... args) {
+  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+}
+
+template <class T>
+typename std::enable_if<std::is_array<T>::value, std::unique_ptr<T>>::type
+make_unique(std::size_t n) {
+  typedef typename std::remove_extent<T>::type RT;
+  return std::unique_ptr<T>(new RT[n]);
+}
+
 struct ci {
 struct ci {
   bool operator()(const std::string &s1, const std::string &s2) const {
   bool operator()(const std::string &s1, const std::string &s2) const {
     return std::lexicographical_compare(
     return std::lexicographical_compare(
@@ -713,8 +734,8 @@ enum Error {
 
 
 class Result {
 class Result {
 public:
 public:
-  Result(const std::shared_ptr<Response> &res, Error err)
-      : res_(res), err_(err) {}
+  Result(std::unique_ptr<Response> res, Error err)
+      : res_(std::move(res)), err_(err) {}
   operator bool() const { return res_ != nullptr; }
   operator bool() const { return res_ != nullptr; }
   bool operator==(std::nullptr_t) const { return res_ == nullptr; }
   bool operator==(std::nullptr_t) 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_; }
   Error error() const { return err_; }
 
 
 private:
 private:
-  std::shared_ptr<Response> res_;
+  std::unique_ptr<Response> res_;
   Error err_;
   Error err_;
 };
 };
 
 
@@ -950,7 +971,7 @@ private:
   bool handle_request(Stream &strm, const Request &req, Response &res,
   bool handle_request(Stream &strm, const Request &req, Response &res,
                       bool close_connection);
                       bool close_connection);
   void stop_core();
   void stop_core();
-  std::shared_ptr<Response> send_with_content_provider(
+  std::unique_ptr<Response> send_with_content_provider(
       const char *method, const char *path, const Headers &headers,
       const char *method, const char *path, const Headers &headers,
       const std::string &body, size_t content_length,
       const std::string &body, size_t content_length,
       ContentProvider content_provider, const char *content_type);
       ContentProvider content_provider, const char *content_type);
@@ -1108,7 +1129,7 @@ public:
 #endif
 #endif
 
 
 private:
 private:
-  std::shared_ptr<ClientImpl> cli_;
+  std::unique_ptr<ClientImpl> cli_;
 
 
 #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
 #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
   bool is_ssl_ = false;
   bool is_ssl_ = false;
@@ -2584,19 +2605,19 @@ bool prepare_content_receiver(T &x, int &status, ContentReceiver receiver,
                               bool decompress, U callback) {
                               bool decompress, U callback) {
   if (decompress) {
   if (decompress) {
     std::string encoding = x.get_header_value("Content-Encoding");
     std::string encoding = x.get_header_value("Content-Encoding");
-    std::shared_ptr<decompressor> decompressor;
+    std::unique_ptr<decompressor> decompressor;
 
 
     if (encoding.find("gzip") != std::string::npos ||
     if (encoding.find("gzip") != std::string::npos ||
         encoding.find("deflate") != std::string::npos) {
         encoding.find("deflate") != std::string::npos) {
 #ifdef CPPHTTPLIB_ZLIB_SUPPORT
 #ifdef CPPHTTPLIB_ZLIB_SUPPORT
-      decompressor = std::make_shared<gzip_decompressor>();
+      decompressor = detail::make_unique<gzip_decompressor>();
 #else
 #else
       status = 415;
       status = 415;
       return false;
       return false;
 #endif
 #endif
     } else if (encoding.find("br") != std::string::npos) {
     } else if (encoding.find("br") != std::string::npos) {
 #ifdef CPPHTTPLIB_BROTLI_SUPPORT
 #ifdef CPPHTTPLIB_BROTLI_SUPPORT
-      decompressor = std::make_shared<brotli_decompressor>();
+      decompressor = detail::make_unique<brotli_decompressor>();
 #else
 #else
       status = 415;
       status = 415;
       return false;
       return false;
@@ -4066,16 +4087,16 @@ inline bool Server::write_response(Stream &strm, bool close_connection,
     }
     }
 
 
     if (type != detail::EncodingType::None) {
     if (type != detail::EncodingType::None) {
-      std::shared_ptr<detail::compressor> compressor;
+      std::unique_ptr<detail::compressor> compressor;
 
 
       if (type == detail::EncodingType::Gzip) {
       if (type == detail::EncodingType::Gzip) {
 #ifdef CPPHTTPLIB_ZLIB_SUPPORT
 #ifdef CPPHTTPLIB_ZLIB_SUPPORT
-        compressor = std::make_shared<detail::gzip_compressor>();
+        compressor = detail::make_unique<detail::gzip_compressor>();
         res.set_header("Content-Encoding", "gzip");
         res.set_header("Content-Encoding", "gzip");
 #endif
 #endif
       } else if (type == detail::EncodingType::Brotli) {
       } else if (type == detail::EncodingType::Brotli) {
 #ifdef CPPHTTPLIB_BROTLI_SUPPORT
 #ifdef CPPHTTPLIB_BROTLI_SUPPORT
-        compressor = std::make_shared<detail::brotli_compressor>();
+        compressor = detail::make_unique<detail::brotli_compressor>();
         res.set_header("Content-Encoding", "brotli");
         res.set_header("Content-Encoding", "brotli");
 #endif
 #endif
       }
       }
@@ -4157,17 +4178,17 @@ Server::write_content_with_provider(Stream &strm, const Request &req,
     if (res.is_chunked_content_provider) {
     if (res.is_chunked_content_provider) {
       auto type = detail::encoding_type(req, res);
       auto type = detail::encoding_type(req, res);
 
 
-      std::shared_ptr<detail::compressor> compressor;
+      std::unique_ptr<detail::compressor> compressor;
       if (type == detail::EncodingType::Gzip) {
       if (type == detail::EncodingType::Gzip) {
 #ifdef CPPHTTPLIB_ZLIB_SUPPORT
 #ifdef CPPHTTPLIB_ZLIB_SUPPORT
-        compressor = std::make_shared<detail::gzip_compressor>();
+        compressor = detail::make_unique<detail::gzip_compressor>();
 #endif
 #endif
       } else if (type == detail::EncodingType::Brotli) {
       } else if (type == detail::EncodingType::Brotli) {
 #ifdef CPPHTTPLIB_BROTLI_SUPPORT
 #ifdef CPPHTTPLIB_BROTLI_SUPPORT
-        compressor = std::make_shared<detail::brotli_compressor>();
+        compressor = detail::make_unique<detail::brotli_compressor>();
 #endif
 #endif
       } else {
       } else {
-        compressor = std::make_shared<detail::nocompressor>();
+        compressor = detail::make_unique<detail::nocompressor>();
       }
       }
       assert(compressor != nullptr);
       assert(compressor != nullptr);
 
 
@@ -5001,7 +5022,7 @@ inline bool ClientImpl::write_request(Stream &strm, const Request &req,
   return true;
   return true;
 }
 }
 
 
-inline std::shared_ptr<Response> ClientImpl::send_with_content_provider(
+inline std::unique_ptr<Response> ClientImpl::send_with_content_provider(
     const char *method, const char *path, const Headers &headers,
     const char *method, const char *path, const Headers &headers,
     const std::string &body, size_t content_length,
     const std::string &body, size_t content_length,
     ContentProvider content_provider, const char *content_type) {
     ContentProvider content_provider, const char *content_type) {
@@ -5070,9 +5091,9 @@ inline std::shared_ptr<Response> ClientImpl::send_with_content_provider(
     }
     }
   }
   }
 
 
-  auto res = std::make_shared<Response>();
+  auto res = detail::make_unique<Response>();
 
 
-  return send(req, *res) ? res : nullptr;
+  return send(req, *res) ? std::move(res) : nullptr;
 }
 }
 
 
 inline bool ClientImpl::process_request(Stream &strm, const Request &req,
 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.headers.insert(headers.begin(), headers.end());
   req.progress = std::move(progress);
   req.progress = std::move(progress);
 
 
-  auto res = std::make_shared<Response>();
+  auto res = detail::make_unique<Response>();
   auto ret = send(req, *res);
   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,
 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.content_receiver = std::move(content_receiver);
   req.progress = std::move(progress);
   req.progress = std::move(progress);
 
 
-  auto res = std::make_shared<Response>();
+  auto res = detail::make_unique<Response>();
   auto ret = send(req, *res);
   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) {
 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.headers.insert(headers.begin(), headers.end());
   req.path = path;
   req.path = path;
 
 
-  auto res = std::make_shared<Response>();
+  auto res = detail::make_unique<Response>();
   auto ret = send(req, *res);
   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) {
 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) {
                                const char *content_type) {
   auto ret = send_with_content_provider("POST", path, headers, body, 0, nullptr,
   auto ret = send_with_content_provider("POST", path, headers, body, 0, nullptr,
                                         content_type);
                                         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 &params) {
 inline Result ClientImpl::Post(const char *path, const Params &params) {
@@ -5289,7 +5310,7 @@ inline Result ClientImpl::Post(const char *path, const Headers &headers,
                                         content_length,
                                         content_length,
                                         std::move(content_provider),
                                         std::move(content_provider),
                                         content_type);
                                         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,
 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) {
                               const char *content_type) {
   auto ret = send_with_content_provider("PUT", path, headers, body, 0, nullptr,
   auto ret = send_with_content_provider("PUT", path, headers, body, 0, nullptr,
                                         content_type);
                                         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,
 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,
                                         content_length,
                                         std::move(content_provider),
                                         std::move(content_provider),
                                         content_type);
                                         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 &params) {
 inline Result ClientImpl::Put(const char *path, const Params &params) {
@@ -5395,7 +5416,7 @@ inline Result ClientImpl::Patch(const char *path, const Headers &headers,
                                 const char *content_type) {
                                 const char *content_type) {
   auto ret = send_with_content_provider("PATCH", path, headers, body, 0,
   auto ret = send_with_content_provider("PATCH", path, headers, body, 0,
                                         nullptr, content_type);
                                         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,
 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,
                                         content_length,
                                         std::move(content_provider),
                                         std::move(content_provider),
                                         content_type);
                                         content_type);
-  return Result{ret, get_last_error()};
+  return Result{std::move(ret), get_last_error()};
 }
 }
 
 
 inline Result ClientImpl::Delete(const char *path) {
 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); }
   if (content_type) { req.headers.emplace("Content-Type", content_type); }
   req.body = body;
   req.body = body;
 
 
-  auto res = std::make_shared<Response>();
+  auto res = detail::make_unique<Response>();
   auto ret = send(req, *res);
   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) {
 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.headers.insert(headers.begin(), headers.end());
   req.path = path;
   req.path = path;
 
 
-  auto res = std::make_shared<Response>();
+  auto res = detail::make_unique<Response>();
   auto ret = send(req, *res);
   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 {
 inline size_t ClientImpl::is_socket_open() const {
@@ -6234,28 +6255,28 @@ inline Client::Client(const char *scheme_host_port,
 
 
     if (is_ssl) {
     if (is_ssl) {
 #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
 #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
-      cli_ = std::make_shared<SSLClient>(host.c_str(), port, client_cert_path,
-                                         client_key_path);
+      cli_ = detail::make_unique<SSLClient>(host.c_str(), port,
+                                            client_cert_path, client_key_path);
       is_ssl_ = is_ssl;
       is_ssl_ = is_ssl;
 #endif
 #endif
     } else {
     } else {
-      cli_ = std::make_shared<ClientImpl>(host.c_str(), port, client_cert_path,
-                                          client_key_path);
+      cli_ = detail::make_unique<ClientImpl>(host.c_str(), port,
+                                             client_cert_path, client_key_path);
     }
     }
   } else {
   } else {
-    cli_ = std::make_shared<ClientImpl>(scheme_host_port, 80, client_cert_path,
-                                        client_key_path);
+    cli_ = detail::make_unique<ClientImpl>(scheme_host_port, 80,
+                                           client_cert_path, client_key_path);
   }
   }
 }
 }
 
 
 inline Client::Client(const std::string &host, int port)
 inline Client::Client(const std::string &host, int port)
-    : cli_(std::make_shared<ClientImpl>(host, port)) {}
+    : cli_(detail::make_unique<ClientImpl>(host, port)) {}
 
 
 inline Client::Client(const std::string &host, int port,
 inline Client::Client(const std::string &host, int port,
                       const std::string &client_cert_path,
                       const std::string &client_cert_path,
                       const std::string &client_key_path)
                       const std::string &client_key_path)
-    : cli_(std::make_shared<ClientImpl>(host, port, client_cert_path,
-                                        client_key_path)) {}
+    : cli_(detail::make_unique<ClientImpl>(host, port, client_cert_path,
+                                           client_key_path)) {}
 
 
 inline Client::~Client() {}
 inline Client::~Client() {}