Skip to content

Commit cc5147a

Browse files
authored
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]>
1 parent fffbf1a commit cc5147a

File tree

1 file changed

+64
-43
lines changed

1 file changed

+64
-43
lines changed

httplib.h

Lines changed: 64 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,27 @@ namespace httplib {
237237

238238
namespace detail {
239239

240+
/*
241+
* Backport std::make_unique from C++14.
242+
*
243+
* NOTE: This code came up with the following stackoverflow post:
244+
* https://stackoverflow.com/questions/10149840/c-arrays-and-make-unique
245+
*
246+
*/
247+
248+
template <class T, class... Args>
249+
typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
250+
make_unique(Args &&... args) {
251+
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
252+
}
253+
254+
template <class T>
255+
typename std::enable_if<std::is_array<T>::value, std::unique_ptr<T>>::type
256+
make_unique(std::size_t n) {
257+
typedef typename std::remove_extent<T>::type RT;
258+
return std::unique_ptr<T>(new RT[n]);
259+
}
260+
240261
struct ci {
241262
bool operator()(const std::string &s1, const std::string &s2) const {
242263
return std::lexicographical_compare(
@@ -713,8 +734,8 @@ enum Error {
713734

714735
class Result {
715736
public:
716-
Result(const std::shared_ptr<Response> &res, Error err)
717-
: res_(res), err_(err) {}
737+
Result(std::unique_ptr<Response> res, Error err)
738+
: res_(std::move(res)), err_(err) {}
718739
operator bool() const { return res_ != nullptr; }
719740
bool operator==(std::nullptr_t) const { return res_ == nullptr; }
720741
bool operator!=(std::nullptr_t) const { return res_ != nullptr; }
@@ -724,7 +745,7 @@ class Result {
724745
Error error() const { return err_; }
725746

726747
private:
727-
std::shared_ptr<Response> res_;
748+
std::unique_ptr<Response> res_;
728749
Error err_;
729750
};
730751

@@ -950,7 +971,7 @@ class ClientImpl {
950971
bool handle_request(Stream &strm, const Request &req, Response &res,
951972
bool close_connection);
952973
void stop_core();
953-
std::shared_ptr<Response> send_with_content_provider(
974+
std::unique_ptr<Response> send_with_content_provider(
954975
const char *method, const char *path, const Headers &headers,
955976
const std::string &body, size_t content_length,
956977
ContentProvider content_provider, const char *content_type);
@@ -1108,7 +1129,7 @@ class Client {
11081129
#endif
11091130

11101131
private:
1111-
std::shared_ptr<ClientImpl> cli_;
1132+
std::unique_ptr<ClientImpl> cli_;
11121133

11131134
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
11141135
bool is_ssl_ = false;
@@ -2584,19 +2605,19 @@ bool prepare_content_receiver(T &x, int &status, ContentReceiver receiver,
25842605
bool decompress, U callback) {
25852606
if (decompress) {
25862607
std::string encoding = x.get_header_value("Content-Encoding");
2587-
std::shared_ptr<decompressor> decompressor;
2608+
std::unique_ptr<decompressor> decompressor;
25882609

25892610
if (encoding.find("gzip") != std::string::npos ||
25902611
encoding.find("deflate") != std::string::npos) {
25912612
#ifdef CPPHTTPLIB_ZLIB_SUPPORT
2592-
decompressor = std::make_shared<gzip_decompressor>();
2613+
decompressor = detail::make_unique<gzip_decompressor>();
25932614
#else
25942615
status = 415;
25952616
return false;
25962617
#endif
25972618
} else if (encoding.find("br") != std::string::npos) {
25982619
#ifdef CPPHTTPLIB_BROTLI_SUPPORT
2599-
decompressor = std::make_shared<brotli_decompressor>();
2620+
decompressor = detail::make_unique<brotli_decompressor>();
26002621
#else
26012622
status = 415;
26022623
return false;
@@ -4066,16 +4087,16 @@ inline bool Server::write_response(Stream &strm, bool close_connection,
40664087
}
40674088

40684089
if (type != detail::EncodingType::None) {
4069-
std::shared_ptr<detail::compressor> compressor;
4090+
std::unique_ptr<detail::compressor> compressor;
40704091

40714092
if (type == detail::EncodingType::Gzip) {
40724093
#ifdef CPPHTTPLIB_ZLIB_SUPPORT
4073-
compressor = std::make_shared<detail::gzip_compressor>();
4094+
compressor = detail::make_unique<detail::gzip_compressor>();
40744095
res.set_header("Content-Encoding", "gzip");
40754096
#endif
40764097
} else if (type == detail::EncodingType::Brotli) {
40774098
#ifdef CPPHTTPLIB_BROTLI_SUPPORT
4078-
compressor = std::make_shared<detail::brotli_compressor>();
4099+
compressor = detail::make_unique<detail::brotli_compressor>();
40794100
res.set_header("Content-Encoding", "brotli");
40804101
#endif
40814102
}
@@ -4157,17 +4178,17 @@ Server::write_content_with_provider(Stream &strm, const Request &req,
41574178
if (res.is_chunked_content_provider) {
41584179
auto type = detail::encoding_type(req, res);
41594180

4160-
std::shared_ptr<detail::compressor> compressor;
4181+
std::unique_ptr<detail::compressor> compressor;
41614182
if (type == detail::EncodingType::Gzip) {
41624183
#ifdef CPPHTTPLIB_ZLIB_SUPPORT
4163-
compressor = std::make_shared<detail::gzip_compressor>();
4184+
compressor = detail::make_unique<detail::gzip_compressor>();
41644185
#endif
41654186
} else if (type == detail::EncodingType::Brotli) {
41664187
#ifdef CPPHTTPLIB_BROTLI_SUPPORT
4167-
compressor = std::make_shared<detail::brotli_compressor>();
4188+
compressor = detail::make_unique<detail::brotli_compressor>();
41684189
#endif
41694190
} else {
4170-
compressor = std::make_shared<detail::nocompressor>();
4191+
compressor = detail::make_unique<detail::nocompressor>();
41714192
}
41724193
assert(compressor != nullptr);
41734194

@@ -5001,7 +5022,7 @@ inline bool ClientImpl::write_request(Stream &strm, const Request &req,
50015022
return true;
50025023
}
50035024

5004-
inline std::shared_ptr<Response> ClientImpl::send_with_content_provider(
5025+
inline std::unique_ptr<Response> ClientImpl::send_with_content_provider(
50055026
const char *method, const char *path, const Headers &headers,
50065027
const std::string &body, size_t content_length,
50075028
ContentProvider content_provider, const char *content_type) {
@@ -5070,9 +5091,9 @@ inline std::shared_ptr<Response> ClientImpl::send_with_content_provider(
50705091
}
50715092
}
50725093

5073-
auto res = std::make_shared<Response>();
5094+
auto res = detail::make_unique<Response>();
50745095

5075-
return send(req, *res) ? res : nullptr;
5096+
return send(req, *res) ? std::move(res) : nullptr;
50765097
}
50775098

50785099
inline bool ClientImpl::process_request(Stream &strm, const Request &req,
@@ -5168,9 +5189,9 @@ inline Result ClientImpl::Get(const char *path, const Headers &headers,
51685189
req.headers.insert(headers.begin(), headers.end());
51695190
req.progress = std::move(progress);
51705191

5171-
auto res = std::make_shared<Response>();
5192+
auto res = detail::make_unique<Response>();
51725193
auto ret = send(req, *res);
5173-
return Result{ret ? res : nullptr, get_last_error()};
5194+
return Result{ret ? std::move(res) : nullptr, get_last_error()};
51745195
}
51755196

51765197
inline Result ClientImpl::Get(const char *path,
@@ -5232,9 +5253,9 @@ inline Result ClientImpl::Get(const char *path, const Headers &headers,
52325253
req.content_receiver = std::move(content_receiver);
52335254
req.progress = std::move(progress);
52345255

5235-
auto res = std::make_shared<Response>();
5256+
auto res = detail::make_unique<Response>();
52365257
auto ret = send(req, *res);
5237-
return Result{ret ? res : nullptr, get_last_error()};
5258+
return Result{ret ? std::move(res) : nullptr, get_last_error()};
52385259
}
52395260

52405261
inline Result ClientImpl::Head(const char *path) {
@@ -5248,9 +5269,9 @@ inline Result ClientImpl::Head(const char *path, const Headers &headers) {
52485269
req.headers.insert(headers.begin(), headers.end());
52495270
req.path = path;
52505271

5251-
auto res = std::make_shared<Response>();
5272+
auto res = detail::make_unique<Response>();
52525273
auto ret = send(req, *res);
5253-
return Result{ret ? res : nullptr, get_last_error()};
5274+
return Result{ret ? std::move(res) : nullptr, get_last_error()};
52545275
}
52555276

52565277
inline Result ClientImpl::Post(const char *path) {
@@ -5267,7 +5288,7 @@ inline Result ClientImpl::Post(const char *path, const Headers &headers,
52675288
const char *content_type) {
52685289
auto ret = send_with_content_provider("POST", path, headers, body, 0, nullptr,
52695290
content_type);
5270-
return Result{ret, get_last_error()};
5291+
return Result{std::move(ret), get_last_error()};
52715292
}
52725293

52735294
inline Result ClientImpl::Post(const char *path, const Params &params) {
@@ -5289,7 +5310,7 @@ inline Result ClientImpl::Post(const char *path, const Headers &headers,
52895310
content_length,
52905311
std::move(content_provider),
52915312
content_type);
5292-
return Result{ret, get_last_error()};
5313+
return Result{std::move(ret), get_last_error()};
52935314
}
52945315

52955316
inline Result ClientImpl::Post(const char *path, const Headers &headers,
@@ -5354,7 +5375,7 @@ inline Result ClientImpl::Put(const char *path, const Headers &headers,
53545375
const char *content_type) {
53555376
auto ret = send_with_content_provider("PUT", path, headers, body, 0, nullptr,
53565377
content_type);
5357-
return Result{ret, get_last_error()};
5378+
return Result{std::move(ret), get_last_error()};
53585379
}
53595380

53605381
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,
53725393
content_length,
53735394
std::move(content_provider),
53745395
content_type);
5375-
return Result{ret, get_last_error()};
5396+
return Result{std::move(ret), get_last_error()};
53765397
}
53775398

53785399
inline Result ClientImpl::Put(const char *path, const Params &params) {
@@ -5395,7 +5416,7 @@ inline Result ClientImpl::Patch(const char *path, const Headers &headers,
53955416
const char *content_type) {
53965417
auto ret = send_with_content_provider("PATCH", path, headers, body, 0,
53975418
nullptr, content_type);
5398-
return Result{ret, get_last_error()};
5419+
return Result{std::move(ret), get_last_error()};
53995420
}
54005421

54015422
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,
54135434
content_length,
54145435
std::move(content_provider),
54155436
content_type);
5416-
return Result{ret, get_last_error()};
5437+
return Result{std::move(ret), get_last_error()};
54175438
}
54185439

54195440
inline Result ClientImpl::Delete(const char *path) {
@@ -5441,9 +5462,9 @@ inline Result ClientImpl::Delete(const char *path, const Headers &headers,
54415462
if (content_type) { req.headers.emplace("Content-Type", content_type); }
54425463
req.body = body;
54435464

5444-
auto res = std::make_shared<Response>();
5465+
auto res = detail::make_unique<Response>();
54455466
auto ret = send(req, *res);
5446-
return Result{ret ? res : nullptr, get_last_error()};
5467+
return Result{ret ? std::move(res) : nullptr, get_last_error()};
54475468
}
54485469

54495470
inline Result ClientImpl::Options(const char *path) {
@@ -5457,9 +5478,9 @@ inline Result ClientImpl::Options(const char *path, const Headers &headers) {
54575478
req.headers.insert(headers.begin(), headers.end());
54585479
req.path = path;
54595480

5460-
auto res = std::make_shared<Response>();
5481+
auto res = detail::make_unique<Response>();
54615482
auto ret = send(req, *res);
5462-
return Result{ret ? res : nullptr, get_last_error()};
5483+
return Result{ret ? std::move(res) : nullptr, get_last_error()};
54635484
}
54645485

54655486
inline size_t ClientImpl::is_socket_open() const {
@@ -6234,28 +6255,28 @@ inline Client::Client(const char *scheme_host_port,
62346255

62356256
if (is_ssl) {
62366257
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
6237-
cli_ = std::make_shared<SSLClient>(host.c_str(), port, client_cert_path,
6238-
client_key_path);
6258+
cli_ = detail::make_unique<SSLClient>(host.c_str(), port,
6259+
client_cert_path, client_key_path);
62396260
is_ssl_ = is_ssl;
62406261
#endif
62416262
} else {
6242-
cli_ = std::make_shared<ClientImpl>(host.c_str(), port, client_cert_path,
6243-
client_key_path);
6263+
cli_ = detail::make_unique<ClientImpl>(host.c_str(), port,
6264+
client_cert_path, client_key_path);
62446265
}
62456266
} else {
6246-
cli_ = std::make_shared<ClientImpl>(scheme_host_port, 80, client_cert_path,
6247-
client_key_path);
6267+
cli_ = detail::make_unique<ClientImpl>(scheme_host_port, 80,
6268+
client_cert_path, client_key_path);
62486269
}
62496270
}
62506271

62516272
inline Client::Client(const std::string &host, int port)
6252-
: cli_(std::make_shared<ClientImpl>(host, port)) {}
6273+
: cli_(detail::make_unique<ClientImpl>(host, port)) {}
62536274

62546275
inline Client::Client(const std::string &host, int port,
62556276
const std::string &client_cert_path,
62566277
const std::string &client_key_path)
6257-
: cli_(std::make_shared<ClientImpl>(host, port, client_cert_path,
6258-
client_key_path)) {}
6278+
: cli_(detail::make_unique<ClientImpl>(host, port, client_cert_path,
6279+
client_key_path)) {}
62596280

62606281
inline Client::~Client() {}
62616282

0 commit comments

Comments
 (0)