From 154dec3182a6cfa3f9d07fa8389285e8a62cc139 Mon Sep 17 00:00:00 2001 From: George Sedov Date: Tue, 6 Aug 2024 18:35:27 +0200 Subject: [PATCH 1/5] Make hinnant-date optional for C++20 It was standardized in C++20 and thus not needed. Also it causes compilation issues with newer stdlib. --- include/pistache/date_wrapper.h | 30 ++++++++++++++++++++ include/pistache/meson.build | 1 + meson.build | 49 ++++++++++++++++++++++----------- src/common/http_defs.cc | 2 +- tests/cookie_test.cc | 2 +- tests/cookie_test_2.cc | 2 +- tests/headers_test.cc | 2 +- version.txt | 2 +- 8 files changed, 69 insertions(+), 21 deletions(-) create mode 100644 include/pistache/date_wrapper.h diff --git a/include/pistache/date_wrapper.h b/include/pistache/date_wrapper.h new file mode 100644 index 000000000..943e3f94b --- /dev/null +++ b/include/pistache/date_wrapper.h @@ -0,0 +1,30 @@ +/* + * SPDX-FileCopyrightText: 2024 George Sedov + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#if __cplusplus >= 202002L +#include +#include +namespace date +{ + using namespace std::chrono; + + /** + * special case for the to_stream function, which was not introduced + * in the standard, as the functionality was already a part of std::format + */ + template + std::basic_ostream& + to_stream(std::basic_ostream& os, const std::format_string& fmt, Args&&... args) + { + os << std::format(fmt, std::forward(args)...); + return os; + } +} +#else +#include +#endif \ No newline at end of file diff --git a/include/pistache/meson.build b/include/pistache/meson.build index deacccf80..e4a2f5078 100644 --- a/include/pistache/meson.build +++ b/include/pistache/meson.build @@ -11,6 +11,7 @@ install_headers( 'common.h', 'config.h', 'cookie.h', + 'date_wrapper.h', 'description.h', 'endpoint.h', 'eventmeth.h', diff --git a/meson.build b/meson.build index c03092820..55b1b03a3 100644 --- a/meson.build +++ b/meson.build @@ -36,25 +36,42 @@ if get_option('b_coverage') add_project_arguments(compiler.get_supported_arguments(['-fstack-protector-all', '--param=ssp-buffer-size=4']), language: 'cpp') endif -# howardhinnant/date has several names - look for them, from the most -# to the least explicit name. -# In Meson 0.60.0, this can be replaced with a simpler: -# -# dependency('howardhinnant-date', 'hinnant-date', 'date') -# -date_dep = dependency('howardhinnant-date', required: false) -if not date_dep.found() - date_dep = dependency('hinnant-date', required: false) -endif -if not date_dep.found() - date_dep = dependency('date', fallback: ['hinnant-date', 'date_dep']) -endif - deps_libpistache = [ - dependency('threads'), - date_dep + dependency('threads') ] +#Check if compiler supports C++20 date + +cxx_chrono_date_check_code = ''' +#include +#include +int main() { + std::stringstream ss; + ss << std::format("%FT%T%z", std::chrono::system_clock::now()); + std::chrono::system_clock::time_point tp; + ss >> std::chrono::parse("%FT%T%z", tp); + return 0; +} +''' +has_working_cxx_chrono_date = compiler.links(cxx_chrono_date_check_code, name: 'C++20 std::chrono') + +if (not has_working_cxx_chrono_date) + # howardhinnant/date has several names - look for them, from the most + # to the least explicit name. + # In Meson 0.60.0, this can be replaced with a simpler: + # + # dependency('howardhinnant-date', 'hinnant-date', 'date') + # + date_dep = dependency('howardhinnant-date', required: false) + if not date_dep.found() + date_dep = dependency('hinnant-date', required: false) + endif + if not date_dep.found() + date_dep = dependency('date', fallback: ['hinnant-date', 'date_dep']) + endif + deps_libpistache += date_dep +endif + if get_option('PISTACHE_USE_RAPIDJSON') rapidjson_dep = dependency('RapidJSON', fallback: ['rapidjson', 'rapidjson_dep']) deps_libpistache += rapidjson_dep diff --git a/src/common/http_defs.cc b/src/common/http_defs.cc index e12967566..bc036f6d3 100644 --- a/src/common/http_defs.cc +++ b/src/common/http_defs.cc @@ -18,7 +18,7 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wconversion" #endif -#include +#include #ifdef __GNUC__ #pragma GCC diagnostic pop #endif diff --git a/tests/cookie_test.cc b/tests/cookie_test.cc index e3b72d90c..5b17169a8 100644 --- a/tests/cookie_test.cc +++ b/tests/cookie_test.cc @@ -6,7 +6,7 @@ #include -#include +#include #include using namespace Pistache; diff --git a/tests/cookie_test_2.cc b/tests/cookie_test_2.cc index 7cdfe37d1..2fc405aba 100644 --- a/tests/cookie_test_2.cc +++ b/tests/cookie_test_2.cc @@ -6,7 +6,7 @@ #include -#include +#include #include using namespace Pistache; diff --git a/tests/headers_test.cc b/tests/headers_test.cc index 617c167c3..0ae2230df 100644 --- a/tests/headers_test.cc +++ b/tests/headers_test.cc @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include #include diff --git a/version.txt b/version.txt index f9e52323c..8a58d9eb3 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -0.3.1.20240626 +0.3.1.20240806 From 7a6abaf888275abcd9abca96a089a32b06b481bd Mon Sep 17 00:00:00 2001 From: George Sedov Date: Tue, 6 Aug 2024 18:41:12 +0200 Subject: [PATCH 2/5] Don't use implicit lambda capture of 'this' This behaviour is deprecated since C++20 --- examples/http_server.cc | 2 +- include/pistache/async.h | 2 +- include/pistache/http.h | 6 +++--- include/pistache/transport.h | 4 ++-- src/client/client.cc | 12 ++++++------ src/common/description.cc | 4 ++-- src/common/http.cc | 4 ++-- src/common/reactor.cc | 2 +- src/server/endpoint.cc | 2 +- src/server/listener.cc | 2 +- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/examples/http_server.cc b/examples/http_server.cc index 837988d05..0d8fd83f3 100644 --- a/examples/http_server.cc +++ b/examples/http_server.cc @@ -177,7 +177,7 @@ class MyHandler : public Http::Handler { response .send(Http::Code::Request_Timeout, "Timeout") - .then([=](ssize_t) {}, PrintException()); + .then([](ssize_t) {}, PrintException()); } }; diff --git a/include/pistache/async.h b/include/pistache/async.h index 392375515..5cda4a988 100644 --- a/include/pistache/async.h +++ b/include/pistache/async.h @@ -731,7 +731,7 @@ namespace Pistache::Async void finishResolve(P& promise) { auto chainer = makeChainer(promise); - promise.then(std::move(chainer), [=](std::exception_ptr exc) { + promise.then(std::move(chainer), [this](std::exception_ptr exc) { auto core = this->chain_; core->exc = std::move(exc); core->state = State::Rejected; diff --git a/include/pistache/http.h b/include/pistache/http.h index 4fd8d3169..2b38fa28b 100644 --- a/include/pistache/http.h +++ b/include/pistache/http.h @@ -298,7 +298,7 @@ namespace Pistache template void arm(Duration duration) { - Async::Promise p([=](Async::Deferred deferred) { + Async::Promise p([duration, this](Async::Deferred deferred) { #ifdef _USE_LIBEVENT std::shared_ptr event_meth_epoll_equiv( @@ -318,13 +318,13 @@ namespace Pistache }); p.then( - [=](uint64_t numWakeup) { + [this](uint64_t numWakeup) { this->armed = false; this->onTimeout(numWakeup); CLOSE_FD(timerFd); timerFd = PS_FD_EMPTY; }, - [=](std::exception_ptr exc) { std::rethrow_exception(exc); }); + [](std::exception_ptr exc) { std::rethrow_exception(exc); }); armed = true; } diff --git a/include/pistache/transport.h b/include/pistache/transport.h index 887ae970b..15b9df7a2 100644 --- a/include/pistache/transport.h +++ b/include/pistache/transport.h @@ -62,7 +62,7 @@ namespace Pistache::Tcp // Always enqueue reponses for sending. Giving preference to consumer // context means chunked responses could be sent out of order. return Async::Promise( - [=](Async::Deferred deferred) mutable { + [fd, buffer, flags, this](Async::Deferred deferred) mutable { BufferHolder holder { buffer }; WriteEntry write(std::move(deferred), std::move(holder), fd, flags @@ -77,7 +77,7 @@ namespace Pistache::Tcp Async::Promise load() { - return Async::Promise([=](Async::Deferred deferred) { + return Async::Promise([this](Async::Deferred deferred) { PS_TIMEDBG_START_CURLY; loadRequest_ = std::move(deferred); diff --git a/src/client/client.cc b/src/client/client.cc index 928d0ac1b..93daca3c9 100644 --- a/src/client/client.cc +++ b/src/client/client.cc @@ -186,7 +186,7 @@ namespace Pistache::Http::Experimental void registerPoller(Polling::Epoll& poller) override; void unregisterPoller(Polling::Epoll& poller) override; - Async::Promise asyncConnect(std::shared_ptr connection, + Async::Promise asyncConnect(const std::shared_ptr& connection, const struct sockaddr* address, socklen_t addr_len); @@ -349,13 +349,13 @@ namespace Pistache::Http::Experimental } Async::Promise - Transport::asyncConnect(std::shared_ptr connection, + Transport::asyncConnect(const std::shared_ptr& connection, const struct sockaddr* address, socklen_t addr_len) { PS_TIMEDBG_START_THIS; return Async::Promise( - [=](Async::Resolver& resolve, Async::Rejection& reject) { + [connection, address, addr_len, this](Async::Resolver& resolve, Async::Rejection& reject) { PS_TIMEDBG_START; ConnectionEntry entry(std::move(resolve), std::move(reject), connection, @@ -728,7 +728,7 @@ namespace Pistache::Http::Experimental transport_ ->asyncConnect(shared_from_this(), addr->ai_addr, addr->ai_addrlen) .then( - [=]() { + [sfd, this]() { socklen_t len = sizeof(saddr); getsockname(sfd, reinterpret_cast(&saddr), &len); connectionState_.store(Connected); @@ -931,7 +931,7 @@ namespace Pistache::Http::Experimental PS_TIMEDBG_START_THIS; return Async::Promise( - [=](Async::Resolver& resolve, Async::Rejection& reject) { + [&, this](Async::Resolver& resolve, Async::Rejection& reject) { PS_TIMEDBG_START; performImpl(request, std::move(resolve), std::move(reject), std::move(onDone)); @@ -944,7 +944,7 @@ namespace Pistache::Http::Experimental PS_TIMEDBG_START_THIS; return Async::Promise( - [=](Async::Resolver& resolve, Async::Rejection& reject) { + [&, this](Async::Resolver& resolve, Async::Rejection& reject) { PS_TIMEDBG_START; requestsQueue.push(RequestData(std::move(resolve), std::move(reject), diff --git a/src/common/description.cc b/src/common/description.cc index 178eda95f..584c334e7 100644 --- a/src/common/description.cc +++ b/src/common/description.cc @@ -408,7 +408,7 @@ namespace Pistache::Rest void Swagger::install(Rest::Router& router) { - Route::Handler uiHandler = [=](const Rest::Request& req, + Route::Handler uiHandler = [this](const Rest::Request& req, Http::ResponseWriter response) { const auto& res = req.resource(); @@ -529,7 +529,7 @@ namespace Pistache::Rest return Route::Result::Failure; }; - router.addCustomHandler(uiHandler); + router.addCustomHandler(std::move(uiHandler)); } } // namespace Pistache::Rest diff --git a/src/common/http.cc b/src/common/http.cc index dbafafe25..44d78c471 100644 --- a/src/common/http.cc +++ b/src/common/http.cc @@ -1055,11 +1055,11 @@ namespace Pistache::Http return transport_->asyncWrite(fd, buffer) .then(ssize_t)>, std::function>( - [=](ssize_t data) { + [](ssize_t data) { return Async::Promise::resolved(data); }, - [=](std::exception_ptr& eptr) { + [](std::exception_ptr& eptr) { return Async::Promise::rejected(eptr); }); } diff --git a/src/common/reactor.cc b/src/common/reactor.cc index dff153fa9..1d01524a5 100644 --- a/src/common/reactor.cc +++ b/src/common/reactor.cc @@ -622,7 +622,7 @@ namespace Pistache::Aio void run() { - thread = std::thread([=]() { + thread = std::thread([this]() { if (!threadsName_.empty()) { pthread_setname_np( diff --git a/src/server/endpoint.cc b/src/server/endpoint.cc index 3faade7ed..6dd0f219b 100644 --- a/src/server/endpoint.cc +++ b/src/server/endpoint.cc @@ -235,7 +235,7 @@ namespace Pistache::Http else { ResponseWriter response(Http::Version::Http11, this, static_cast(handler_.get()), peer); - response.send(Http::Code::Request_Timeout).then([=](ssize_t) { removePeer(peer); }, [=](std::exception_ptr) { removePeer(peer); }); + response.send(Http::Code::Request_Timeout).then([peer, this](ssize_t) { removePeer(peer); }, [peer, this](std::exception_ptr) { removePeer(peer); }); } } diff --git a/src/server/listener.cc b/src/server/listener.cc index 3e0a06dcc..924f26503 100644 --- a/src/server/listener.cc +++ b/src/server/listener.cc @@ -559,7 +559,7 @@ namespace Pistache::Tcp void Listener::runThreaded() { shutdownFd.bind(poller); - acceptThread = std::thread([=]() { this->run(); }); + acceptThread = std::thread([this]() { this->run(); }); } void Listener::shutdown() From 364c7221fdecb6cd56728cdadf1d2577ef7db19f Mon Sep 17 00:00:00 2001 From: George Sedov Date: Tue, 6 Aug 2024 19:31:33 +0200 Subject: [PATCH 3/5] fix the sneaky variable hidden behind ifdefs Capture by-reference is probably what was intended from the start, seeing how the buffer is passed. --- include/pistache/transport.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pistache/transport.h b/include/pistache/transport.h index 15b9df7a2..e1c5e989a 100644 --- a/include/pistache/transport.h +++ b/include/pistache/transport.h @@ -62,7 +62,7 @@ namespace Pistache::Tcp // Always enqueue reponses for sending. Giving preference to consumer // context means chunked responses could be sent out of order. return Async::Promise( - [fd, buffer, flags, this](Async::Deferred deferred) mutable { + [&, this](Async::Deferred deferred) mutable { BufferHolder holder { buffer }; WriteEntry write(std::move(deferred), std::move(holder), fd, flags From db8d71f9d6867d90733dd2562c439f8bf153e41b Mon Sep 17 00:00:00 2001 From: George Sedov Date: Wed, 7 Aug 2024 11:07:02 +0200 Subject: [PATCH 4/5] Revert the unneeded signature change --- src/client/client.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/client.cc b/src/client/client.cc index 93daca3c9..c7d141eaa 100644 --- a/src/client/client.cc +++ b/src/client/client.cc @@ -186,7 +186,7 @@ namespace Pistache::Http::Experimental void registerPoller(Polling::Epoll& poller) override; void unregisterPoller(Polling::Epoll& poller) override; - Async::Promise asyncConnect(const std::shared_ptr& connection, + Async::Promise asyncConnect(std::shared_ptr connection, const struct sockaddr* address, socklen_t addr_len); @@ -349,7 +349,7 @@ namespace Pistache::Http::Experimental } Async::Promise - Transport::asyncConnect(const std::shared_ptr& connection, + Transport::asyncConnect(std::shared_ptr connection, const struct sockaddr* address, socklen_t addr_len) { PS_TIMEDBG_START_THIS; From 818f8ad547e7c3dfbc706cdfc7b4c1170995b9ad Mon Sep 17 00:00:00 2001 From: George Sedov Date: Wed, 4 Dec 2024 16:33:09 +0100 Subject: [PATCH 5/5] test for specific C++20 features --- include/pistache/date_wrapper.h | 2 +- meson.build | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/include/pistache/date_wrapper.h b/include/pistache/date_wrapper.h index 943e3f94b..7a854bdac 100644 --- a/include/pistache/date_wrapper.h +++ b/include/pistache/date_wrapper.h @@ -6,7 +6,7 @@ #pragma once -#if __cplusplus >= 202002L +#if PISTACHE_USE_STD_CHRONO #include #include namespace date diff --git a/meson.build b/meson.build index 9665e2dea..9fb540c3b 100644 --- a/meson.build +++ b/meson.build @@ -44,17 +44,16 @@ public_deps = [] #Check if compiler supports C++20 date cxx_chrono_date_check_code = ''' -#include #include -int main() { - std::stringstream ss; - ss << std::format("%FT%T%z", std::chrono::system_clock::now()); - std::chrono::system_clock::time_point tp; - ss >> std::chrono::parse("%FT%T%z", tp); - return 0; -} +#include +#if defined(__cpp_lib_format) && (__cpp_lib_format >= 201907L) && \ + defined(__cpp_lib_chrono) && (__cpp_lib_chrono >= 201907L) +// OK +#else +#error "no" +#endif ''' -has_working_cxx_chrono_date = compiler.links(cxx_chrono_date_check_code, name: 'C++20 std::chrono') +has_working_cxx_chrono_date = compiler.compiles(cxx_chrono_date_check_code, name: 'C++20 std::chrono') if (not has_working_cxx_chrono_date) # howardhinnant/date has several names - look for them, from the most @@ -71,6 +70,8 @@ if (not has_working_cxx_chrono_date) date_dep = dependency('date', fallback: ['hinnant-date', 'date_dep']) endif deps_libpistache += date_dep +else + add_project_arguments('-DPISTACHE_USE_STD_CHRONO', language: 'cpp') endif if get_option('PISTACHE_USE_RAPIDJSON')