From ecbe7c1b4faa5437130d6ccbe0c05a270e9aa558 Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Sun, 11 May 2025 10:33:05 +0300 Subject: [PATCH 01/56] start working on MutableSharedBuffer&SharedBufferView --- .clang-tidy | 1 + solid/utility/sharedbuffer.hpp | 66 +++++++++++++++++++++++++--------- 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 9c566e017..e3a37d17c 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -20,6 +20,7 @@ modernize-*,\ -modernize-use-noexcept,\ -modernize-use-transparent-functors,\ -modernize-use-using,\ +-modernize-use-trailing-return-type,\ performance-*,\ -performance-inefficient-string-concatenation,\ readability-*,\ diff --git a/solid/utility/sharedbuffer.hpp b/solid/utility/sharedbuffer.hpp index c01ba59f2..e726eb96f 100644 --- a/solid/utility/sharedbuffer.hpp +++ b/solid/utility/sharedbuffer.hpp @@ -82,7 +82,7 @@ class SharedBufferBase { _other.pdata_ = &sentinel; } - char* data() const + [[nodiscard]] char* data() const { return pdata_->data(); } @@ -117,29 +117,29 @@ class SharedBufferBase { reset(); } - std::size_t size() const + [[nodiscard]] std::size_t size() const { return pdata_->size_; } - std::size_t capacity() const + [[nodiscard]] std::size_t capacity() const { return pdata_->capacity_; } - std::size_t actualCapacity() const; + [[nodiscard]] std::size_t actualCapacity() const; - auto makerThreadId() const + [[nodiscard]] auto makerThreadId() const { return pdata_->make_thread_id_; } - bool empty() const + [[nodiscard]] bool empty() const { return pdata_->size_ == 0; } - std::size_t useCount() const + [[nodiscard]] std::size_t useCount() const { return pdata_->use_count_.load(); } @@ -148,7 +148,7 @@ class SharedBufferBase { { size_t previous_use_count = 0; if (*this) { - auto buf = pdata_->release(previous_use_count); + auto* buf = pdata_->release(previous_use_count); delete[] buf; pdata_ = &sentinel; } @@ -198,7 +198,7 @@ class SharedBuffer : public impl::SharedBufferBase { reset(); } - char* data() const + [[nodiscard]] char* data() const { return pdata_->data(); } @@ -219,7 +219,7 @@ class SharedBuffer : public impl::SharedBufferBase { return *this; } - SharedBuffer& operator=(SharedBuffer&& _other) + SharedBuffer& operator=(SharedBuffer&& _other) noexcept { doMove(std::move(_other)); return *this; @@ -233,12 +233,13 @@ inline SharedBuffer make_shared_buffer(const std::size_t _cap) return SharedBuffer(_cap); } -class ConstSharedBuffer; - //----------------------------------------------------------------------------- // MutableSharedBuffer //----------------------------------------------------------------------------- +class ConstSharedBuffer; +class SharedBufferView; + class MutableSharedBuffer : public impl::SharedBufferBase { friend class ConstSharedBuffer; friend class BufferManager; @@ -303,6 +304,8 @@ class MutableSharedBuffer : public impl::SharedBufferBase { doMove(std::move(_other)); return *this; } + + SharedBufferView view(size_t _offset, size_t _size); }; inline MutableSharedBuffer make_mutable_buffer(const std::size_t _cap) @@ -338,7 +341,7 @@ class ConstSharedBuffer : public impl::SharedBufferBase { reset(); } - const char* data() const + [[nodiscard]] const char* data() const { return impl::SharedBufferBase::data(); } @@ -347,7 +350,7 @@ class ConstSharedBuffer : public impl::SharedBufferBase { { if (*this) { size_t previous_use_count = 0; - auto buf = pdata_->release(previous_use_count); + auto* buf = pdata_->release(previous_use_count); if (buf) { pdata_->acquire(); return MutableSharedBuffer(std::move(*this)); @@ -408,6 +411,35 @@ inline SharedBuffer::SharedBuffer(MutableSharedBuffer&& _other) { } +//----------------------------------------------------------------------------- +// SharedBufferView +//----------------------------------------------------------------------------- + +class SharedBufferView : private impl::SharedBufferBase { + friend class MutableSharedBuffer; + const char* data_{nullptr}; + size_t size_{0}; + + SharedBufferView( + MutableSharedBuffer const& _other, size_t const _offset, size_t const _size) + : impl::SharedBufferBase(_other) + , data_(impl::SharedBufferBase::data() + _offset) + , size_(_size) + { + } + +public: + [[nodiscard]] char const* data() const + { + return data_; + } + + [[nodiscard]] size_t size() const + { + return size_; + } +}; + //----------------------------------------------------------------------------- // BufferManager //----------------------------------------------------------------------------- @@ -442,9 +474,9 @@ class BufferManager : NonCopyable { return MutableSharedBuffer{make(_cap)}; } - static void localMaxCount(const size_t _cap, const size_t _count); - static size_t localMaxCount(const size_t _cap); - static size_t localCount(const size_t _cap); + static void localMaxCount(size_t _cap, size_t _count); + static size_t localMaxCount(size_t _cap); + static size_t localCount(size_t _cap); static const Configuration& configuration(); From a6ca59c23d90955a3c2659cc82f328a4d04b350f Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Sat, 17 May 2025 15:17:08 +0300 Subject: [PATCH 02/56] started working on sharedbufferview --- solid/utility/sharedbuffer.hpp | 82 +++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/solid/utility/sharedbuffer.hpp b/solid/utility/sharedbuffer.hpp index e726eb96f..3a047665b 100644 --- a/solid/utility/sharedbuffer.hpp +++ b/solid/utility/sharedbuffer.hpp @@ -233,32 +233,73 @@ inline SharedBuffer make_shared_buffer(const std::size_t _cap) return SharedBuffer(_cap); } +//----------------------------------------------------------------------------- +// SharedBufferView +//----------------------------------------------------------------------------- + +class SharedBufferView : protected impl::SharedBufferBase { + friend class MutableSharedBuffer; + const char* data_{nullptr}; + size_t size_{0}; + + SharedBufferView( + MutableSharedBuffer const& _other, size_t const _offset, size_t const _size) + : impl::SharedBufferBase(_other) + , data_(impl::SharedBufferBase::data() + _offset) + , size_(_size) + { + } + +protected: + SharedBufferView(size_t const _cap) + : SharedBufferBase(_cap) + { + } + + SharedBufferView(const std::size_t _cap, const std::thread::id& _thr_id) + : SharedBufferBase(_cap, _thr_id) + { + } + + SharedBufferView(impl::SharedBufferBase && other): impl::SharedBufferBase(std::move(other)){} + +public: + [[nodiscard]] char const* data() const + { + return data_; + } + + [[nodiscard]] size_t size() const + { + return size_; + } +}; + //----------------------------------------------------------------------------- // MutableSharedBuffer //----------------------------------------------------------------------------- class ConstSharedBuffer; -class SharedBufferView; -class MutableSharedBuffer : public impl::SharedBufferBase { +class MutableSharedBuffer : public SharedBufferView { friend class ConstSharedBuffer; friend class BufferManager; friend MutableSharedBuffer make_mutable_buffer(const std::size_t); MutableSharedBuffer(const std::size_t _cap) - : SharedBufferBase(_cap) + : SharedBufferView(_cap) { } MutableSharedBuffer(const std::size_t _cap, const std::thread::id& _thr_id) - : SharedBufferBase(_cap, _thr_id) + : SharedBufferView(_cap, _thr_id) { } MutableSharedBuffer(ConstSharedBuffer&& _other); MutableSharedBuffer(SharedBuffer&& _other) - : SharedBufferBase(std::move(_other)) + : SharedBufferView(std::move(_other)) { } @@ -268,7 +309,7 @@ class MutableSharedBuffer : public impl::SharedBufferBase { MutableSharedBuffer(const MutableSharedBuffer& _other) = delete; MutableSharedBuffer(MutableSharedBuffer&& _other) - : SharedBufferBase(std::move(_other)) + : SharedBufferView(std::move(_other)) { } @@ -411,35 +452,6 @@ inline SharedBuffer::SharedBuffer(MutableSharedBuffer&& _other) { } -//----------------------------------------------------------------------------- -// SharedBufferView -//----------------------------------------------------------------------------- - -class SharedBufferView : private impl::SharedBufferBase { - friend class MutableSharedBuffer; - const char* data_{nullptr}; - size_t size_{0}; - - SharedBufferView( - MutableSharedBuffer const& _other, size_t const _offset, size_t const _size) - : impl::SharedBufferBase(_other) - , data_(impl::SharedBufferBase::data() + _offset) - , size_(_size) - { - } - -public: - [[nodiscard]] char const* data() const - { - return data_; - } - - [[nodiscard]] size_t size() const - { - return size_; - } -}; - //----------------------------------------------------------------------------- // BufferManager //----------------------------------------------------------------------------- From ed629d1ef7d50c8e132dfbc158f74d19bcf39a4b Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Sun, 8 Jun 2025 01:16:33 +0300 Subject: [PATCH 03/56] mprpc: WIP - switch to using RingSharedBuffer and MutableSharedBuffer --- CMakeLists.txt | 2 +- solid/frame/mprpc/mprpccompression_snappy.hpp | 12 +- solid/frame/mprpc/mprpcconfiguration.hpp | 67 ++--- solid/frame/mprpc/mprpcprotocol.hpp | 17 +- .../mprpc/mprpcprotocol_serialization_v3.hpp | 2 +- solid/frame/mprpc/mprpcrelayengine.hpp | 12 +- solid/frame/mprpc/mprpcsocketstub.hpp | 2 +- solid/frame/mprpc/mprpcsocketstub_openssl.hpp | 2 +- solid/frame/mprpc/mprpcsocketstub_plain.hpp | 2 +- solid/frame/mprpc/src/mprpcconfiguration.cpp | 40 +-- solid/frame/mprpc/src/mprpcconnection.cpp | 218 +++++++++------- solid/frame/mprpc/src/mprpcconnection.hpp | 53 ++-- solid/frame/mprpc/src/mprpcmessagereader.cpp | 7 +- solid/frame/mprpc/src/mprpcmessagewriter.cpp | 6 +- solid/frame/mprpc/src/mprpcmessagewriter.hpp | 25 +- solid/frame/mprpc/src/mprpcutility.hpp | 39 ++- .../mprpc/test/test_clientserver_basic.cpp | 2 +- solid/system/exception.hpp | 35 ++- solid/utility/sharedbuffer.hpp | 242 +++++++++++++++--- solid/utility/src/sharedbuffer.cpp | 13 + solid/utility/test/test_collapse.cpp | 2 + solid/utility/test/test_shared_buffer.cpp | 2 + 22 files changed, 487 insertions(+), 315 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f4c1cf42..3f0183a30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -328,7 +328,7 @@ if(NOT NO_EXTERNAL) include_directories(${CMAKE_BINARY_DIR}/external/include) if(EXTERNAL_DIR STREQUAL "" OR NOT EXISTS ${EXTERNAL_DIR}) - set(EXTERNAL_DIR "${CMAKE_CURRENT_BINARY_DIR}/external") + set(EXTERNAL_DIR "${CMAKE_BINARY_DIR}/external") include(cmake/build-openssl.cmake) else() diff --git a/solid/frame/mprpc/mprpccompression_snappy.hpp b/solid/frame/mprpc/mprpccompression_snappy.hpp index 1ca06f816..5b3890698 100644 --- a/solid/frame/mprpc/mprpccompression_snappy.hpp +++ b/solid/frame/mprpc/mprpccompression_snappy.hpp @@ -16,10 +16,7 @@ #include "solid/frame/mprpc/mprpcconfiguration.hpp" #include "solid/frame/mprpc/mprpcprotocol.hpp" -namespace solid { -namespace frame { -namespace mprpc { -namespace snappy { +namespace solid::frame::mprpc::snappy { struct Engine { const size_t buff_threshold; @@ -37,7 +34,7 @@ struct Engine { if (_bufsz > buff_threshold) { - char tmpbuf[Protocol::MaxPacketDataSize]; + char tmpbuf[Protocol::max_packet_size]; size_t len = 0; @@ -80,7 +77,4 @@ inline void setup(mprpc::Configuration& _rcfg, size_t _buff_threshold = 1024, si _rcfg.writer.inplace_compress_fnc = Engine(_buff_threshold, _diff_threshold); } -} // namespace snappy -} // namespace mprpc -} // namespace frame -} // namespace solid +} // namespace solid::frame::mprpc::snappy diff --git a/solid/frame/mprpc/mprpcconfiguration.hpp b/solid/frame/mprpc/mprpcconfiguration.hpp index 198660711..f7f3a0289 100644 --- a/solid/frame/mprpc/mprpcconfiguration.hpp +++ b/solid/frame/mprpc/mprpcconfiguration.hpp @@ -63,7 +63,7 @@ using RelayDataFlagsT = Flags; std::ostream& operator<<(std::ostream& _ros, const RelayDataFlagsT& _flags); struct RelayData { - SharedBuffer buffer_; + SharedBufferView buffer_; const char* pdata_ = nullptr; size_t data_size_ = 0; RelayData* pnext_ = nullptr; @@ -76,8 +76,6 @@ struct RelayData { RelayData( RelayData&& _rrelmsg) noexcept : buffer_(std::move(_rrelmsg.buffer_)) - , pdata_(_rrelmsg.pdata_) - , data_size_(_rrelmsg.data_size_) , pnext_(nullptr) , flags_(_rrelmsg.flags_) , message_flags_(_rrelmsg.message_flags_) @@ -88,8 +86,6 @@ struct RelayData { RelayData& operator=(RelayData&& _rrelmsg) noexcept { buffer_ = std::move(_rrelmsg.buffer_); - pdata_ = _rrelmsg.pdata_; - data_size_ = _rrelmsg.data_size_; pnext_ = _rrelmsg.pnext_; flags_ = _rrelmsg.flags_; message_flags_ = _rrelmsg.message_flags_; @@ -102,9 +98,6 @@ struct RelayData { void clear() { - pdata_ = nullptr; - data_size_ = 0; - // connection_id_.clear(); buffer_.reset(); pnext_ = nullptr; flags_.reset(); @@ -112,27 +105,27 @@ struct RelayData { pmessage_header_ = nullptr; } - bool isMessageBegin() const + [[nodiscard]] bool isMessageBegin() const { return flags_.has(RelayDataFlagsE::First); } - bool isMessageEnd() const + [[nodiscard]] bool isMessageEnd() const { return flags_.has(RelayDataFlagsE::Last); } - bool isMessageLast() const + [[nodiscard]] bool isMessageLast() const { return isMessageEnd() && !Message::is_response_part(this->message_flags_); } - bool isMessagePart() const + [[nodiscard]] bool isMessagePart() const { return Message::is_response_part(this->message_flags_); } - bool isRequest() const + [[nodiscard]] bool isRequest() const { return Message::is_awaiting_response(this->message_flags_); } @@ -140,13 +133,9 @@ struct RelayData { private: friend class RelayConnection; RelayData( - const SharedBuffer& _buffer, - const char* _pdata, - size_t _data_size, - const bool _is_last) + const SharedBufferView& _buffer, + const bool _is_last) : buffer_(_buffer) - , pdata_(_pdata) - , data_size_(_data_size) { if (_is_last) { flags_.set(RelayDataFlagsE::Last); @@ -163,7 +152,7 @@ class RelayEngine { protected: using PushFunctionT = solid_function_t(bool(RelayData*&, const MessageId&, MessageId&, bool&)); - using DoneFunctionT = solid_function_t(void(SharedBuffer&)); + using DoneFunctionT = solid_function_t(void(SharedBufferView&)); using CancelFunctionT = solid_function_t(void(const MessageHeader&)); RelayEngine() {} @@ -284,8 +273,8 @@ using ClientSetupSocketDeviceFunctionT = solid_function_t(bool(SocketDe using ResolveCompleteFunctionT = solid_function_t(void(AddressVectorT&&)); using ConnectionStopFunctionT = solid_function_t(void(ConnectionContext&)); using ConnectionStartFunctionT = solid_function_t(void(ConnectionContext&)); -using SendAllocateBufferFunctionT = solid_function_t(SharedBuffer(const uint32_t)); -using RecvAllocateBufferFunctionT = solid_function_t(SharedBuffer(const uint32_t)); +using SendAllocateBufferFunctionT = solid_function_t(MutableSharedBuffer(const uint32_t)); +using RecvAllocateBufferFunctionT = solid_function_t(MutableSharedBuffer(const uint32_t)); using CompressFunctionT = solid_function_t(size_t(char*, size_t, ErrorConditionT&)); using UncompressFunctionT = solid_function_t(size_t(char*, const char*, size_t, ErrorConditionT&)); using ConnectionEnterActiveCompleteFunctionT = solid_function_t(void(ConnectionContext&, ErrorConditionT const&)); @@ -343,21 +332,21 @@ class Configuration { ReaderConfiguration reader; WriterConfiguration writer; - std::chrono::milliseconds connection_timeout_recv = std::chrono::minutes(10); - std::chrono::milliseconds connection_timeout_send_soft = std::chrono::seconds(10); - std::chrono::milliseconds connection_timeout_send_hard = std::chrono::minutes(5); - uint8_t connection_recv_buffer_start_capacity_kb = 0; - uint8_t connection_recv_buffer_max_capacity_kb = 64; - uint8_t connection_send_buffer_start_capacity_kb = 0; - uint8_t connection_send_buffer_max_capacity_kb = 64; - uint16_t connection_relay_buffer_count = 8; - ConnectionStopFunctionT connection_stop_fnc; - ConnectionOnEventFunctionT connection_on_event_fnc; - ConnectionSendTimeoutSoftFunctionT connection_on_send_timeout_soft_ = [](ConnectionContext&) {}; - RecvAllocateBufferFunctionT connection_recv_buffer_allocate_fnc; - SendAllocateBufferFunctionT connection_send_buffer_allocate_fnc; - Protocol::PointerT protocol_ptr; - ActorCreateFunctionT actor_create_fnc; + std::chrono::milliseconds connection_timeout_recv = std::chrono::minutes(10); + std::chrono::milliseconds connection_timeout_send_soft = std::chrono::seconds(10); + std::chrono::milliseconds connection_timeout_send_hard = std::chrono::minutes(5); + /* [[deprecated("Not used anymore")]] */ uint8_t connection_recv_buffer_start_capacity_kb = 0; + /* [[deprecated("Not used anymore")]] */ uint8_t connection_recv_buffer_max_capacity_kb = 64; + /* [[deprecated("Not used anymore")]] */ uint8_t connection_send_buffer_start_capacity_kb = 0; + /* [[deprecated("Not used anymore")]] */ uint8_t connection_send_buffer_max_capacity_kb = 64; + uint16_t connection_relay_buffer_count = 8; + ConnectionStopFunctionT connection_stop_fnc; + ConnectionOnEventFunctionT connection_on_event_fnc; + ConnectionSendTimeoutSoftFunctionT connection_on_send_timeout_soft_ = [](ConnectionContext&) {}; + RecvAllocateBufferFunctionT connection_recv_buffer_allocate_fnc; + SendAllocateBufferFunctionT connection_send_buffer_allocate_fnc; + Protocol::PointerT protocol_ptr; + ActorCreateFunctionT actor_create_fnc; struct Server { using ConnectionCreateSocketFunctionT = solid_function_t(SocketStubPtrT(Configuration const&, frame::aio::ActorProxy const&, SocketDevice&&, char*)); @@ -511,9 +500,9 @@ class Configuration { return !isServer() && isClient(); } - SharedBuffer allocateRecvBuffer() const; + [[nodiscard]] MutableSharedBuffer allocateRecvBuffer() const; - SharedBuffer allocateSendBuffer() const; + [[nodiscard]] MutableSharedBuffer allocateSendBuffer() const; void check() const; diff --git a/solid/frame/mprpc/mprpcprotocol.hpp b/solid/frame/mprpc/mprpcprotocol.hpp index 6cec470f9..d208a307a 100644 --- a/solid/frame/mprpc/mprpcprotocol.hpp +++ b/solid/frame/mprpc/mprpcprotocol.hpp @@ -17,9 +17,7 @@ #include -namespace solid { -namespace frame { -namespace mprpc { +namespace solid::frame::mprpc { class ConnectionContext; @@ -162,7 +160,8 @@ class Protocol : NonCopyable { uint32_t version_minor_ = 0; public: - static constexpr size_t MaxPacketDataSize = 1024 * 64; + static constexpr size_t packet_header_size = 4; + static constexpr size_t max_packet_size = std::numeric_limits::max() - (std::numeric_limits::max() % packet_header_size); using PointerT = std::shared_ptr; @@ -190,10 +189,10 @@ class Protocol : NonCopyable { // virtual const TypeStub& operator[](const size_t _idx) const = 0; virtual void complete(const size_t _idx, ConnectionContext&, MessagePointerT<>&, MessagePointerT<>&, ErrorConditionT const&) const = 0; - virtual Serializer::PointerT createSerializer(const WriterConfiguration& _rconf) const = 0; - virtual Deserializer::PointerT createDeserializer(const ReaderConfiguration& _rconf) const = 0; + [[nodiscard]] virtual Serializer::PointerT createSerializer(const WriterConfiguration& _rconf) const = 0; + [[nodiscard]] virtual Deserializer::PointerT createDeserializer(const ReaderConfiguration& _rconf) const = 0; - virtual size_t minimumFreePacketDataSize() const = 0; + [[nodiscard]] virtual size_t minimumFreePacketDataSize() const = 0; void version(const uint32_t _major, const uint32_t _minor) { @@ -212,6 +211,4 @@ class Protocol : NonCopyable { } }; -} // namespace mprpc -} // namespace frame -} // namespace solid +} // namespace solid::frame::mprpc diff --git a/solid/frame/mprpc/mprpcprotocol_serialization_v3.hpp b/solid/frame/mprpc/mprpcprotocol_serialization_v3.hpp index 259b208d1..a1a52a0d2 100644 --- a/solid/frame/mprpc/mprpcprotocol_serialization_v3.hpp +++ b/solid/frame/mprpc/mprpcprotocol_serialization_v3.hpp @@ -361,7 +361,7 @@ class Protocol : public mprpc::Protocol { { } - size_t minimumFreePacketDataSize() const override + [[nodiscard]] size_t minimumFreePacketDataSize() const override { return 16; } diff --git a/solid/frame/mprpc/mprpcrelayengine.hpp b/solid/frame/mprpc/mprpcrelayengine.hpp index d7a7c59ec..a8fc75e3c 100644 --- a/solid/frame/mprpc/mprpcrelayengine.hpp +++ b/solid/frame/mprpc/mprpcrelayengine.hpp @@ -14,10 +14,7 @@ #include "solid/system/error.hpp" #include "solid/system/pimpl.hpp" -namespace solid { -namespace frame { -namespace mprpc { -namespace relay { +namespace solid::frame::mprpc::relay { struct ConnectionStubBase { ActorIdT id_; @@ -98,7 +95,7 @@ class EngineCore : public RelayEngine { doExecute(f); } - ConnectionPrintStub plot(const ConnectionStubBase& _rcon) const + [[nodiscard]] ConnectionPrintStub plot(const ConnectionStubBase& _rcon) const { return ConnectionPrintStub(*this, _rcon); } @@ -158,7 +155,4 @@ class EngineCore : public RelayEngine { void doRegisterConnectionId(const ConnectionContext& _rconctx, const size_t _idx); }; -} // namespace relay -} // namespace mprpc -} // namespace frame -} // namespace solid +} // namespace solid::frame::mprpc::relay diff --git a/solid/frame/mprpc/mprpcsocketstub.hpp b/solid/frame/mprpc/mprpcsocketstub.hpp index 4b3df0b0a..244a7d8c4 100644 --- a/solid/frame/mprpc/mprpcsocketstub.hpp +++ b/solid/frame/mprpc/mprpcsocketstub.hpp @@ -73,7 +73,7 @@ class SocketStub { virtual bool hasPendingSend() const = 0; virtual bool sendAll( - frame::aio::ReactorContext& _rctx, OnSendF _pf, char* _buf, size_t _bufcp) + frame::aio::ReactorContext& _rctx, OnSendF _pf, char const* _buf, size_t _bufcp) = 0; virtual void prepareSocket( diff --git a/solid/frame/mprpc/mprpcsocketstub_openssl.hpp b/solid/frame/mprpc/mprpcsocketstub_openssl.hpp index d0dcf1e40..f3a9959f4 100644 --- a/solid/frame/mprpc/mprpcsocketstub_openssl.hpp +++ b/solid/frame/mprpc/mprpcsocketstub_openssl.hpp @@ -172,7 +172,7 @@ class SocketStub final : public mprpc::SocketStub { } bool sendAll( - frame::aio::ReactorContext& _rctx, OnSendF _pf, char* _buf, size_t _bufcp) override final + frame::aio::ReactorContext& _rctx, OnSendF _pf, char const* _buf, size_t _bufcp) override final { return sock.sendAll(_rctx, _buf, _bufcp, _pf); } diff --git a/solid/frame/mprpc/mprpcsocketstub_plain.hpp b/solid/frame/mprpc/mprpcsocketstub_plain.hpp index 683ff2561..02d599a4c 100644 --- a/solid/frame/mprpc/mprpcsocketstub_plain.hpp +++ b/solid/frame/mprpc/mprpcsocketstub_plain.hpp @@ -128,7 +128,7 @@ class SocketStub final : public mprpc::SocketStub { } bool sendAll( - frame::aio::ReactorContext& _rctx, OnSendF _pf, char* _buf, size_t _bufcp) override final + frame::aio::ReactorContext& _rctx, OnSendF _pf, char const* _buf, size_t _bufcp) override final { return sock.sendAll(_rctx, _buf, _bufcp, _pf); } diff --git a/solid/frame/mprpc/src/mprpcconfiguration.cpp b/solid/frame/mprpc/src/mprpcconfiguration.cpp index a3a30d38f..8d7040c8d 100644 --- a/solid/frame/mprpc/src/mprpcconfiguration.cpp +++ b/solid/frame/mprpc/src/mprpcconfiguration.cpp @@ -40,14 +40,14 @@ std::ostream& operator<<(std::ostream& _ros, const RelayDataFlagsT& _flags) } namespace { -SharedBuffer default_allocate_recv_buffer(const uint32_t _cp) +MutableSharedBuffer default_allocate_recv_buffer(const uint32_t _cp) { - return BufferManager::make(_cp); + return BufferManager::makeMutable(_cp); } -SharedBuffer default_allocate_send_buffer(const uint32_t _cp) +MutableSharedBuffer default_allocate_send_buffer(const uint32_t _cp) { - return make_shared_buffer(_cp); + return make_mutable_buffer(_cp); } // void empty_reset_serializer_limits(ConnectionContext &, serialization::binary::Limits&){} @@ -188,11 +188,6 @@ bool RelayEngine::notifyConnection(Manager& _rm, const ActorIdT& _rrelay_uid, co //----------------------------------------------------------------------------- void Configuration::init() { - connection_recv_buffer_start_capacity_kb = 16; - connection_send_buffer_start_capacity_kb = 16; - - connection_recv_buffer_max_capacity_kb = connection_send_buffer_max_capacity_kb = 64; - connection_recv_buffer_allocate_fnc = &default_allocate_recv_buffer; connection_send_buffer_allocate_fnc = &default_allocate_send_buffer; @@ -300,22 +295,6 @@ void Configuration::prepare() pool_max_pending_connection_count = 1; } - if (connection_recv_buffer_max_capacity_kb > 64) { - connection_recv_buffer_max_capacity_kb = 64; - } - - if (connection_send_buffer_max_capacity_kb > 64) { - connection_send_buffer_max_capacity_kb = 64; - } - - if (connection_recv_buffer_start_capacity_kb > connection_recv_buffer_max_capacity_kb) { - connection_recv_buffer_start_capacity_kb = connection_recv_buffer_max_capacity_kb; - } - - if (connection_send_buffer_start_capacity_kb > connection_send_buffer_max_capacity_kb) { - connection_send_buffer_start_capacity_kb = connection_send_buffer_max_capacity_kb; - } - if (!server.hasSecureConfiguration()) { server.connection_start_secure = false; } @@ -365,15 +344,18 @@ void Configuration::createListenerDevice(SocketDevice& _rsd) const } } +constexpr size_t send_buffer_capacity = Protocol::max_packet_size; +constexpr size_t recv_buffer_capacity = send_buffer_capacity * 2; + //----------------------------------------------------------------------------- -SharedBuffer Configuration::allocateRecvBuffer() const +MutableSharedBuffer Configuration::allocateRecvBuffer() const { - return connection_recv_buffer_allocate_fnc(connection_recv_buffer_start_capacity_kb * 1024); + return connection_recv_buffer_allocate_fnc(recv_buffer_capacity); } //----------------------------------------------------------------------------- -SharedBuffer Configuration::allocateSendBuffer() const +MutableSharedBuffer Configuration::allocateSendBuffer() const { - return connection_send_buffer_allocate_fnc(connection_send_buffer_start_capacity_kb * 1024); + return connection_send_buffer_allocate_fnc(send_buffer_capacity); } //----------------------------------------------------------------------------- } // namespace mprpc diff --git a/solid/frame/mprpc/src/mprpcconnection.cpp b/solid/frame/mprpc/src/mprpcconnection.cpp index ae41df163..94d3436de 100644 --- a/solid/frame/mprpc/src/mprpcconnection.cpp +++ b/solid/frame/mprpc/src/mprpcconnection.cpp @@ -8,17 +8,17 @@ // See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt. // #include "mprpcconnection.hpp" +#include "mprpcutility.hpp" #include "solid/frame/aio/aioreactorcontext.hpp" #include "solid/frame/manager.hpp" #include "solid/frame/mprpc/mprpcerror.hpp" #include "solid/frame/mprpc/mprpcservice.hpp" #include "solid/utility/event.hpp" +#include #include #include -namespace solid { -namespace frame { -namespace mprpc { +namespace solid::frame::mprpc { namespace { const LoggerT logger("solid::frame::mprpc::connection"); @@ -236,21 +236,27 @@ struct RecvRaw { //----------------------------------------------------------------------------- inline void Connection::doOptimizeRecvBuffer() { + if (recv_buf_.cempty()) [[likely]] { + recv_buf_.optimize(); + } else if ((recv_buf_.csize() + recv_buf_.msize()) < PacketHeader::max_size) { + // not enough space in the recv_buf for a packet. + solid_log(logger, Warning, this << " optimizing - " << recv_buf_.csize() << " " << recv_buf_.msize()); + recv_buf_.optimize(); + } + assert(recv_buf_.msize()); +#if 0 // TODO: remove const size_t remaining_size = recv_buf_.size() - cons_buf_off_; if (remaining_size <= cons_buf_off_) { memcpy(recv_buf_.data(), recv_buf_.data() + cons_buf_off_, remaining_size); cons_buf_off_ = 0; recv_buf_.resize(remaining_size); } +#endif } //----------------------------------------------------------------------------- inline void Connection::doOptimizeRecvBufferForced() { - const size_t remaining_size = recv_buf_.size() - cons_buf_off_; - - memmove(recv_buf_.data(), recv_buf_.data() + cons_buf_off_, remaining_size); - cons_buf_off_ = 0; - recv_buf_.resize(remaining_size); + recv_buf_.optimize(); } //----------------------------------------------------------------------------- Connection::Connection( @@ -815,7 +821,7 @@ void Connection::doHandleEventEnterActive(frame::aio::ReactorContext& _rctx, Eve if (!isStopping()) { // start receiving messages - this->postRecvSome(_rctx, recv_buf_.data(), recv_buf_.capacity()); + this->postRecvSome(_rctx, recv_buf_.mdata(), recv_buf_.msize()); if (rconfig.hasConnectionTimeoutRecv()) { timeout_recv_ = _rctx.nanoTime() + rconfig.connection_timeout_recv; @@ -877,7 +883,7 @@ void Connection::doHandleEventEnterPassive(frame::aio::ReactorContext& _rctx, Ev }); // start receiving messages - this->postRecvSome(_rctx, recv_buf_.data(), recv_buf_.capacity()); + this->postRecvSome(_rctx, recv_buf_.mdata(), recv_buf_.msize()); if (isServer() && config.server.hasConnectionTimeoutActive()) { timeout_active_ = _rctx.nanoTime() + config.server.connection_timeout_active; @@ -949,7 +955,7 @@ template solid_log(logger, Verbose, &rthis << ""); // we need the connection_on_secure_connect_fnc for advancing. if (solid_function_empty(config.client.connection_on_secure_handshake_fnc)) { - rthis.doStop(_rctx, error_connection_invalid_state); // TODO: add new error + rthis.doStop(_rctx, error_connection_invalid_state); } } else { rthis.flags_.set(FlagsE::Secure); @@ -1047,17 +1053,13 @@ void Connection::doHandleEventSendRaw(frame::aio::ReactorContext& _rctx, EventBa solid_log(logger, Info, this << " datasize = " << pdata->data.size()); - size_t tocopy = send_buf_.capacity(); + size_t const tocopy = std::min(send_buf_.msize(), pdata->data.size()); - if (tocopy > pdata->data.size()) { - tocopy = pdata->data.size(); - } - - memcpy(send_buf_.data(), pdata->data.data(), tocopy); + memcpy(send_buf_.mdata(), pdata->data.data(), tocopy); if (tocopy != 0u) { pdata->offset = tocopy; - if (this->postSendAll(_rctx, send_buf_.data(), tocopy, _revent)) { + if (this->postSendAll(_rctx, send_buf_.mdata(), tocopy, _revent)) { pdata->complete_fnc(conctx, _rctx.error()); } } else { @@ -1073,39 +1075,42 @@ void Connection::doHandleEventRecvRaw(frame::aio::ReactorContext& _rctx, EventBa { RecvRaw* pdata = _revent.cast(); ConnectionContext conctx(_rctx, service(_rctx), *this); - size_t used_size = 0; + size_t consume_size = 0; solid_assert_log(pdata, logger); solid_log(logger, Info, this); if (this->isRawState() && pdata != nullptr) { - if (recv_buf_.size() == cons_buf_off_) { - if (this->postRecvSome(_rctx, recv_buf_.data(), recv_buf_.capacity(), _revent)) { + if (recv_buf_.csize() == 0U) { + if (this->postRecvSome(_rctx, recv_buf_.mdata(), recv_buf_.msize(), _revent)) { - pdata->complete_fnc(conctx, nullptr, used_size, _rctx.error()); + pdata->complete_fnc(conctx, nullptr, consume_size, _rctx.error()); } } else { - used_size = recv_buf_.size() - cons_buf_off_; + consume_size = recv_buf_.csize(); - pdata->complete_fnc(conctx, recv_buf_.data() + cons_buf_off_, used_size, _rctx.error()); + pdata->complete_fnc(conctx, recv_buf_.cdata(), consume_size, _rctx.error()); - if (used_size > (recv_buf_.size() - cons_buf_off_)) { - used_size = (recv_buf_.size() - cons_buf_off_); - } - - cons_buf_off_ += used_size; + consume_size = std::min(consume_size, recv_buf_.csize()); + // cons_buf_off_ += used_size;//TODO: remove + recv_buf_.consume(consume_size); + if (recv_buf_.cempty()) { + recv_buf_.optimize(); + } +#if 0 // TODO: if (cons_buf_off_ == recv_buf_.size()) { cons_buf_off_ = 0; recv_buf_.resize(0); } else { solid_assert_log(cons_buf_off_ < recv_buf_.size(), logger); } +#endif } } else if (pdata != nullptr) { - pdata->complete_fnc(conctx, nullptr, used_size, error_connection_invalid_state); + pdata->complete_fnc(conctx, nullptr, consume_size, error_connection_invalid_state); } } //----------------------------------------------------------------------------- @@ -1198,17 +1203,13 @@ template if (!_rctx.error()) { - size_t tocopy = pdata->data.size() - pdata->offset; - - if (tocopy > rthis.send_buf_.capacity()) { - tocopy = rthis.send_buf_.capacity(); - } + size_t const tocopy = std::min(pdata->data.size() - pdata->offset, rthis.send_buf_.msize()); - memcpy(rthis.send_buf_.data(), pdata->data.data() + pdata->offset, tocopy); + memcpy(rthis.send_buf_.mdata(), pdata->data.data() + pdata->offset, tocopy); if (tocopy != 0u) { pdata->offset += tocopy; - if (rthis.postSendAll(_rctx, rthis.send_buf_.data(), tocopy, _revent)) { + if (rthis.postSendAll(_rctx, rthis.send_buf_.mdata(), tocopy, _revent)) { pdata->complete_fnc(conctx, _rctx.error()); } } else { @@ -1232,17 +1233,16 @@ template if (pdata != nullptr) { - size_t used_size = _sz; + size_t consume_size = _sz; - pdata->complete_fnc(conctx, rthis.recv_buf_.data(), used_size, _rctx.error()); + pdata->complete_fnc(conctx, rthis.recv_buf_.cdata(), consume_size, _rctx.error()); - if (used_size > _sz) { - used_size = _sz; - } + consume_size = std::min(consume_size, _sz); - if (used_size < _sz) { - rthis.recv_buf_.resize(_sz); - rthis.cons_buf_off_ = used_size; + if (consume_size < _sz) { + rthis.recv_buf_.append(_sz); + rthis.recv_buf_.consume(consume_size); + rthis.recv_buf_.optimize(); } } } @@ -1250,6 +1250,38 @@ template template void Connection::doResetRecvBuffer(frame::aio::ReactorContext& _rctx, const uint8_t _request_buffer_ack_count, ErrorConditionT& _rerr) { + if (_request_buffer_ack_count == 0) [[likely]] { + return; + } else if (recv_buf_.useCount() > 1) { + solid_log(logger, Verbose, this << " buffer used for relay - try replace it. vec_size = " << recv_buf_vec_.size() << " count = " << recv_buf_count_); + MutableSharedBuffer new_buf; + if (!recv_buf_vec_.empty()) { + new_buf = std::move(recv_buf_vec_.back()); + recv_buf_vec_.pop_back(); + } else if (recv_buf_count_ < service(_rctx).configuration().connection_relay_buffer_count) { + new_buf = service(_rctx).configuration().allocateRecvBuffer(); + } else { + recv_buf_.reset(); + _rerr = error_connection_too_many_recv_buffers; + return; + } + memcpy(new_buf.mdata(), recv_buf_.cdata(), recv_buf_.csize()); + new_buf.append(recv_buf_.csize()); + recv_buf_ = std::move(new_buf); + } else { + // tried to relay received messages/message parts - but all failed + // so we need to ack the buffer + solid_assert_log(recv_buf_.useCount(), logger); + solid_log(logger, Info, this << " send accept for " << (int)_request_buffer_ack_count << " buffers"); + + if (ackd_buf_count_ == 0) { + ackd_buf_count_ += _request_buffer_ack_count; + this->post(_rctx, [this](frame::aio::ReactorContext& _rctx, EventBase const& /*_revent*/) { this->doSend(_rctx); }); + } else { + ackd_buf_count_ += _request_buffer_ack_count; + } + } +#if 0 // TODO: remove if (_request_buffer_ack_count == 0) { } else if (recv_buf_.useCount() > 1) { @@ -1285,6 +1317,7 @@ void Connection::doResetRecvBuffer(frame::aio::ReactorContext& _rctx, const uint ackd_buf_count_ += _request_buffer_ack_count; } } +#endif } //----------------------------------------------------------------------------- template @@ -1358,13 +1391,15 @@ struct ConnectionReceiver : MessageReaderReceiver { template /*static*/ void Connection::onRecv(frame::aio::ReactorContext& _rctx, size_t _sz) { - Connection& rthis = static_cast(_rctx.actor()); - ConnectionContext conctx(_rctx, rthis.service(_rctx), rthis); - const Configuration& rconfig = rthis.service(_rctx).configuration(); - unsigned repeatcnt = 4; - char* pbuf = nullptr; - size_t bufsz = 0; - const uint32_t recvbufcp = rthis.recv_buf_.capacity(); + Connection& rthis = static_cast(_rctx.actor()); + ConnectionContext conctx(_rctx, rthis.service(_rctx), rthis); + const Configuration& rconfig = rthis.service(_rctx).configuration(); + unsigned repeatcnt = 4; + // TODO: remove + // char* pbuf = nullptr; + // size_t bufsz = 0; + // const uint32_t recvbufcp = rthis.recv_buf_.capacity(); + auto& rrecvbuf = rthis.recv_buf_; typename Ctx::ReceiverT rcvr(rthis, _rctx, rconfig.reader, rconfig.protocol(), conctx); ErrorConditionT error; @@ -1373,15 +1408,18 @@ template rthis.service(_rctx).wstatistic().connectionRecvBufferSize(_sz, rthis.recv_buf_.capacity()); if (!_rctx.error()) { - rthis.recv_buf_.append(_sz); - pbuf = rthis.recv_buf_.data() + rthis.cons_buf_off_; - bufsz = rthis.recv_buf_.size() - rthis.cons_buf_off_; + rrecvbuf.append(_sz); + // TODO: remove + // pbuf = rthis.recv_buf_.data() + rthis.cons_buf_off_; + // bufsz = rthis.recv_buf_.size() - rthis.cons_buf_off_;//rrecvbuf.csize() rcvr.request_buffer_ack_count_ = 0; - rthis.cons_buf_off_ += rthis.msg_reader_.read(pbuf, bufsz, rcvr, error); + auto const consumed_size = rthis.msg_reader_.read(rrecvbuf.cdata(), rrecvbuf.csize(), rcvr, error); + // rthis.cons_buf_off_ += consumed_size;//TODO:remove + rrecvbuf.consume(consumed_size); - solid_log(logger, Verbose, &rthis << " consumed size " << rthis.cons_buf_off_ << " of " << bufsz); + solid_log(logger, Verbose, &rthis << " consumed size " << consumed_size << " remaining " << rrecvbuf.csize()); rthis.doResetRecvBuffer(_rctx, rcvr.request_buffer_ack_count_, error); @@ -1391,25 +1429,27 @@ template return; } - if (rthis.cons_buf_off_ < bufsz) { + // if (rthis.cons_buf_off_ < bufsz) {//TODO: remove +#if 0 // TODO + if () { rthis.doOptimizeRecvBufferForced(); } +#endif } else { solid_log(logger, Info, &rthis << ' ' << rthis.id() << " receiving " << _rctx.error().message()); rthis.flags_.set(FlagsE::StopPeer); rthis.doStop(_rctx, _rctx.error(), _rctx.systemError()); return; } + --repeatcnt; rthis.doOptimizeRecvBuffer(); - - solid_assert_log(rthis.recv_buf_, logger); - - pbuf = rthis.recv_buf_.data() + rthis.recv_buf_.size(); - - bufsz = recvbufcp - rthis.recv_buf_.size(); - // solid_log(logger, Info, &rthis<<" buffer size "<(_rctx, pbuf, bufsz, _sz)); + assert(rrecvbuf.msize()); + // TODO: remove + // pbuf = rthis.recv_buf_.data() + rthis.recv_buf_.size(); + // bufsz = recvbufcp - rthis.recv_buf_.size(); + // solid_log(logger, Info, &rthis<<" buffer size "<(_rctx, rrecvbuf.mdata(), rrecvbuf.msize(), _sz)); if (rconfig.hasConnectionTimeoutRecv()) { rthis.timeout_recv_ = _rctx.nanoTime() + rconfig.connection_timeout_recv; @@ -1418,7 +1458,7 @@ template } if (repeatcnt == 0 && !rthis.flags_.isSet(FlagsE::PauseRecv)) { - const bool rv = rthis.postRecvSome(_rctx, pbuf, bufsz); // fully asynchronous call + const bool rv = rthis.postRecvSome(_rctx, rthis.recv_buf_.mdata(), rthis.recv_buf_.msize()); // fully asynchronous call solid_assert_log(!rv, logger); (void)rv; } @@ -1468,7 +1508,7 @@ void Connection::doSend(frame::aio::ReactorContext& _rctx) write_flags.set(MessageWriter::WriteFlagsE::ShouldSendKeepAlive); } - WriteBuffer buffer{send_buf_.data(), send_buf_.capacity()}; + WriteBuffer buffer{send_buf_.mdata(), send_buf_.msize()}; error = msg_writer_.write( buffer, write_flags, ackd_buf_count_, cancel_remote_msg_vec_, send_relay_free_count_, sender); @@ -1476,7 +1516,9 @@ void Connection::doSend(frame::aio::ReactorContext& _rctx) flags_.reset(FlagsE::Keepalive); if (!error) { - service(_rctx).wstatistic().connectionSendBufferSize(buffer.size(), send_buf_.capacity()); + + service(_rctx).wstatistic().connectionSendBufferSize(buffer.size(), send_buf_.msize()); + if (!buffer.empty() && this->sendAll(_rctx, buffer.data(), buffer.size())) { sent_something = true; if (_rctx.error()) { @@ -1491,11 +1533,10 @@ void Connection::doSend(frame::aio::ReactorContext& _rctx) solid_assert(msg_writer_.isEmpty()); repeatcnt = 0; solid_statistic_inc(service(_rctx).wstatistic().connection_send_wait_count_); - break; } else { sent_something = true; - break; } + break; } else { break; } @@ -1829,7 +1870,7 @@ bool Connection::recvSome(frame::aio::ReactorContext& _rctx, char* _buf, size_t } //----------------------------------------------------------------------------- template -bool Connection::sendAll(frame::aio::ReactorContext& _rctx, char* _buf, size_t _bufcp) +bool Connection::sendAll(frame::aio::ReactorContext& _rctx, char const* _buf, size_t _bufcp) { solid_check(!isStopping()); return sock_ptr_->sendAll(_rctx, Connection::onSend, _buf, _bufcp); @@ -1855,10 +1896,11 @@ void Connection::doResumeRead(frame::aio::ReactorContext& _rctx) if (flags_.isSet(FlagsE::PauseRecv)) { flags_.reset(FlagsE::PauseRecv); - const auto pbuf = recv_buf_.data() + recv_buf_.size(); - const auto bufsz = recv_buf_.capacity() - recv_buf_.size(); + // TODO: remove + // const auto pbuf = recv_buf_.data() + recv_buf_.size(); + // const auto bufsz = recv_buf_.capacity() - recv_buf_.size(); - const bool rv = postRecvSome(_rctx, pbuf, bufsz); // fully asynchronous call + const bool rv = postRecvSome(_rctx, recv_buf_.mdata(), recv_buf_.msize()); // fully asynchronous call solid_assert_log(!rv, logger); (void)rv; @@ -2304,10 +2346,9 @@ void RelayConnection::doCancelRelayed( const Configuration& rconfig = configuration(_rctx); size_t ack_buf_cnt = 0; - const auto done_lambda = [this, &ack_buf_cnt](SharedBuffer& _rbuf) { - if (_rbuf.useCount() == 1) { + const auto done_lambda = [this, &ack_buf_cnt](SharedBufferView& _rbuf) { + if (returnRecvBuffer(std::move(_rbuf))) { ++ack_buf_cnt; - returnRecvBuffer(std::move(_rbuf)); } }; @@ -2324,14 +2365,14 @@ bool RelayConnection::doReceiveRelayStart( frame::aio::ReactorContext& _rctx, MessageHeader& _rmsghdr, const char* _pbeg, - size_t _sz, + size_t const _sz, MessageId& _rrelay_id, const bool _is_last, ErrorConditionT& _rerror) { Configuration const& config = configuration(_rctx); ConnectionContext conctx{_rctx, service(_rctx), *this}; - RelayData relmsg{recvBuffer(), _pbeg, _sz /*, this->uid(_rctx)*/, _is_last}; + RelayData relmsg{recvBufferView(_pbeg, _sz), _is_last}; return config.relayEngine().relayStart(uid(_rctx), relayId(), _rmsghdr, std::move(relmsg), _rrelay_id, _rerror); } @@ -2339,14 +2380,14 @@ bool RelayConnection::doReceiveRelayStart( bool RelayConnection::doReceiveRelayBody( frame::aio::ReactorContext& _rctx, const char* _pbeg, - size_t _sz, + size_t const _sz, const MessageId& _rrelay_id, const bool _is_last, ErrorConditionT& _rerror) { Configuration const& config = configuration(_rctx); ConnectionContext conctx{_rctx, service(_rctx), *this}; - RelayData relmsg{recvBuffer(), _pbeg, _sz /*, this->uid(_rctx)*/, _is_last}; + RelayData relmsg{recvBufferView(_pbeg, _sz), _is_last}; return config.relayEngine().relay(relayId(), std::move(relmsg), _rrelay_id, _rerror); } @@ -2355,14 +2396,14 @@ bool RelayConnection::doReceiveRelayResponse( frame::aio::ReactorContext& _rctx, MessageHeader& _rmsghdr, const char* _pbeg, - size_t _sz, + size_t const _sz, const MessageId& _rrelay_id, const bool _is_last, ErrorConditionT& _rerror) { Configuration const& config = configuration(_rctx); ConnectionContext conctx{_rctx, service(_rctx), *this}; - RelayData relmsg{recvBuffer(), _pbeg, _sz /*, this->uid(_rctx)*/, _is_last}; + RelayData relmsg{recvBufferView(_pbeg, _sz), _is_last}; return config.relayEngine().relayResponse(relayId(), _rmsghdr, std::move(relmsg), _rrelay_id, _rerror); } @@ -2388,10 +2429,9 @@ void RelayConnection::doHandleEventRelayDone(frame::aio::ReactorContext& _rctx, Configuration const& config = configuration(_rctx); size_t ack_buf_cnt = 0; - const auto done_lambda = [this, &ack_buf_cnt](SharedBuffer& _rbuf) { - if (_rbuf.useCount() == 1) { + const auto done_lambda = [this, &ack_buf_cnt](SharedBufferView& _rbuf) { + if (returnRecvBuffer(std::move(_rbuf))) { ++ack_buf_cnt; - returnRecvBuffer(std::move(_rbuf)); } }; const auto cancel_lambda = [this](const MessageHeader& _rmsghdr) { @@ -2550,6 +2590,4 @@ void Message::header(frame::mprpc::ConnectionContext& _rctx) header_ = std::move(*_rctx.pmessage_header_); } -} // namespace mprpc -} // namespace frame -} // namespace solid +} // namespace solid::frame::mprpc diff --git a/solid/frame/mprpc/src/mprpcconnection.hpp b/solid/frame/mprpc/src/mprpcconnection.hpp index 27bbb59a5..3e7a74780 100644 --- a/solid/frame/mprpc/src/mprpcconnection.hpp +++ b/solid/frame/mprpc/src/mprpcconnection.hpp @@ -15,7 +15,6 @@ #include "solid/system/flags.hpp" #include "solid/utility/any.hpp" #include "solid/utility/event.hpp" -#include "solid/utility/queue.hpp" #include "solid/frame/aio/aioactor.hpp" #include "solid/frame/aio/aiotimer.hpp" @@ -26,14 +25,11 @@ #include "mprpcmessagereader.hpp" #include "mprpcmessagewriter.hpp" -namespace solid { -namespace frame { -namespace aio { +namespace solid::frame { -namespace openssl { +namespace aio::openssl { class Context; -} // namespace openssl -} // namespace aio +} // namespace aio::openssl namespace mprpc { @@ -42,12 +38,12 @@ class Service; struct ResolveMessage { AddressVectorT addrvec; - bool empty() const + [[nodiscard]] bool empty() const { return addrvec.empty(); } - SocketAddressInet const& currentAddress() const + [[nodiscard]] SocketAddressInet const& currentAddress() const { return addrvec.back(); } @@ -61,7 +57,7 @@ struct ResolveMessage { ResolveMessage(const ResolveMessage&) = delete; - ResolveMessage(ResolveMessage&& _urm) + ResolveMessage(ResolveMessage&& _urm) noexcept : addrvec(std::move(_urm.addrvec)) { } @@ -200,9 +196,9 @@ class Connection : public frame::aio::Actor { void setFlag(const FlagsE _flag); void resetFlag(const FlagsE _flag); - const SharedBuffer& recvBuffer() const; + SharedBufferView recvBufferView(const char*, size_t) const; - void returnRecvBuffer(SharedBuffer&& _buf); + bool returnRecvBuffer(SharedBufferView&& _buf); void ackBufferCountAdd(uint8_t _val); @@ -269,7 +265,7 @@ class Connection : public frame::aio::Actor { template bool recvSome(frame::aio::ReactorContext& _rctx, char* _buf, size_t _bufcp, size_t& _sz); template - bool sendAll(frame::aio::ReactorContext& _rctx, char* _buf, size_t _bufcp); + bool sendAll(frame::aio::ReactorContext& _rctx, char const* _buf, size_t _bufcp); void prepareSocket(frame::aio::ReactorContext& _rctx); const NanoTime& minTimeout() const; @@ -349,7 +345,7 @@ class Connection : public frame::aio::Actor { = frame::aio::SteadyTimer; using FlagsT = solid::Flags; using RequestIdVectorT = MessageWriter::RequestIdVectorT; - using RecvBufferVectorT = std::vector; + using RecvBufferVectorT = std::vector; template friend struct ConnectionReceiver; @@ -358,19 +354,19 @@ class Connection : public frame::aio::Actor { template friend struct ConnectionSenderResponse; - ConnectionPoolId pool_id_; - const std::string& rpool_name_; - TimerT timer_; - FlagsT flags_ = 0; - size_t cons_buf_off_ = 0; + ConnectionPoolId pool_id_; + const std::string& rpool_name_; + TimerT timer_; + FlagsT flags_ = 0; + // size_t cons_buf_off_ = 0;//TODO:delete uint32_t recv_keepalive_count_ = 0; std::chrono::steady_clock::time_point recv_keepalive_boundary_ = std::chrono::steady_clock::time_point::min(); uint16_t recv_buf_count_ = 0; uint8_t send_relay_free_count_; uint8_t ackd_buf_count_ = 0; - SharedBuffer recv_buf_; + RingSharedBuffer recv_buf_; RecvBufferVectorT recv_buf_vec_; - SharedBuffer send_buf_; + MutableSharedBuffer send_buf_; MessageIdVectorT pending_message_vec_; MessageReader msg_reader_; MessageWriter msg_writer_; @@ -666,14 +662,18 @@ inline void Connection::resetFlag(const FlagsE _flag) flags_.reset(_flag); } //----------------------------------------------------------------------------- -inline const SharedBuffer& Connection::recvBuffer() const +inline SharedBufferView Connection::recvBufferView(const char* _pbuf, size_t const _size) const { - return recv_buf_; + return recv_buf_.view(_pbuf - recv_buf_.data(), _size); } //----------------------------------------------------------------------------- -inline void Connection::returnRecvBuffer(SharedBuffer&& _buf) +inline bool Connection::returnRecvBuffer(SharedBufferView&& _buf) { - recv_buf_vec_.emplace_back(std::move(_buf)); + if (auto buf = _buf.collapse()) { + recv_buf_vec_.emplace_back(std::move(buf)); + return true; + } + return false; } //----------------------------------------------------------------------------- inline void Connection::ackBufferCountAdd(uint8_t _val) @@ -712,5 +712,4 @@ inline ErrorConditionT Connection::pollServicePoolForUpdates(frame::aio::Reactor } //----------------------------------------------------------------------------- } // namespace mprpc -} // namespace frame -} // namespace solid +} // namespace solid::frame diff --git a/solid/frame/mprpc/src/mprpcmessagereader.cpp b/solid/frame/mprpc/src/mprpcmessagereader.cpp index eeb456399..2c845c44c 100644 --- a/solid/frame/mprpc/src/mprpcmessagereader.cpp +++ b/solid/frame/mprpc/src/mprpcmessagereader.cpp @@ -13,6 +13,7 @@ #include "solid/frame/mprpc/mprpccontext.hpp" #include "solid/frame/mprpc/mprpcerror.hpp" #include "solid/frame/mprpc/mprpcmessage.hpp" +#include "solid/frame/mprpc/mprpcprotocol.hpp" #include "solid/system/exception.hpp" #include "solid/system/log.hpp" @@ -49,7 +50,7 @@ size_t MessageReader::read( while (pbufpos != pbufend) { if (state_ == StateE::ReadPacketHead) { // try read the header - if ((pbufend - pbufpos) >= static_cast(PacketHeader::size_of_header)) { + if ((pbufend - pbufpos) >= static_cast(PacketHeader::header_size)) { state_ = StateE::ReadPacketBody; } else { break; @@ -187,7 +188,7 @@ void MessageReader::doConsumePacket( if (!_packet_header.isCompressed()) [[likely]] { doConsumePacketLoop(pbufpos, pbufend, _receiver, _rerror); } else { - char tmpbuf[Protocol::MaxPacketDataSize]; // decompress = TODO: try not to use so much stack + char tmpbuf[Protocol::max_packet_size]; // decompress = TODO: try not to use so much stack const size_t uncompressed_size = _receiver.configuration().decompress_fnc(tmpbuf, pbufpos, pbufend - pbufpos, _rerror); if (!_rerror) { @@ -397,7 +398,7 @@ void MessageReader::doConsumeMessageRelayStart( const bool is_message_end = (_cmd & static_cast(PacketHeader::CommandE::EndMessageFlag)) != 0; solid_log(logger, Verbose, "msgidx = " << _msgidx << " message_size = " << _message_size << " is_message_end = " << is_message_end); - // TODO: + if (_receiver.receiveRelayStart(rmsgstub.message_header_, _pbufpos, _message_size, rmsgstub.relay_id, is_message_end, _rerror)) { rmsgstub.state_ = MessageStub::StateE::RelayBody; } else { diff --git a/solid/frame/mprpc/src/mprpcmessagewriter.cpp b/solid/frame/mprpc/src/mprpcmessagewriter.cpp index 0dd4899ce..03bdc1ba8 100644 --- a/solid/frame/mprpc/src/mprpcmessagewriter.cpp +++ b/solid/frame/mprpc/src/mprpcmessagewriter.cpp @@ -419,11 +419,11 @@ ErrorConditionT MessageWriter::write( bool more = true; ErrorConditionT error; - while (more && freesz >= (PacketHeader::size_of_header + _rsender.protocol().minimumFreePacketDataSize())) { + while (more && freesz >= (PacketHeader::header_size + _rsender.protocol().minimumFreePacketDataSize())) { PacketHeader packet_header(PacketHeader::TypeE::Data, 0, 0); PacketOptions packet_options; - char* pbufdata = pbufpos + PacketHeader::size_of_header; + char* pbufdata = pbufpos + PacketHeader::header_size; size_t fillsz = doWritePacketData(pbufdata, pbufend, packet_options, _rackd_buf_count, _cancel_remote_msg_vec, _rrelay_free_count, _rsender, error); if (fillsz != 0u) { @@ -452,7 +452,7 @@ ErrorConditionT MessageWriter::write( more = false; // do not allow multiple packets per relay buffer } - solid_assert_log(static_cast(fillsz) < static_cast(0xffffUL), logger); + solid_assert_log(static_cast(fillsz) <= static_cast(PacketHeader::max_size), logger); packet_header.size(static_cast(fillsz)); diff --git a/solid/frame/mprpc/src/mprpcmessagewriter.hpp b/solid/frame/mprpc/src/mprpcmessagewriter.hpp index c4ba32218..a9c12e58b 100644 --- a/solid/frame/mprpc/src/mprpcmessagewriter.hpp +++ b/solid/frame/mprpc/src/mprpcmessagewriter.hpp @@ -22,25 +22,22 @@ #include "solid/system/flags.hpp" #include "solid/utility/innerlist.hpp" -namespace solid { -namespace frame { -namespace mprpc { +namespace solid::frame::mprpc { -// TODO: replace this with SharedBuffer struct WriteBuffer { WriteBuffer(char* _data = nullptr, size_t _size = -1) : data_(_data) , size_(_size) { } - char* data() const noexcept { return data_; } - size_t size() const noexcept { return size_; } + [[nodiscard]] char* data() const noexcept { return data_; } + [[nodiscard]] size_t size() const noexcept { return size_; } void resize(const size_t _size) noexcept { size_ = _size; } - bool empty() const noexcept { return size_ == 0; } + [[nodiscard]] bool empty() const noexcept { return size_ == 0; } - char* end() const noexcept { return data_ + size_; } + [[nodiscard]] char* end() const noexcept { return data_ + size_; } void reset(char* _data = nullptr, size_t _size = -1) noexcept { @@ -68,9 +65,9 @@ struct MessageWriterSender { { } - WriterConfiguration const& configuration() const { return rconfig_; } - Protocol const& protocol() const { return rproto_; } - ConnectionContext& context() const { return rconctx_; } + [[nodiscard]] WriterConfiguration const& configuration() const { return rconfig_; } + [[nodiscard]] Protocol const& protocol() const { return rproto_; } + [[nodiscard]] ConnectionContext& context() const { return rconctx_; } virtual ~MessageWriterSender(); @@ -193,7 +190,7 @@ class MessageWriter { void cancel(MessageId const& _rmsguid, MessageWriterSender& _rsender, const bool _force = false); - MessagePointerT<> fetchRequest(MessageId const& _rmsguid) const; + [[nodiscard]] MessagePointerT<> fetchRequest(MessageId const& _rmsguid) const; ResponseStateE checkResponseState(MessageId const& _rmsguid, MessageId& _rrelay_id, const bool _erase_request); @@ -399,6 +396,4 @@ inline bool MessageWriter::MessageStub::isSynchronous() const noexcept return Message::is_synchronous(msgbundle_.message_flags); } //----------------------------------------------------------------------------- -} // namespace mprpc -} // namespace frame -} // namespace solid +} // namespace solid::frame::mprpc diff --git a/solid/frame/mprpc/src/mprpcutility.hpp b/solid/frame/mprpc/src/mprpcutility.hpp index 672016290..29307b85d 100644 --- a/solid/frame/mprpc/src/mprpcutility.hpp +++ b/solid/frame/mprpc/src/mprpcutility.hpp @@ -10,15 +10,15 @@ #pragma once +#include "solid/frame/mprpc/mprpcprotocol.hpp" #include "solid/system/cassert.hpp" #include "solid/system/log.hpp" #include "solid/system/socketaddress.hpp" #include "solid/frame/mprpc/mprpcservice.hpp" +#include -namespace solid { -namespace frame { -namespace mprpc { +namespace solid::frame::mprpc { enum struct ResponseStateE { Wait, @@ -50,7 +50,8 @@ class PacketHeader { uint16_t size_; public: - static constexpr size_t size_of_header = 4; + static constexpr size_t header_size = 4; + static constexpr uint16_t max_size = Protocol::max_packet_size - header_size; enum struct TypeE : uint8_t { Data = 1, @@ -71,7 +72,6 @@ class PacketHeader { }; enum struct FlagE : uint8_t { - Size64KB = 1, // DO NOT CHANGE!! Compressed = 2, AckRequest = 4, }; @@ -81,6 +81,7 @@ class PacketHeader { const uint8_t _flags = 0, const uint16_t _size = 0) { + static_assert(Protocol::packet_header_size == header_size); reset(_type, _flags, _size); } @@ -94,18 +95,17 @@ class PacketHeader { size(_size); } - uint32_t size() const + [[nodiscard]] uint16_t size() const { - uint32_t sz = (flags_ & static_cast(FlagE::Size64KB)); - return (sz << 16) | size_; + return size_; } - uint8_t type() const + [[nodiscard]] uint8_t type() const { return type_; } - uint8_t flags() const + [[nodiscard]] uint8_t flags() const { return flags_; } @@ -119,22 +119,21 @@ class PacketHeader { flags_ = _flags /*& (0xff - Size64KBFlagE)*/; } - void size(uint32_t _sz) + void size(uint16_t const _sz) { - size_ = _sz & 0xffff; - flags_ |= ((_sz & (1 << 16)) >> 16); + size_ = _sz; } - bool isTypeKeepAlive() const + [[nodiscard]] bool isTypeKeepAlive() const { return type_ == static_cast(TypeE::KeepAlive); } - bool isCompressed() const + [[nodiscard]] bool isCompressed() const { - return flags_ & static_cast(FlagE::Compressed); + return (flags_ & static_cast(FlagE::Compressed)) != 0U; } - bool isOk() const + [[nodiscard]] bool isOk() const { switch (static_cast(type_)) { case TypeE::Data: @@ -144,7 +143,7 @@ class PacketHeader { return false; } - return size() <= Protocol::MaxPacketDataSize; + return size() <= max_size; } char* store(char* _pc, const Protocol& _rproto) const @@ -244,6 +243,4 @@ struct MessageBundle { } }; -} // namespace mprpc -} // namespace frame -} // namespace solid +} // namespace solid::frame::mprpc diff --git a/solid/frame/mprpc/test/test_clientserver_basic.cpp b/solid/frame/mprpc/test/test_clientserver_basic.cpp index 2cde94587..f20748bb9 100644 --- a/solid/frame/mprpc/test/test_clientserver_basic.cpp +++ b/solid/frame/mprpc/test/test_clientserver_basic.cpp @@ -265,7 +265,7 @@ int test_clientserver_basic(int argc, char* argv[]) { solid::log_start(std::cerr, {".*:EWXS"}); - // solid::log_start(std::cerr, {"solid::frame::mprpc.*:EWX", "\\*:VIEWX"}); + // solid::log_start(std::cerr, {"solid::frame::mprpc.*:VIEWX", "\\*:VIEWX"}); size_t max_per_pool_connection_count = 1; diff --git a/solid/system/exception.hpp b/solid/system/exception.hpp index 65d738462..b4f7876fd 100644 --- a/solid/system/exception.hpp +++ b/solid/system/exception.hpp @@ -90,6 +90,7 @@ class RuntimeError : public std::runtime_error { (solid_likely(a) ? static_cast(0) : solid_throw_error(c)); // adapted from https://github.com/Microsoft/GSL/blob/master/include/gsl/gsl_assert +#if 0 #if defined(__clang__) || defined(__GNUC__) #define solid_likely(x) __builtin_expect(!!(x), 1) #define solid_unlikely(x) __builtin_expect(!!(x), 0) @@ -97,38 +98,32 @@ class RuntimeError : public std::runtime_error { #define solid_likely(x) (!!(x)) #define solid_unlikely(x) (!(x)) #endif +#else +#define solid_likely(x) (!!(x)) +#define solid_unlikely(x) (!(x)) +#endif -#define solid_check1(a) \ - (solid_likely(a) ? static_cast(0) : solid_throw("(" #a ") check failed")); +#define solid_check1(a) \ + if (!(a)) [[unlikely]] { \ + solid_throw("(" #a ") check failed"); \ + } -#define solid_check2(a, msg) \ - (solid_likely(a) ? static_cast(0) : solid_throw("(" #a ") check failed: " << msg)); +#define solid_check2(a, msg) \ + if (!(a)) [[unlikely]] { \ + solid_throw("(" #a ") check failed: " << msg); \ + } #define solid_check_log2(a, l) \ - if (solid_likely(a)) { \ - } else { \ + if (!(a)) [[unlikely]] { \ solid_throw_log(l, "(" #a ") check failed"); \ } #define solid_check_log3(a, l, msg) \ - if (solid_likely(a)) { \ - } else { \ + if (!(a)) [[unlikely]] { \ solid_throw_log(l, "(" #a ") check failed: " << msg); \ } // adapted from: https://stackoverflow.com/questions/9183993/msvc-variadic-macro-expansion/9338429#9338429 -#if 1 #define solid_check(...) SOLID_CALL_OVERLOAD(solid_check, __VA_ARGS__) #define solid_check_log(...) SOLID_CALL_OVERLOAD(solid_check_log, __VA_ARGS__) -#else -#define GET_3RD_ARG(arg1, arg2, arg3, ...) arg3 - -#define solid_check_MACRO_CHOOSER(...) \ - GET_3RD_ARG(__VA_ARGS__, solid_check2, \ - solid_check1) - -#define solid_check(...) \ - solid_check_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__) -#endif - } // namespace solid diff --git a/solid/utility/sharedbuffer.hpp b/solid/utility/sharedbuffer.hpp index 3a047665b..7733b0701 100644 --- a/solid/utility/sharedbuffer.hpp +++ b/solid/utility/sharedbuffer.hpp @@ -2,9 +2,11 @@ #include #include +#include #include #include "solid/system/common.hpp" +#include "solid/system/exception.hpp" #include "solid/system/pimpl.hpp" namespace solid { @@ -54,11 +56,10 @@ class SharedBufferBase { friend class BufferManager; static inline SharedBufferData sentinel{}; - static SharedBufferData* allocate_data(const std::size_t _cap); + static SharedBufferData* allocate_data(std::size_t _cap); SharedBufferData* pdata_; -protected: SharedBufferBase() : pdata_(&sentinel) { @@ -69,14 +70,14 @@ class SharedBufferBase { { } - SharedBufferBase(const std::size_t _cap, const std::thread::id& _thr_id); + SharedBufferBase(std::size_t _cap, const std::thread::id& _thr_id); SharedBufferBase(const SharedBufferBase& _other) : pdata_(_other ? &_other.pdata_->acquire() : _other.pdata_) { } - SharedBufferBase(SharedBufferBase&& _other) + SharedBufferBase(SharedBufferBase&& _other) noexcept : pdata_(_other.pdata_) { _other.pdata_ = &sentinel; @@ -108,6 +109,8 @@ class SharedBufferBase { } public: + static constexpr size_t npos = std::numeric_limits::max(); + explicit operator bool() const noexcept { return pdata_ != &sentinel; @@ -166,7 +169,7 @@ class MutableSharedBuffer; class SharedBuffer : public impl::SharedBufferBase { friend class BufferManager; - friend SharedBuffer make_shared_buffer(const std::size_t); + friend SharedBuffer make_shared_buffer(std::size_t); SharedBuffer(const std::size_t _cap) : SharedBufferBase(_cap) @@ -186,7 +189,7 @@ class SharedBuffer : public impl::SharedBufferBase { { } - SharedBuffer(SharedBuffer&& _other) + SharedBuffer(SharedBuffer&& _other) noexcept : SharedBufferBase(std::move(_other)) { } @@ -243,36 +246,91 @@ class SharedBufferView : protected impl::SharedBufferBase { size_t size_{0}; SharedBufferView( - MutableSharedBuffer const& _other, size_t const _offset, size_t const _size) - : impl::SharedBufferBase(_other) - , data_(impl::SharedBufferBase::data() + _offset) - , size_(_size) - { - } + MutableSharedBuffer const& _other, size_t _offset, size_t _size); protected: SharedBufferView(size_t const _cap) : SharedBufferBase(_cap) + , data_(impl::SharedBufferBase::data()) { } SharedBufferView(const std::size_t _cap, const std::thread::id& _thr_id) : SharedBufferBase(_cap, _thr_id) + , data_(impl::SharedBufferBase::data()) { } - SharedBufferView(impl::SharedBufferBase && other): impl::SharedBufferBase(std::move(other)){} + SharedBufferView(impl::SharedBufferBase&& _other) + : impl::SharedBufferBase(std::move(_other)) + , data_(impl::SharedBufferBase::data()) + { + } public: - [[nodiscard]] char const* data() const + SharedBufferView() = default; + + SharedBufferView(SharedBufferView&& _other) noexcept + : impl::SharedBufferBase(std::move(_other)) + , data_(_other.data_) + , size_(_other.size_) + { + _other.data_ = nullptr; + _other.size_ = 0U; + } + + SharedBufferView(SharedBufferView const& _other) + : impl::SharedBufferBase(_other) + , data_(_other.data_) + , size_(_other.size_) + { + } + + explicit operator bool() const noexcept + { + return impl::SharedBufferBase::operator bool(); + } + + [[nodiscard]] size_t useCount() const + { + return impl::SharedBufferBase::useCount(); + } + + [[nodiscard]] char const* cdata() const { return data_; } - [[nodiscard]] size_t size() const + [[nodiscard]] size_t csize() const { return size_; } + + [[nodiscard]] bool cempty() const + { + return size_ == 0U; + } + + MutableSharedBuffer collapse(); + + void reset() + { + impl::SharedBufferBase::reset(); + data_ = nullptr; + size_ = 0U; + } + + SharedBufferView& operator=(SharedBufferView&& _other) noexcept + { + if (this != &_other) { + doMove(std::move(_other)); + data_ = _other.data_; + size_ = _other.size_; + _other.data_ = nullptr; + _other.size_ = 0; + } + return *this; + } }; //----------------------------------------------------------------------------- @@ -281,25 +339,33 @@ class SharedBufferView : protected impl::SharedBufferBase { class ConstSharedBuffer; -class MutableSharedBuffer : public SharedBufferView { +class MutableSharedBuffer : protected impl::SharedBufferBase { friend class ConstSharedBuffer; + friend class SharedBuffer; friend class BufferManager; - friend MutableSharedBuffer make_mutable_buffer(const std::size_t); + friend class SharedBufferView; + + friend MutableSharedBuffer make_mutable_buffer(std::size_t); MutableSharedBuffer(const std::size_t _cap) - : SharedBufferView(_cap) + : impl::SharedBufferBase(_cap) { } MutableSharedBuffer(const std::size_t _cap, const std::thread::id& _thr_id) - : SharedBufferView(_cap, _thr_id) + : impl::SharedBufferBase(_cap, _thr_id) { } MutableSharedBuffer(ConstSharedBuffer&& _other); MutableSharedBuffer(SharedBuffer&& _other) - : SharedBufferView(std::move(_other)) + : impl::SharedBufferBase(std::move(_other)) + { + } + + MutableSharedBuffer(SharedBufferView&& _other) + : impl::SharedBufferBase(std::move(_other)) { } @@ -308,8 +374,8 @@ class MutableSharedBuffer : public SharedBufferView { MutableSharedBuffer(const MutableSharedBuffer& _other) = delete; - MutableSharedBuffer(MutableSharedBuffer&& _other) - : SharedBufferView(std::move(_other)) + MutableSharedBuffer(MutableSharedBuffer&& _other) noexcept + : impl::SharedBufferBase(std::move(_other)) { } @@ -318,35 +384,61 @@ class MutableSharedBuffer : public SharedBufferView { reset(); } - char* data() + explicit operator bool() const noexcept { - return impl::SharedBufferBase::data(); + return impl::SharedBufferBase::operator bool(); + } + + [[nodiscard]] size_t useCount() const + { + return impl::SharedBufferBase::useCount(); + } + + char* mdata() + { + return impl::SharedBufferBase::data() + size(); + } + + [[nodiscard]] size_t msize() const + { + return capacity() - size(); } void append(const std::size_t _size) { + solid_check(_size <= msize()); pdata_->size_ += _size; } - void resize(const std::size_t _size = 0) + [[nodiscard]] size_t capacity() const { - pdata_->size_ = _size; + return impl::SharedBufferBase::capacity(); } MutableSharedBuffer& operator=(const MutableSharedBuffer& _other) = delete; - MutableSharedBuffer& operator=(MutableSharedBuffer&& _other) + MutableSharedBuffer& operator=(MutableSharedBuffer&& _other) noexcept { - doMove(std::move(_other)); + if (this != &_other) { + doMove(std::move(_other)); + } return *this; } + MutableSharedBuffer& operator=(SharedBuffer&& _other) { doMove(std::move(_other)); return *this; } - SharedBufferView view(size_t _offset, size_t _size); + [[nodiscard]] SharedBufferView view(size_t const _offset = 0, size_t _size = impl::SharedBufferBase::npos) const + { + if (_size == impl::SharedBufferBase::npos) { + _size = size(); + } + solid_check((_offset + _size) <= size()); + return {*this, _offset, _size}; + } }; inline MutableSharedBuffer make_mutable_buffer(const std::size_t _cap) @@ -354,6 +446,62 @@ inline MutableSharedBuffer make_mutable_buffer(const std::size_t _cap) return MutableSharedBuffer(make_shared_buffer(_cap)); } +//----------------------------------------------------------------------------- +// RingSharedBuffer +//----------------------------------------------------------------------------- + +class RingSharedBuffer : public MutableSharedBuffer { + size_t consume_offset_ = 0; + +public: + [[nodiscard]] char const* data() const + { + return impl::SharedBufferBase::data(); + } + + [[nodiscard]] char const* cdata() const + { + return data() + consume_offset_; + } + [[nodiscard]] size_t csize() const + { + return size() - consume_offset_; + } + + void consume(size_t const _size) + { + solid_check(_size <= csize()); + consume_offset_ += _size; + } + + [[nodiscard]] bool cempty() const + { + return csize() == 0U; + } + + [[nodiscard]] bool canOptimize() const + { + return useCount() == 1U; + } + + RingSharedBuffer& operator=(MutableSharedBuffer&& _other) noexcept + { + if (this != &_other) { + doMove(std::move(_other)); + consume_offset_ = 0U; + } + return *this; + } + + void optimize(); + + void reset() + { + impl::SharedBufferBase::reset(); + consume_offset_ = 0U; + } +}; + //----------------------------------------------------------------------------- // ConstSharedBuffer //----------------------------------------------------------------------------- @@ -367,7 +515,7 @@ class ConstSharedBuffer : public impl::SharedBufferBase { { } - ConstSharedBuffer(ConstSharedBuffer&& _other) + ConstSharedBuffer(ConstSharedBuffer&& _other) noexcept : SharedBufferBase(std::move(_other)) { } @@ -394,6 +542,7 @@ class ConstSharedBuffer : public impl::SharedBufferBase { auto* buf = pdata_->release(previous_use_count); if (buf) { pdata_->acquire(); + pdata_->size_ = 0; return MutableSharedBuffer(std::move(*this)); } else { pdata_ = &sentinel; @@ -436,8 +585,33 @@ class ConstSharedBuffer : public impl::SharedBufferBase { } }; +inline SharedBufferView::SharedBufferView( + MutableSharedBuffer const& _other, size_t const _offset, size_t const _size) + : impl::SharedBufferBase(_other) + , data_(impl::SharedBufferBase::data() + _offset) + , size_(_size) +{ +} + +inline MutableSharedBuffer SharedBufferView::collapse() +{ + if (*this) { + size_t previous_use_count = 0; + auto* buf = pdata_->release(previous_use_count); + if (buf) { + pdata_->acquire(); + pdata_->size_ = 0; + this->size_ = 0; + return MutableSharedBuffer(std::move(*this)); + } else { + pdata_ = &sentinel; + } + } + return {}; +} + inline MutableSharedBuffer::MutableSharedBuffer(ConstSharedBuffer&& _other) - : SharedBufferBase(std::move(_other)) + : impl::SharedBufferBase(std::move(_other)) { } @@ -465,7 +639,7 @@ class BufferManager : NonCopyable { using DataT = impl::SharedBufferData; static char* release(DataT* _pdata); - static DataT* allocate(const size_t _cap); + static DataT* allocate(size_t _cap); public: struct LocalData; @@ -476,12 +650,12 @@ class BufferManager : NonCopyable { static BufferManager& instance(const Configuration* _pconfig = nullptr); - inline static SharedBuffer make(const size_t _cap) + static SharedBuffer make(const size_t _cap) { return SharedBuffer{_cap, std::this_thread::get_id()}; } - inline static MutableSharedBuffer makeMutable(const size_t _cap) + static MutableSharedBuffer makeMutable(const size_t _cap) { return MutableSharedBuffer{make(_cap)}; } diff --git a/solid/utility/src/sharedbuffer.cpp b/solid/utility/src/sharedbuffer.cpp index c17785e30..5a082d938 100644 --- a/solid/utility/src/sharedbuffer.cpp +++ b/solid/utility/src/sharedbuffer.cpp @@ -71,6 +71,19 @@ std::size_t SharedBufferBase::actualCapacity() const } // namespace impl +void RingSharedBuffer::optimize() +{ + solid_check(canOptimize()); + if (consume_offset_ == size()) [[likely]] { + consume_offset_ = 0U; + pdata_->size_ = 0U; + } else { + memmove(impl::SharedBufferBase::data(), cdata(), csize()); + pdata_->size_ = csize(); + consume_offset_ = 0U; + } +} + //----------------------------------------------------------------------------- struct BufferManager::LocalData { diff --git a/solid/utility/test/test_collapse.cpp b/solid/utility/test/test_collapse.cpp index 18149372e..1d1427d0f 100644 --- a/solid/utility/test/test_collapse.cpp +++ b/solid/utility/test/test_collapse.cpp @@ -152,6 +152,7 @@ int test_collapse(int argc, char* argv[]) const auto stop_time = chrono::high_resolution_clock::now(); cout << "Duration: " << chrono::duration_cast(stop_time - start_time).count() << "us" << endl; } else if (choice == 'b') { +#if false // TODO: CallPoolT wp{{thread_count, 10000, 100}, [](const size_t) { set_current_thread_affinity(); @@ -183,6 +184,7 @@ int test_collapse(int argc, char* argv[]) } const auto stop_time = chrono::high_resolution_clock::now(); cout << "Duration: " << chrono::duration_cast(stop_time - start_time).count() << "us" << endl; +#endif } else { cout << "Invalid choice. Expected B or p or b. Got [" << choice << "]." << endl; } diff --git a/solid/utility/test/test_shared_buffer.cpp b/solid/utility/test/test_shared_buffer.cpp index 69c40b23a..a2cbf93a5 100644 --- a/solid/utility/test/test_shared_buffer.cpp +++ b/solid/utility/test/test_shared_buffer.cpp @@ -28,6 +28,7 @@ int test_shared_buffer(int argc, char* argv[]) solid_check(sb3); } +#if false // TODO: { MutableSharedBuffer sb = make_mutable_buffer(1000); @@ -134,6 +135,7 @@ int test_shared_buffer(int argc, char* argv[]) solid_check(sb2.capacity() == i); cout << i << " " << sb1.capacity() << " " << sb1.actualCapacity() << " " << sb2.capacity() << " " << sb2.actualCapacity() << endl; } +#endif { SharedBuffer empty_buf; solid_check(empty_buf.capacity() == 0); From 54be9eeff8c23f13ee1e7d831518e5f32e39cba4 Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Mon, 9 Jun 2025 22:49:46 +0300 Subject: [PATCH 04/56] mprpc: fixing issues with moving to ringsharedbuffer --- solid/frame/mprpc/mprpcconfiguration.hpp | 10 +- solid/frame/mprpc/mprpcservice.hpp | 12 +- solid/frame/mprpc/mprpcsocketstub_openssl.hpp | 4 - solid/frame/mprpc/mprpcsocketstub_plain.hpp | 4 - solid/frame/mprpc/src/mprpcconfiguration.cpp | 2 +- solid/frame/mprpc/src/mprpcconnection.cpp | 117 ++++-------------- solid/frame/mprpc/src/mprpcconnection.hpp | 10 +- solid/frame/mprpc/src/mprpcmessagereader.cpp | 3 + solid/frame/mprpc/src/mprpcmessagewriter.cpp | 19 ++- solid/frame/mprpc/src/mprpcrelayengine.cpp | 18 +-- solid/frame/mprpc/src/mprpcservice.cpp | 14 +-- solid/frame/mprpc/test/test_relay_basic.cpp | 3 + solid/utility/sharedbuffer.hpp | 5 +- solid/utility/src/sharedbuffer.cpp | 9 ++ 14 files changed, 82 insertions(+), 148 deletions(-) diff --git a/solid/frame/mprpc/mprpcconfiguration.hpp b/solid/frame/mprpc/mprpcconfiguration.hpp index f7f3a0289..b4b20b7e2 100644 --- a/solid/frame/mprpc/mprpcconfiguration.hpp +++ b/solid/frame/mprpc/mprpcconfiguration.hpp @@ -64,9 +64,7 @@ std::ostream& operator<<(std::ostream& _ros, const RelayDataFlagsT& _flags); struct RelayData { SharedBufferView buffer_; - const char* pdata_ = nullptr; - size_t data_size_ = 0; - RelayData* pnext_ = nullptr; + RelayData* pnext_ = nullptr; RelayDataFlagsT flags_; MessageHeader::FlagsT message_flags_ = 0; MessageHeader* pmessage_header_ = nullptr; @@ -133,9 +131,9 @@ struct RelayData { private: friend class RelayConnection; RelayData( - const SharedBufferView& _buffer, - const bool _is_last) - : buffer_(_buffer) + SharedBufferView&& _buffer, + const bool _is_last) + : buffer_(std::move(_buffer)) { if (_is_last) { flags_.set(RelayDataFlagsE::Last); diff --git a/solid/frame/mprpc/mprpcservice.hpp b/solid/frame/mprpc/mprpcservice.hpp index 4b2e81553..70fd2af39 100644 --- a/solid/frame/mprpc/mprpcservice.hpp +++ b/solid/frame/mprpc/mprpcservice.hpp @@ -9,6 +9,8 @@ // #pragma once +#include +#include #include #include "solid/system/exception.hpp" @@ -98,6 +100,7 @@ struct ServiceStatistic : solid::Statistic { std::atomic connection_send_posted_; std::atomic max_fetch_size_; std::atomic min_fetch_size_; + std::atomic_uint64_t max_optimize_duration_us_{0}; void fetchCount(const uint64_t _count, const bool _more) { @@ -164,6 +167,11 @@ struct ServiceStatistic : solid::Statistic { #endif } + void optimizeDuration(std::chrono::microseconds _us) + { + solid_statistic_max(max_optimize_duration_us_, static_cast(_us.count())); + } + ServiceStatistic(); std::ostream& print(std::ostream& _ros) const override; }; @@ -190,7 +198,7 @@ class RecipientUrl final { return false; } - bool hasURLNonEmpty() const + [[nodiscard]] bool hasURLNonEmpty() const { if (url_var_opt_.has_value()) { if (auto* psv = std::get_if(&url_var_opt_.value())) { @@ -200,7 +208,7 @@ class RecipientUrl final { return false; } - std::string_view url() const + [[nodiscard]] std::string_view url() const { if (url_var_opt_.has_value()) { if (auto* psv = std::get_if(&url_var_opt_.value())) { diff --git a/solid/frame/mprpc/mprpcsocketstub_openssl.hpp b/solid/frame/mprpc/mprpcsocketstub_openssl.hpp index f3a9959f4..105a6c088 100644 --- a/solid/frame/mprpc/mprpcsocketstub_openssl.hpp +++ b/solid/frame/mprpc/mprpcsocketstub_openssl.hpp @@ -113,8 +113,6 @@ class SocketStub final : public mprpc::SocketStub { } lambda(_pf, _revent); - // TODO: find solution for costly event copy - return sock.postSendAll(_rctx, _pbuf, _bufcp, lambda); } @@ -144,8 +142,6 @@ class SocketStub final : public mprpc::SocketStub { } lambda(_pf, _revent); - // TODO: find solution for costly event copy - return sock.postRecvSome(_rctx, _pbuf, _bufcp, lambda); } diff --git a/solid/frame/mprpc/mprpcsocketstub_plain.hpp b/solid/frame/mprpc/mprpcsocketstub_plain.hpp index 02d599a4c..a6cdd881e 100644 --- a/solid/frame/mprpc/mprpcsocketstub_plain.hpp +++ b/solid/frame/mprpc/mprpcsocketstub_plain.hpp @@ -69,8 +69,6 @@ class SocketStub final : public mprpc::SocketStub { } lambda(_pf, _revent); - // TODO: find solution for costly event copy - return sock.postSendAll(_rctx, _pbuf, _bufcp, lambda); } @@ -100,8 +98,6 @@ class SocketStub final : public mprpc::SocketStub { } lambda(_pf, _revent); - // TODO: find solution for costly event copy - return sock.postRecvSome(_rctx, _pbuf, _bufcp, lambda); } diff --git a/solid/frame/mprpc/src/mprpcconfiguration.cpp b/solid/frame/mprpc/src/mprpcconfiguration.cpp index 8d7040c8d..656f3e362 100644 --- a/solid/frame/mprpc/src/mprpcconfiguration.cpp +++ b/solid/frame/mprpc/src/mprpcconfiguration.cpp @@ -47,7 +47,7 @@ MutableSharedBuffer default_allocate_recv_buffer(const uint32_t _cp) MutableSharedBuffer default_allocate_send_buffer(const uint32_t _cp) { - return make_mutable_buffer(_cp); + return BufferManager::makeMutable(_cp); } // void empty_reset_serializer_limits(ConnectionContext &, serialization::binary::Limits&){} diff --git a/solid/frame/mprpc/src/mprpcconnection.cpp b/solid/frame/mprpc/src/mprpcconnection.cpp index 94d3436de..4eb43bbcb 100644 --- a/solid/frame/mprpc/src/mprpcconnection.cpp +++ b/solid/frame/mprpc/src/mprpcconnection.cpp @@ -15,8 +15,11 @@ #include "solid/frame/mprpc/mprpcservice.hpp" #include "solid/utility/event.hpp" #include +#include #include +#include #include +#include namespace solid::frame::mprpc { namespace { @@ -238,25 +241,12 @@ inline void Connection::doOptimizeRecvBuffer() { if (recv_buf_.cempty()) [[likely]] { recv_buf_.optimize(); - } else if ((recv_buf_.csize() + recv_buf_.msize()) < PacketHeader::max_size) { + } else if ((recv_buf_.csize() + recv_buf_.msize()) < Protocol::max_packet_size) { // not enough space in the recv_buf for a packet. - solid_log(logger, Warning, this << " optimizing - " << recv_buf_.csize() << " " << recv_buf_.msize()); + // solid_log(logger, Warning, this << " optimizing - " << recv_buf_.csize() << " " << recv_buf_.msize()); recv_buf_.optimize(); } assert(recv_buf_.msize()); -#if 0 // TODO: remove - const size_t remaining_size = recv_buf_.size() - cons_buf_off_; - if (remaining_size <= cons_buf_off_) { - memcpy(recv_buf_.data(), recv_buf_.data() + cons_buf_off_, remaining_size); - cons_buf_off_ = 0; - recv_buf_.resize(remaining_size); - } -#endif -} -//----------------------------------------------------------------------------- -inline void Connection::doOptimizeRecvBufferForced() -{ - recv_buf_.optimize(); } //----------------------------------------------------------------------------- Connection::Connection( @@ -1094,19 +1084,11 @@ void Connection::doHandleEventRecvRaw(frame::aio::ReactorContext& _rctx, EventBa consume_size = std::min(consume_size, recv_buf_.csize()); - // cons_buf_off_ += used_size;//TODO: remove recv_buf_.consume(consume_size); + if (recv_buf_.cempty()) { recv_buf_.optimize(); } -#if 0 // TODO: - if (cons_buf_off_ == recv_buf_.size()) { - cons_buf_off_ = 0; - recv_buf_.resize(0); - } else { - solid_assert_log(cons_buf_off_ < recv_buf_.size(), logger); - } -#endif } } else if (pdata != nullptr) { @@ -1263,6 +1245,8 @@ void Connection::doResetRecvBuffer(frame::aio::ReactorContext& _rctx, const uint } else { recv_buf_.reset(); _rerr = error_connection_too_many_recv_buffers; + solid_log(logger, Warning, this << " used all recv buffers"); + assert(false); return; } memcpy(new_buf.mdata(), recv_buf_.cdata(), recv_buf_.csize()); @@ -1281,43 +1265,6 @@ void Connection::doResetRecvBuffer(frame::aio::ReactorContext& _rctx, const uint ackd_buf_count_ += _request_buffer_ack_count; } } -#if 0 // TODO: remove - if (_request_buffer_ack_count == 0) { - - } else if (recv_buf_.useCount() > 1) { - solid_log(logger, Verbose, this << " buffer used for relay - try replace it. vec_size = " << recv_buf_vec_.size() << " count = " << recv_buf_count_); - SharedBuffer new_buf; - if (!recv_buf_vec_.empty()) { - new_buf = std::move(recv_buf_vec_.back()); - recv_buf_vec_.pop_back(); - } else if (recv_buf_count_ < service(_rctx).configuration().connection_relay_buffer_count) { - new_buf = service(_rctx).configuration().allocateRecvBuffer(); - } else { - recv_buf_.reset(); - _rerr = error_connection_too_many_recv_buffers; - cons_buf_off_ = 0; - return; - } - const size_t cnssz = recv_buf_.size() - cons_buf_off_; - - memcpy(new_buf.data(), recv_buf_.data() + cons_buf_off_, cnssz); - cons_buf_off_ = 0; - new_buf.resize(cnssz); - recv_buf_ = std::move(new_buf); - } else { - // tried to relay received messages/message parts - but all failed - // so we need to ack the buffer - solid_assert_log(recv_buf_.useCount(), logger); - solid_log(logger, Info, this << " send accept for " << (int)_request_buffer_ack_count << " buffers"); - - if (ackd_buf_count_ == 0) { - ackd_buf_count_ += _request_buffer_ack_count; - this->post(_rctx, [this](frame::aio::ReactorContext& _rctx, EventBase const& /*_revent*/) { this->doSend(_rctx); }); - } else { - ackd_buf_count_ += _request_buffer_ack_count; - } - } -#endif } //----------------------------------------------------------------------------- template @@ -1391,15 +1338,11 @@ struct ConnectionReceiver : MessageReaderReceiver { template /*static*/ void Connection::onRecv(frame::aio::ReactorContext& _rctx, size_t _sz) { - Connection& rthis = static_cast(_rctx.actor()); - ConnectionContext conctx(_rctx, rthis.service(_rctx), rthis); - const Configuration& rconfig = rthis.service(_rctx).configuration(); - unsigned repeatcnt = 4; - // TODO: remove - // char* pbuf = nullptr; - // size_t bufsz = 0; - // const uint32_t recvbufcp = rthis.recv_buf_.capacity(); - auto& rrecvbuf = rthis.recv_buf_; + Connection& rthis = static_cast(_rctx.actor()); + ConnectionContext conctx(_rctx, rthis.service(_rctx), rthis); + const Configuration& rconfig = rthis.service(_rctx).configuration(); + unsigned repeatcnt = 4; + auto& rrecvbuf = rthis.recv_buf_; typename Ctx::ReceiverT rcvr(rthis, _rctx, rconfig.reader, rconfig.protocol(), conctx); ErrorConditionT error; @@ -1409,14 +1352,11 @@ template if (!_rctx.error()) { rrecvbuf.append(_sz); - // TODO: remove - // pbuf = rthis.recv_buf_.data() + rthis.cons_buf_off_; - // bufsz = rthis.recv_buf_.size() - rthis.cons_buf_off_;//rrecvbuf.csize() rcvr.request_buffer_ack_count_ = 0; auto const consumed_size = rthis.msg_reader_.read(rrecvbuf.cdata(), rrecvbuf.csize(), rcvr, error); - // rthis.cons_buf_off_ += consumed_size;//TODO:remove + rrecvbuf.consume(consumed_size); solid_log(logger, Verbose, &rthis << " consumed size " << consumed_size << " remaining " << rrecvbuf.csize()); @@ -1428,13 +1368,6 @@ template rthis.doStop(_rctx, error); return; } - - // if (rthis.cons_buf_off_ < bufsz) {//TODO: remove -#if 0 // TODO - if () { - rthis.doOptimizeRecvBufferForced(); - } -#endif } else { solid_log(logger, Info, &rthis << ' ' << rthis.id() << " receiving " << _rctx.error().message()); rthis.flags_.set(FlagsE::StopPeer); @@ -1443,12 +1376,14 @@ template } --repeatcnt; + auto t_start = std::chrono::high_resolution_clock::now(); rthis.doOptimizeRecvBuffer(); - assert(rrecvbuf.msize()); - // TODO: remove - // pbuf = rthis.recv_buf_.data() + rthis.recv_buf_.size(); - // bufsz = recvbufcp - rthis.recv_buf_.size(); - // solid_log(logger, Info, &rthis<<" buffer size "<(std::chrono::high_resolution_clock::now() - t_start); + rthis.service(_rctx) + .wstatistic() + .optimizeDuration(duration); + solid_check(rrecvbuf.msize()); + } while (repeatcnt != 0U && !rthis.flags_.isSet(FlagsE::PauseRecv) && rthis.recvSome(_rctx, rrecvbuf.mdata(), rrecvbuf.msize(), _sz)); if (rconfig.hasConnectionTimeoutRecv()) { @@ -1896,10 +1831,6 @@ void Connection::doResumeRead(frame::aio::ReactorContext& _rctx) if (flags_.isSet(FlagsE::PauseRecv)) { flags_.reset(FlagsE::PauseRecv); - // TODO: remove - // const auto pbuf = recv_buf_.data() + recv_buf_.size(); - // const auto bufsz = recv_buf_.capacity() - recv_buf_.size(); - const bool rv = postRecvSome(_rctx, recv_buf_.mdata(), recv_buf_.msize()); // fully asynchronous call solid_assert_log(!rv, logger); @@ -2373,6 +2304,7 @@ bool RelayConnection::doReceiveRelayStart( Configuration const& config = configuration(_rctx); ConnectionContext conctx{_rctx, service(_rctx), *this}; RelayData relmsg{recvBufferView(_pbeg, _sz), _is_last}; + assert(relmsg.buffer_.cdata() == _pbeg and relmsg.buffer_.csize() == _sz); return config.relayEngine().relayStart(uid(_rctx), relayId(), _rmsghdr, std::move(relmsg), _rrelay_id, _rerror); } @@ -2388,6 +2320,7 @@ bool RelayConnection::doReceiveRelayBody( Configuration const& config = configuration(_rctx); ConnectionContext conctx{_rctx, service(_rctx), *this}; RelayData relmsg{recvBufferView(_pbeg, _sz), _is_last}; + assert(relmsg.buffer_.cdata() == _pbeg and relmsg.buffer_.csize() == _sz); return config.relayEngine().relay(relayId(), std::move(relmsg), _rrelay_id, _rerror); } @@ -2404,6 +2337,7 @@ bool RelayConnection::doReceiveRelayResponse( Configuration const& config = configuration(_rctx); ConnectionContext conctx{_rctx, service(_rctx), *this}; RelayData relmsg{recvBufferView(_pbeg, _sz), _is_last}; + assert(relmsg.buffer_.cdata() == _pbeg and relmsg.buffer_.csize() == _sz); return config.relayEngine().relayResponse(relayId(), _rmsghdr, std::move(relmsg), _rrelay_id, _rerror); } @@ -2430,6 +2364,9 @@ void RelayConnection::doHandleEventRelayDone(frame::aio::ReactorContext& _rctx, size_t ack_buf_cnt = 0; const auto done_lambda = [this, &ack_buf_cnt](SharedBufferView& _rbuf) { + if (_rbuf.useCount() == 1) { + solid_log(logger, Info, this << " returnRecvBuffer " << _rbuf.useCount()); + } if (returnRecvBuffer(std::move(_rbuf))) { ++ack_buf_cnt; } diff --git a/solid/frame/mprpc/src/mprpcconnection.hpp b/solid/frame/mprpc/src/mprpcconnection.hpp index 3e7a74780..3ed96dfa1 100644 --- a/solid/frame/mprpc/src/mprpcconnection.hpp +++ b/solid/frame/mprpc/src/mprpcconnection.hpp @@ -312,7 +312,6 @@ class Connection : public frame::aio::Actor { EventBase& _revent); void doOptimizeRecvBuffer(); - void doOptimizeRecvBufferForced(); void doPrepare(frame::aio::ReactorContext& _rctx); void doUnprepare(frame::aio::ReactorContext& _rctx); template @@ -354,11 +353,10 @@ class Connection : public frame::aio::Actor { template friend struct ConnectionSenderResponse; - ConnectionPoolId pool_id_; - const std::string& rpool_name_; - TimerT timer_; - FlagsT flags_ = 0; - // size_t cons_buf_off_ = 0;//TODO:delete + ConnectionPoolId pool_id_; + const std::string& rpool_name_; + TimerT timer_; + FlagsT flags_ = 0; uint32_t recv_keepalive_count_ = 0; std::chrono::steady_clock::time_point recv_keepalive_boundary_ = std::chrono::steady_clock::time_point::min(); uint16_t recv_buf_count_ = 0; diff --git a/solid/frame/mprpc/src/mprpcmessagereader.cpp b/solid/frame/mprpc/src/mprpcmessagereader.cpp index 2c845c44c..1f4c1fc33 100644 --- a/solid/frame/mprpc/src/mprpcmessagereader.cpp +++ b/solid/frame/mprpc/src/mprpcmessagereader.cpp @@ -17,6 +17,8 @@ #include "solid/system/exception.hpp" #include "solid/system/log.hpp" +#include + namespace solid { namespace frame { namespace mprpc { @@ -61,6 +63,7 @@ size_t MessageReader::read( // try read the data const char* tmpbufpos = packet_header.load(pbufpos, _receiver.protocol()); if (!packet_header.isOk()) { + assert(false); _rerror = error_reader_invalid_packet_header; solid_log(logger, Error, _rerror.message()); break; diff --git a/solid/frame/mprpc/src/mprpcmessagewriter.cpp b/solid/frame/mprpc/src/mprpcmessagewriter.cpp index 03bdc1ba8..5adaf92ae 100644 --- a/solid/frame/mprpc/src/mprpcmessagewriter.cpp +++ b/solid/frame/mprpc/src/mprpcmessagewriter.cpp @@ -16,9 +16,7 @@ #include "solid/system/cassert.hpp" #include "solid/system/log.hpp" -namespace solid { -namespace frame { -namespace mprpc { +namespace solid::frame::mprpc { namespace { const LoggerT logger("solid::frame::mprpc::writer"); } @@ -192,8 +190,7 @@ bool MessageWriter::enqueue( MessageStub& rmsgstub(message_vec_[msgidx]); - if (_rprelay_data->pdata_ != nullptr) { - + if (_rprelay_data->buffer_) { solid_log(logger, Verbose, this << " " << msgidx << " relay_data.flags " << _rprelay_data->flags_ << ' ' << MessageWriterPrintPairT(*this, PrintInnerListsE)); if (_rprelay_data->isMessageBegin()) { @@ -202,8 +199,8 @@ bool MessageWriter::enqueue( } rmsgstub.prelay_data_ = _rprelay_data; - rmsgstub.prelay_pos_ = rmsgstub.prelay_data_->pdata_; - rmsgstub.relay_size_ = rmsgstub.prelay_data_->data_size_; + rmsgstub.prelay_pos_ = rmsgstub.prelay_data_->buffer_.cdata(); + rmsgstub.relay_size_ = rmsgstub.prelay_data_->buffer_.csize(); rmsgstub.pool_msg_id_ = _rengine_msg_id; _rprelay_data = nullptr; @@ -452,9 +449,9 @@ ErrorConditionT MessageWriter::write( more = false; // do not allow multiple packets per relay buffer } - solid_assert_log(static_cast(fillsz) <= static_cast(PacketHeader::max_size), logger); + solid_assert_log(fillsz <= static_cast(PacketHeader::max_size), logger); - packet_header.size(static_cast(fillsz)); + packet_header.size(static_cast(fillsz)); pbufpos = packet_header.store(pbufpos, _rsender.protocol()); pbufpos = pbufdata + fillsz; @@ -1128,6 +1125,4 @@ std::ostream& operator<<(std::ostream& _ros, std::pair { pback_->pnext_ = nullptr; } pback_->pmessage_header_ = &header_; - solid_log(logger, Verbose, "pushed relay_data " << pback_ << " size = " << pback_->data_size_ << " is_begin = " << pback_->isMessageBegin() << " is_end = " << pback_->isMessageEnd() << " is_last = " << pback_->isMessageLast()); + solid_log(logger, Verbose, "pushed relay_data " << pback_ << " size = " << pback_->buffer_.csize() << " is_begin = " << pback_->isMessageBegin() << " is_end = " << pback_->isMessageEnd() << " is_last = " << pback_->isMessageLast()); } RelayData* pop() @@ -550,7 +547,7 @@ bool EngineCore::doRelayStart( _rrelmsg.flags_.set(RelayDataFlagsE::First); _rrelmsg.message_flags_ = rmsg.header_.flags_; - solid_log(logger, Info, _rrelay_con_uid << " msgid = " << _rrelay_id << " size = " << _rrelmsg.data_size_ << " receiver_conidx " << rmsg.receiver_con_id_.index << " sender_conidx " << rmsg.sender_con_id_.index << " flags = " << _rrelmsg.flags_); + solid_log(logger, Info, _rrelay_con_uid << " msgid = " << _rrelay_id << " size = " << _rrelmsg.buffer_.csize() << " receiver_conidx " << rmsg.receiver_con_id_.index << " sender_conidx " << rmsg.sender_con_id_.index << " flags = " << _rrelmsg.flags_); solid_assert_log(rmsg.pfront_ == nullptr, logger); @@ -584,7 +581,7 @@ bool EngineCore::doRelay( const size_t msgidx = _rrelay_id.index; MessageStub& rmsg = impl_->msg_dq_[msgidx]; const bool is_msg_relay_data_queue_empty = (rmsg.pfront_ == nullptr); - size_t data_size = _rrelmsg.data_size_; + size_t data_size = _rrelmsg.buffer_.csize(); auto flags = rmsg.last_message_flags_; _rrelmsg.message_flags_ = rmsg.last_message_flags_; @@ -695,7 +692,7 @@ bool EngineCore::doRelayResponse( } } else if (rmsg.state_ == MessageStateE::Relay || rmsg.state_ == MessageStateE::WaitResponsePart) { const bool is_msg_relay_data_queue_empty = (rmsg.pfront_ == nullptr); - size_t data_size = _rrelmsg.data_size_; + size_t data_size = _rrelmsg.buffer_.csize(); rmsg.state_ = MessageStateE::Relay; @@ -1129,7 +1126,4 @@ void EngineCore::Proxy::registerConnectionId(const ConnectionContext& _rconctx, re_.doRegisterConnectionId(_rconctx, _idx); } //----------------------------------------------------------------------------- -} // namespace relay -} // namespace mprpc -} // namespace frame -} // namespace solid +} // namespace solid::frame::mprpc::relay diff --git a/solid/frame/mprpc/src/mprpcservice.cpp b/solid/frame/mprpc/src/mprpcservice.cpp index 4f629c7e6..32dc1b5e3 100644 --- a/solid/frame/mprpc/src/mprpcservice.cpp +++ b/solid/frame/mprpc/src/mprpcservice.cpp @@ -46,9 +46,7 @@ using namespace std; -namespace solid { -namespace frame { -namespace mprpc { +namespace solid::frame::mprpc { namespace { const LoggerT logger("solid::frame::mprpc::service"); @@ -636,8 +634,7 @@ struct Service::Data { NameMapT name_map_; ConnectionPoolDequeT pool_dq_; ConnectionPoolInnerListT pool_free_list_; - // std::string tmp_str_; - ServiceStatistic statistic_; + ServiceStatistic statistic_; Data(Service& _rsvc, Configuration&& _config) : rmutex_(_rsvc.mutex()) @@ -2196,7 +2193,7 @@ bool Service::Data::doMainConnectionStoppingCleanAll( solid_log(logger, Verbose, this << " pool " << pool_index << " set closing"); } - return true; // TODO: maybe we should return false + return true; } return false; } @@ -2844,9 +2841,8 @@ std::ostream& ServiceStatistic::print(std::ostream& _ros) const _ros << " 70:" << poll_pool_fetch_count_70_ << " 80:" << poll_pool_fetch_count_80_ << ']'; _ros << " max_fetch = " << max_fetch_size_; _ros << " min_fetch = " << min_fetch_size_; + _ros << " max_optimize_duration_us_ = " << max_optimize_duration_us_; return _ros; } //============================================================================= -} // namespace mprpc -} // namespace frame -} // namespace solid +} // namespace solid::frame::mprpc diff --git a/solid/frame/mprpc/test/test_relay_basic.cpp b/solid/frame/mprpc/test/test_relay_basic.cpp index ba04ef15f..eee641662 100644 --- a/solid/frame/mprpc/test/test_relay_basic.cpp +++ b/solid/frame/mprpc/test/test_relay_basic.cpp @@ -573,6 +573,9 @@ int test_relay_basic(int argc, char* argv[]) solid_throw("Not all messages were completed"); } + cout << " mprpcrelay statistics: " << mprpcrelay.statistic() << endl; + cout << " mprpcpeera statistics: " << mprpcpeera.statistic() << endl; + cout << " mprpcpeerb statistics: " << mprpcpeerb.statistic() << endl; // m.stop(); } diff --git a/solid/utility/sharedbuffer.hpp b/solid/utility/sharedbuffer.hpp index 7733b0701..2298ded6e 100644 --- a/solid/utility/sharedbuffer.hpp +++ b/solid/utility/sharedbuffer.hpp @@ -44,6 +44,7 @@ struct SharedBufferData { } char* release(size_t& _previous_use_count); + char* collapse(size_t& _previous_use_count); char* data() { @@ -539,7 +540,7 @@ class ConstSharedBuffer : public impl::SharedBufferBase { { if (*this) { size_t previous_use_count = 0; - auto* buf = pdata_->release(previous_use_count); + auto* buf = pdata_->collapse(previous_use_count); if (buf) { pdata_->acquire(); pdata_->size_ = 0; @@ -597,7 +598,7 @@ inline MutableSharedBuffer SharedBufferView::collapse() { if (*this) { size_t previous_use_count = 0; - auto* buf = pdata_->release(previous_use_count); + auto* buf = pdata_->collapse(previous_use_count); if (buf) { pdata_->acquire(); pdata_->size_ = 0; diff --git a/solid/utility/src/sharedbuffer.cpp b/solid/utility/src/sharedbuffer.cpp index 5a082d938..accbceaf2 100644 --- a/solid/utility/src/sharedbuffer.cpp +++ b/solid/utility/src/sharedbuffer.cpp @@ -37,6 +37,15 @@ char* SharedBufferData::release(size_t& _previous_use_count) return nullptr; } +char* SharedBufferData::collapse(size_t& _previous_use_count) +{ + _previous_use_count = use_count_.fetch_sub(1); + if (_previous_use_count == 1) { + return buffer_; + } + return nullptr; +} + /* static */ SharedBufferData* SharedBufferBase::allocate_data(const std::size_t _cap) { const std::size_t new_cap = compute_capacity(_cap); From eaee2ec610c390b004c3ddd0b2ace224df5871ff Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Sat, 14 Jun 2025 12:26:58 +0300 Subject: [PATCH 05/56] mprpc: small improvements on connection mprpc socket relate --- solid/frame/mprpc/mprpcconfiguration.hpp | 5 ++-- solid/frame/mprpc/mprpcsocketstub_openssl.hpp | 23 +++++++++--------- solid/frame/mprpc/mprpcsocketstub_plain.hpp | 24 ++++++++++--------- solid/frame/mprpc/src/mprpcconfiguration.cpp | 6 ++--- solid/frame/mprpc/src/mprpcconnection.hpp | 18 +++++++------- solid/utility/sharedbuffer.hpp | 3 ++- 6 files changed, 41 insertions(+), 38 deletions(-) diff --git a/solid/frame/mprpc/mprpcconfiguration.hpp b/solid/frame/mprpc/mprpcconfiguration.hpp index b4b20b7e2..f56ada061 100644 --- a/solid/frame/mprpc/mprpcconfiguration.hpp +++ b/solid/frame/mprpc/mprpcconfiguration.hpp @@ -39,9 +39,8 @@ struct ActorProxy; namespace mprpc { -enum struct ConnectionValues : size_t { - SocketEmplacementSize = 128 -}; +constexpr size_t socket_emplace_size = 512; +constexpr size_t socket_emplace_align = 16; class Service; class Connection; diff --git a/solid/frame/mprpc/mprpcsocketstub_openssl.hpp b/solid/frame/mprpc/mprpcsocketstub_openssl.hpp index 105a6c088..51f7d9acd 100644 --- a/solid/frame/mprpc/mprpcsocketstub_openssl.hpp +++ b/solid/frame/mprpc/mprpcsocketstub_openssl.hpp @@ -28,10 +28,7 @@ #include "solid/frame/mprpc/mprpcservice.hpp" -namespace solid { -namespace frame { -namespace mprpc { -namespace openssl { +namespace solid::frame::mprpc::openssl { using ContextT = frame::aio::openssl::Context; using StreamSocketT = frame::aio::Stream; @@ -240,8 +237,11 @@ class SocketStub final : public mprpc::SocketStub { inline SocketStubPtrT create_client_socket(mprpc::Configuration const& _rcfg, frame::aio::ActorProxy const& _rproxy, char* _emplace_buf) { - - if (sizeof(SocketStub) > static_cast(ConnectionValues::SocketEmplacementSize)) { +#ifdef SOLID_HAS_ASSERT + static_assert(sizeof(SocketStub) <= socket_emplace_size); + static_assert(alignof(SocketStub) == socket_emplace_align); +#endif + if constexpr (sizeof(SocketStub) > socket_emplace_size and alignof(SocketStub) > socket_emplace_align) { return SocketStubPtrT(new SocketStub(_rproxy, const_cast(_rcfg.client.secure_any.cast())->context), SocketStub::delete_deleter); } else { return SocketStubPtrT(new (_emplace_buf) SocketStub(_rproxy, const_cast(_rcfg.client.secure_any.cast())->context), SocketStub::emplace_deleter); @@ -250,8 +250,12 @@ inline SocketStubPtrT create_client_socket(mprpc::Configuration const& _rcfg, fr inline SocketStubPtrT create_server_socket(mprpc::Configuration const& _rcfg, frame::aio::ActorProxy const& _rproxy, SocketDevice&& _usd, char* _emplace_buf) { +#ifdef SOLID_HAS_ASSERT + static_assert(sizeof(SocketStub) <= socket_emplace_size); + static_assert(alignof(SocketStub) == socket_emplace_align); +#endif - if (sizeof(SocketStub) > static_cast(ConnectionValues::SocketEmplacementSize)) { + if constexpr (sizeof(SocketStub) > socket_emplace_size and alignof(SocketStub) > socket_emplace_align) { return SocketStubPtrT(new SocketStub(_rproxy, std::move(_usd), const_cast(_rcfg.server.secure_any.cast())->context), SocketStub::delete_deleter); } else { return SocketStubPtrT(new (_emplace_buf) SocketStub(_rproxy, std::move(_usd), const_cast(_rcfg.server.secure_any.cast())->context), SocketStub::emplace_deleter); @@ -358,7 +362,4 @@ inline void setup_server( rsecure_cfg.connection_verify_fnc = std::move(_verify_fnc); } -} // namespace openssl -} // namespace mprpc -} // namespace frame -} // namespace solid +} // namespace solid::frame::mprpc::openssl diff --git a/solid/frame/mprpc/mprpcsocketstub_plain.hpp b/solid/frame/mprpc/mprpcsocketstub_plain.hpp index a6cdd881e..69aae976d 100644 --- a/solid/frame/mprpc/mprpcsocketstub_plain.hpp +++ b/solid/frame/mprpc/mprpcsocketstub_plain.hpp @@ -10,6 +10,7 @@ #pragma once +#include "solid/frame/mprpc/mprpcconfiguration.hpp" #include "solid/system/socketdevice.hpp" #include "solid/utility/event.hpp" @@ -18,10 +19,7 @@ #include "solid/frame/aio/aiostream.hpp" #include "solid/frame/mprpc/mprpcsocketstub.hpp" -namespace solid { -namespace frame { -namespace mprpc { -namespace plain { +namespace solid::frame::mprpc::plain { class SocketStub final : public mprpc::SocketStub { public: @@ -147,7 +145,11 @@ class SocketStub final : public mprpc::SocketStub { inline SocketStubPtrT create_client_socket(Configuration const& /*_rcfg*/, frame::aio::ActorProxy const& _rproxy, char* _emplace_buf) { - if (sizeof(SocketStub) > static_cast(ConnectionValues::SocketEmplacementSize)) { +#ifdef SOLID_HAS_ASSERT + static_assert(sizeof(SocketStub) <= socket_emplace_size); + static_assert(alignof(SocketStub) == socket_emplace_align); +#endif + if constexpr (sizeof(SocketStub) > socket_emplace_size and alignof(SocketStub) > socket_emplace_align) { return SocketStubPtrT(new SocketStub(_rproxy), SocketStub::delete_deleter); } else { return SocketStubPtrT(new (_emplace_buf) SocketStub(_rproxy), SocketStub::emplace_deleter); @@ -156,15 +158,15 @@ inline SocketStubPtrT create_client_socket(Configuration const& /*_rcfg*/, frame inline SocketStubPtrT create_server_socket(Configuration const& /*_rcfg*/, frame::aio::ActorProxy const& _rproxy, SocketDevice&& _usd, char* _emplace_buf) { - - if (sizeof(SocketStub) > static_cast(ConnectionValues::SocketEmplacementSize)) { +#ifdef SOLID_HAS_ASSERT + static_assert(sizeof(SocketStub) <= socket_emplace_size); + static_assert(alignof(SocketStub) == socket_emplace_align); +#endif + if constexpr (sizeof(SocketStub) > socket_emplace_size and alignof(SocketStub) > socket_emplace_align) { return SocketStubPtrT(new SocketStub(_rproxy, std::move(_usd)), SocketStub::delete_deleter); } else { return SocketStubPtrT(new (_emplace_buf) SocketStub(_rproxy, std::move(_usd)), SocketStub::emplace_deleter); } } -} // namespace plain -} // namespace mprpc -} // namespace frame -} // namespace solid +} // namespace solid::frame::mprpc::plain diff --git a/solid/frame/mprpc/src/mprpcconfiguration.cpp b/solid/frame/mprpc/src/mprpcconfiguration.cpp index 656f3e362..717e9e3ee 100644 --- a/solid/frame/mprpc/src/mprpcconfiguration.cpp +++ b/solid/frame/mprpc/src/mprpcconfiguration.cpp @@ -42,12 +42,12 @@ std::ostream& operator<<(std::ostream& _ros, const RelayDataFlagsT& _flags) namespace { MutableSharedBuffer default_allocate_recv_buffer(const uint32_t _cp) { - return BufferManager::makeMutable(_cp); + return BufferManager::make_mutable(_cp); } MutableSharedBuffer default_allocate_send_buffer(const uint32_t _cp) { - return BufferManager::makeMutable(_cp); + return BufferManager::make_mutable(_cp); } // void empty_reset_serializer_limits(ConnectionContext &, serialization::binary::Limits&){} @@ -345,7 +345,7 @@ void Configuration::createListenerDevice(SocketDevice& _rsd) const } constexpr size_t send_buffer_capacity = Protocol::max_packet_size; -constexpr size_t recv_buffer_capacity = send_buffer_capacity * 2; +constexpr size_t recv_buffer_capacity = send_buffer_capacity * 2 + 64; //----------------------------------------------------------------------------- MutableSharedBuffer Configuration::allocateRecvBuffer() const diff --git a/solid/frame/mprpc/src/mprpcconnection.hpp b/solid/frame/mprpc/src/mprpcconnection.hpp index 3ed96dfa1..e2552e95d 100644 --- a/solid/frame/mprpc/src/mprpcconnection.hpp +++ b/solid/frame/mprpc/src/mprpcconnection.hpp @@ -374,15 +374,15 @@ class Connection : public frame::aio::Actor { bool poll_pool_more_ = true; bool send_posted_ = false; Any<> any_data_; - char socket_emplace_buf_[static_cast(ConnectionValues::SocketEmplacementSize)] = {}; - SocketStubPtrT sock_ptr_; - NanoTime timeout_recv_ = NanoTime::max(); // client and server - NanoTime timeout_send_soft_ = NanoTime::max(); // client and server - NanoTime timeout_send_hard_ = NanoTime::max(); // client and server - NanoTime timeout_secure_ = NanoTime::max(); // server - NanoTime timeout_active_ = NanoTime::max(); // server - NanoTime timeout_keepalive_ = NanoTime::max(); // client - UniqueId relay_id_; + alignas(socket_emplace_align) char socket_emplace_buf_[socket_emplace_size] = {}; + SocketStubPtrT sock_ptr_; + NanoTime timeout_recv_ = NanoTime::max(); // client and server + NanoTime timeout_send_soft_ = NanoTime::max(); // client and server + NanoTime timeout_send_hard_ = NanoTime::max(); // client and server + NanoTime timeout_secure_ = NanoTime::max(); // server + NanoTime timeout_active_ = NanoTime::max(); // server + NanoTime timeout_keepalive_ = NanoTime::max(); // client + UniqueId relay_id_; }; //----------------------------------------------------------------------------- diff --git a/solid/utility/sharedbuffer.hpp b/solid/utility/sharedbuffer.hpp index 2298ded6e..df9e116b2 100644 --- a/solid/utility/sharedbuffer.hpp +++ b/solid/utility/sharedbuffer.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -656,7 +657,7 @@ class BufferManager : NonCopyable { return SharedBuffer{_cap, std::this_thread::get_id()}; } - static MutableSharedBuffer makeMutable(const size_t _cap) + static MutableSharedBuffer make_mutable(const size_t _cap) { return MutableSharedBuffer{make(_cap)}; } From 626b5c9fcdcb84aed1ae4dcc96b653c36c7eb2d3 Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Tue, 19 Aug 2025 09:00:46 +0300 Subject: [PATCH 06/56] some cleanup and keep working on sharedbuffer pool --- CMakeLists.txt | 2 +- .../mprpc/mprpcprotocol_serialization_v3.hpp | 17 +- solid/frame/mprpc/src/mprpcconfiguration.cpp | 4 +- .../alpha/client/alphaclient.cpp | 2 +- .../alpha/server/alphaserver.hpp | 2 +- .../beta/client/betaclient.cpp | 2 +- .../beta/server/betaserver.hpp | 2 +- .../gamma/client/gammaclient.cpp | 2 +- .../gamma/server/gammaserver.hpp | 2 +- .../test/test_clientserver_versioning.cpp | 10 +- solid/reflection/v1/metadata.hpp | 8 +- solid/utility/sharedbuffer.hpp | 135 +++++- solid/utility/src/sharedbuffer.cpp | 418 +++++++++++++++++- solid/utility/test/test_shared_buffer.cpp | 15 +- solid/utility/threadpool.hpp | 35 +- tutorials/mprpc_echo/mprpc_echo_client.cpp | 2 +- .../mprpc_echo/mprpc_echo_client_pool.cpp | 2 +- tutorials/mprpc_echo/mprpc_echo_server.cpp | 2 +- tutorials/mprpc_file/mprpc_file_client.cpp | 2 +- tutorials/mprpc_file/mprpc_file_server.cpp | 2 +- .../mprpc_request/mprpc_request_client.cpp | 2 +- .../mprpc_request/mprpc_request_server.cpp | 2 +- .../mprpc_request_client.cpp | 2 +- .../mprpc_request_server.cpp | 2 +- 24 files changed, 575 insertions(+), 99 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f0183a30..7485b1fb8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,7 +64,7 @@ message("Install directory: \"${CMAKE_INSTALL_PREFIX}\"") message("External directory: \"${EXTERNAL_DIR}\"") message("Fortify: \"${FORTIFY}\"") -list(APPEND CMAKE_PREFIX_PATH ${EXTERNAL_PATH}) +list(APPEND CMAKE_PREFIX_PATH ${EXTERNAL_DIR}) #----------------------------------------------------------------- # Prepare the definitions for build types diff --git a/solid/frame/mprpc/mprpcprotocol_serialization_v3.hpp b/solid/frame/mprpc/mprpcprotocol_serialization_v3.hpp index a1a52a0d2..ea8fad5ea 100644 --- a/solid/frame/mprpc/mprpcprotocol_serialization_v3.hpp +++ b/solid/frame/mprpc/mprpcprotocol_serialization_v3.hpp @@ -20,10 +20,7 @@ #include "solid/serialization/v3/serialization.hpp" #include "solid/system/error.hpp" -namespace solid { -namespace frame { -namespace mprpc { -namespace serialization_v3 { +namespace solid::frame::mprpc::serialization_v3 { template using SerializerTT = serialization::v3::binary::Serializer; @@ -134,6 +131,11 @@ struct is_pair> : std::true_type { template class Protocol : public mprpc::Protocol { struct TypeData { + MessageCompleteFunctionT complete_fnc_; + + TypeData(const TypeData&) = default; + TypeData(TypeData&&) = default; + template TypeData(F&& _f) : complete_fnc_(std::forward(_f)) @@ -146,8 +148,6 @@ class Protocol : public mprpc::Protocol { { complete_fnc_(_rctx, _p1, _p2, _e); } - - MessageCompleteFunctionT complete_fnc_; }; using ThisT = Protocol; @@ -384,7 +384,4 @@ auto create_protocol(MetadataFactory&& _metadata_factory, InitFunction _init_fnc return std::make_shared(_metadata_factory, _init_fnc); } -} // namespace serialization_v3 -} // namespace mprpc -} // namespace frame -} // namespace solid +} // namespace solid::frame::mprpc::serialization_v3 diff --git a/solid/frame/mprpc/src/mprpcconfiguration.cpp b/solid/frame/mprpc/src/mprpcconfiguration.cpp index 717e9e3ee..f76b806e3 100644 --- a/solid/frame/mprpc/src/mprpcconfiguration.cpp +++ b/solid/frame/mprpc/src/mprpcconfiguration.cpp @@ -42,12 +42,12 @@ std::ostream& operator<<(std::ostream& _ros, const RelayDataFlagsT& _flags) namespace { MutableSharedBuffer default_allocate_recv_buffer(const uint32_t _cp) { - return BufferManager::make_mutable(_cp); + return BufferPool::make_mutable(_cp); } MutableSharedBuffer default_allocate_send_buffer(const uint32_t _cp) { - return BufferManager::make_mutable(_cp); + return BufferPool::make_mutable(_cp); } // void empty_reset_serializer_limits(ConnectionContext &, serialization::binary::Limits&){} diff --git a/solid/frame/mprpc/test/multiprotocol_basic/alpha/client/alphaclient.cpp b/solid/frame/mprpc/test/multiprotocol_basic/alpha/client/alphaclient.cpp index 7c7705f39..4685d7a01 100644 --- a/solid/frame/mprpc/test/multiprotocol_basic/alpha/client/alphaclient.cpp +++ b/solid/frame/mprpc/test/multiprotocol_basic/alpha/client/alphaclient.cpp @@ -117,7 +117,7 @@ ErrorConditionT start( auto proto = frame::mprpc::serialization_v3::create_protocol( reflection::v1::metadata::factory, [](auto& _rmap) { - auto lambda = [&](const TypeIdT _id, const std::string_view _name, type_identity const& _rtype) { + auto lambda = [&](const TypeIdT _id, const std::string_view _name, type_identity const&) { _rmap.template registerMessage(_id, _name, complete_message); }; alpha_protocol::configure_protocol(lambda); diff --git a/solid/frame/mprpc/test/multiprotocol_basic/alpha/server/alphaserver.hpp b/solid/frame/mprpc/test/multiprotocol_basic/alpha/server/alphaserver.hpp index 14adf5290..d88b27156 100644 --- a/solid/frame/mprpc/test/multiprotocol_basic/alpha/server/alphaserver.hpp +++ b/solid/frame/mprpc/test/multiprotocol_basic/alpha/server/alphaserver.hpp @@ -15,7 +15,7 @@ void complete_message( template void register_messages(Reg& _rmap) { - auto lambda = [&](const TypeIdT _id, const std::string_view _name, std::type_identity const& _rtype) { + auto lambda = [&](const TypeIdT _id, const std::string_view _name, std::type_identity const&) { _rmap.template registerMessage(_id, _name, complete_message); }; alpha_protocol::configure_protocol(lambda); diff --git a/solid/frame/mprpc/test/multiprotocol_basic/beta/client/betaclient.cpp b/solid/frame/mprpc/test/multiprotocol_basic/beta/client/betaclient.cpp index ed226df89..afbebeb98 100644 --- a/solid/frame/mprpc/test/multiprotocol_basic/beta/client/betaclient.cpp +++ b/solid/frame/mprpc/test/multiprotocol_basic/beta/client/betaclient.cpp @@ -105,7 +105,7 @@ ErrorConditionT start( auto proto = frame::mprpc::serialization_v3::create_protocol( reflection::v1::metadata::factory, [](auto& _rmap) { - auto lambda = [&](const TypeIdT _id, const std::string_view _name, type_identity const& _rtype) { + auto lambda = [&](const TypeIdT _id, const std::string_view _name, type_identity const&) { using TypeT = T; if constexpr (std::is_same_v) { _rmap.template registerMessage(_id, _name, complete_message_first); diff --git a/solid/frame/mprpc/test/multiprotocol_basic/beta/server/betaserver.hpp b/solid/frame/mprpc/test/multiprotocol_basic/beta/server/betaserver.hpp index 73e283047..008bf8e1f 100644 --- a/solid/frame/mprpc/test/multiprotocol_basic/beta/server/betaserver.hpp +++ b/solid/frame/mprpc/test/multiprotocol_basic/beta/server/betaserver.hpp @@ -15,7 +15,7 @@ void complete_message( template void register_messages(Reg& _rmap) { - auto lambda = [&](const TypeIdT _id, const std::string_view _name, std::type_identity const& _rtype) { + auto lambda = [&](const TypeIdT _id, const std::string_view _name, std::type_identity const&) { _rmap.template registerMessage(_id, _name, complete_message); }; beta_protocol::configure_protocol(lambda); diff --git a/solid/frame/mprpc/test/multiprotocol_basic/gamma/client/gammaclient.cpp b/solid/frame/mprpc/test/multiprotocol_basic/gamma/client/gammaclient.cpp index 19566cae9..3c9cf98a6 100644 --- a/solid/frame/mprpc/test/multiprotocol_basic/gamma/client/gammaclient.cpp +++ b/solid/frame/mprpc/test/multiprotocol_basic/gamma/client/gammaclient.cpp @@ -66,7 +66,7 @@ ErrorConditionT start( auto proto = frame::mprpc::serialization_v3::create_protocol( reflection::v1::metadata::factory, [](auto& _rmap) { - auto lambda = [&](const TypeIdT _id, const std::string_view _name, type_identity const& _rtype) { + auto lambda = [&](const TypeIdT _id, const std::string_view _name, type_identity const&) { _rmap.template registerMessage(_id, _name, complete_message); }; gamma_protocol::configure_protocol(lambda); diff --git a/solid/frame/mprpc/test/multiprotocol_basic/gamma/server/gammaserver.hpp b/solid/frame/mprpc/test/multiprotocol_basic/gamma/server/gammaserver.hpp index 62c358adf..2520178a2 100644 --- a/solid/frame/mprpc/test/multiprotocol_basic/gamma/server/gammaserver.hpp +++ b/solid/frame/mprpc/test/multiprotocol_basic/gamma/server/gammaserver.hpp @@ -31,7 +31,7 @@ void complete_message( template void register_messages(Reg& _rmap) { - auto lambda = [&](const TypeIdT _id, const std::string_view _name, std::type_identity const& _rtype) { + auto lambda = [&](const TypeIdT _id, const std::string_view _name, std::type_identity const&) { _rmap.template registerMessage(_id, _name, complete_message); }; gamma_protocol::configure_protocol(lambda); diff --git a/solid/frame/mprpc/test/test_clientserver_versioning.cpp b/solid/frame/mprpc/test/test_clientserver_versioning.cpp index d4871f5b2..3c9d751b6 100644 --- a/solid/frame/mprpc/test/test_clientserver_versioning.cpp +++ b/solid/frame/mprpc/test/test_clientserver_versioning.cpp @@ -133,7 +133,7 @@ void configure_service(frame::mprpc::ServiceT& _rsvc, AioSchedulerT& _rsch, fram auto proto = frame::mprpc::serialization_v3::create_protocol( reflection::v1::metadata::factory, [&](auto& _rmap) { - auto lambda = [&](const uint8_t _id, const std::string_view _name, const type_identity& _rtype) { + auto lambda = [&](const uint8_t _id, const std::string_view _name, const type_identity&) { _rmap.template registerMessage(_id, _name, complete_message); }; configure_protocol(lambda); @@ -203,7 +203,7 @@ void configure_service(frame::mprpc::ServiceT& _rsvc, AioSchedulerT& _rsch, fram auto proto = frame::mprpc::serialization_v3::create_protocol( reflection::v1::metadata::factory, [&](auto& _rmap) { - auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const& _rtype) { + auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const&) { _rmap.template registerMessage(_id, _name, complete_message); }; configure_protocol(lambda); @@ -277,7 +277,7 @@ void configure_service(frame::mprpc::ServiceT& _rsvc, AioSchedulerT& _rsch, fram auto proto = frame::mprpc::serialization_v3::create_protocol( reflection::v1::metadata::factory, [&](auto& _rmap) { - auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const& _rtype) { + auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const&) { _rmap.template registerMessage(_id, _name, complete_message); }; configure_protocol(lambda); @@ -350,7 +350,7 @@ void configure_service(frame::mprpc::ServiceT& _rsvc, AioSchedulerT& _rsch, fram auto proto = frame::mprpc::serialization_v3::create_protocol( reflection::v1::metadata::factory, [&](auto& _rmap) { - auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const& _rtype) { + auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const&) { _rmap.template registerMessage(_id, _name, complete_message); }; configure_protocol(lambda); @@ -489,7 +489,7 @@ string configure_service(frame::mprpc::ServiceT& _rsvc, AioSchedulerT& _rsch) auto proto = frame::mprpc::serialization_v3::create_protocol( reflection::v1::metadata::factory, [&](auto& _rmap) { - auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const& _rtype) { + auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const&) { _rmap.template registerMessage(_id, _name, complete_message); }; configure_protocol(lambda); diff --git a/solid/reflection/v1/metadata.hpp b/solid/reflection/v1/metadata.hpp index 0644db52f..d3a1521ad 100644 --- a/solid/reflection/v1/metadata.hpp +++ b/solid/reflection/v1/metadata.hpp @@ -239,7 +239,7 @@ struct Variant { template Variant& operator=(T&& _rv) { - var_ = std::move(_rv); + var_ = std::forward(_rv); return *this; } @@ -286,12 +286,6 @@ struct Variant { } }; -template -inline constexpr size_t array_size(const T (&arr)[S]) -{ - return S; -} - inline constexpr auto factory = [](const auto& _rt, auto& _rctx, const TypeMapBase* _ptype_map) -> auto { using rem_ref_value_t = typename std::remove_reference::type; using value_t = std::decay_t; diff --git a/solid/utility/sharedbuffer.hpp b/solid/utility/sharedbuffer.hpp index df9e116b2..08830a898 100644 --- a/solid/utility/sharedbuffer.hpp +++ b/solid/utility/sharedbuffer.hpp @@ -9,6 +9,7 @@ #include "solid/system/common.hpp" #include "solid/system/exception.hpp" #include "solid/system/pimpl.hpp" +#include "solid/utility/common.hpp" namespace solid { @@ -20,12 +21,12 @@ struct SharedBufferData { friend class BufferManager; std::atomic use_count_; - std::thread::id make_thread_id_; - SharedBufferData* pnext_ = nullptr; - std::size_t size_ = 0; - std::size_t capacity_ = 0; - char* buffer_ = nullptr; - char data_[8]; + std::uint64_t make_thread_id_ = InvalidIndex{}; + // SharedBufferData* pnext_ = nullptr;//TODO:remove + std::size_t size_ = 0; + std::size_t capacity_ = 0; + char* buffer_ = nullptr; + char data_[8]; SharedBufferData() : use_count_(1) @@ -51,6 +52,15 @@ struct SharedBufferData { { return data_; } + + void reset(size_t const _cap, uint64_t const _own_id) + { + use_count_.store(1); + size_ = 0; + // pnext_ = nullptr;//TODO:remove + capacity_ = _cap; + make_thread_id_ = _own_id; + } }; class SharedBufferBase { @@ -72,7 +82,7 @@ class SharedBufferBase { { } - SharedBufferBase(std::size_t _cap, const std::thread::id& _thr_id); + SharedBufferBase(std::size_t _cap, bool); SharedBufferBase(const SharedBufferBase& _other) : pdata_(_other ? &_other.pdata_->acquire() : _other.pdata_) @@ -170,7 +180,7 @@ class MutableSharedBuffer; //----------------------------------------------------------------------------- class SharedBuffer : public impl::SharedBufferBase { - friend class BufferManager; + friend class BufferPool; friend SharedBuffer make_shared_buffer(std::size_t); SharedBuffer(const std::size_t _cap) @@ -178,8 +188,8 @@ class SharedBuffer : public impl::SharedBufferBase { { } - SharedBuffer(const std::size_t _cap, const std::thread::id& _thr_id) - : SharedBufferBase(_cap, _thr_id) + SharedBuffer(const std::size_t _cap, bool) + : SharedBufferBase(_cap, true) { } @@ -257,8 +267,8 @@ class SharedBufferView : protected impl::SharedBufferBase { { } - SharedBufferView(const std::size_t _cap, const std::thread::id& _thr_id) - : SharedBufferBase(_cap, _thr_id) + SharedBufferView(const std::size_t _cap, bool) + : SharedBufferBase(_cap, true) , data_(impl::SharedBufferBase::data()) { } @@ -344,7 +354,7 @@ class ConstSharedBuffer; class MutableSharedBuffer : protected impl::SharedBufferBase { friend class ConstSharedBuffer; friend class SharedBuffer; - friend class BufferManager; + friend class BufferPool; friend class SharedBufferView; friend MutableSharedBuffer make_mutable_buffer(std::size_t); @@ -354,8 +364,8 @@ class MutableSharedBuffer : protected impl::SharedBufferBase { { } - MutableSharedBuffer(const std::size_t _cap, const std::thread::id& _thr_id) - : impl::SharedBufferBase(_cap, _thr_id) + MutableSharedBuffer(const std::size_t _cap, bool) + : impl::SharedBufferBase(_cap, true) { } @@ -628,6 +638,7 @@ inline SharedBuffer::SharedBuffer(MutableSharedBuffer&& _other) { } +#if 0 //----------------------------------------------------------------------------- // BufferManager //----------------------------------------------------------------------------- @@ -672,5 +683,99 @@ class BufferManager : NonCopyable { BufferManager(const Configuration& _config); ~BufferManager(); }; +#endif + +#if 1 +class BufferPool : NonCopyable { + friend class impl::SharedBufferData; + friend class impl::SharedBufferBase; + struct LocalData; + struct OwnData; + struct Data; + PimplT pimpl_; + + using DataT = impl::SharedBufferData; + + static char* release(DataT&); + static DataT* allocate(size_t _cap, uint64_t& _rown_id, size_t& _ralloc_capacity); + +public: + struct Configuration { + using CapacityDispatchFncT = std::function(size_t)>; + + size_t const cache_vector_capacity_ = 256; + size_t const capacity_count_ = 12; + uint32_t const max_thread_count_ = 1024; + uint32_t const thread_spin_lock_count_ = 1024; + + CapacityDispatchFncT capacity_dispatch_fnc_{ + [](size_t const _requested_capacity) -> std::pair { + if (_requested_capacity <= 64) { + return {0, 64}; + } else if (_requested_capacity <= 128) { + return {1, 128}; + } else if (_requested_capacity <= 256) { + return {2, 256}; + } else if (_requested_capacity <= 512) { + return {3, 512}; + } else if (_requested_capacity <= 1024) { + return {4, 1024}; + } else if (_requested_capacity <= 2048) { + return {5, 2048}; + } else if (_requested_capacity <= 4096) { + return {6, 4096}; + } else if (_requested_capacity <= (8 * 1024)) { + return {7, (8 * 1024)}; + } else if (_requested_capacity <= (16 * 1024)) { + return {8, (16 * 1024)}; + } else if (_requested_capacity <= (32 * 1024)) { + return {9, (32 * 1024)}; + } else if (_requested_capacity <= (64 * 1024)) { + return {10, (64 * 1024)}; + } else if (_requested_capacity <= (128 * 1024)) { + return {11, (128 * 1024)}; + } else if (_requested_capacity <= (256 * 1024)) { + return {12, (256 * 1024)}; + } + return {0, 0}; + }}; + }; + + static BufferPool& instance(Configuration const& _rconfig) + { + return do_instance(_rconfig); + } + static BufferPool& instance() + { + static Configuration const config; + return do_instance(config); + } + + static SharedBuffer make(const size_t _cap) + { + return SharedBuffer{_cap, true}; + } + + static MutableSharedBuffer make_mutable(const size_t _cap) + { + return MutableSharedBuffer{make(_cap)}; + } + + static void localMaxCount(size_t _cap, size_t _count); + static size_t localMaxCount(size_t _cap); + static size_t localCount(size_t _cap); + + static const Configuration& configuration(); + +private: + BufferPool(const Configuration& _config); + ~BufferPool(); + + static BufferPool& do_instance(Configuration const&); + + static Data& data(); + static LocalData& local_data(); +}; +#endif } // namespace solid \ No newline at end of file diff --git a/solid/utility/src/sharedbuffer.cpp b/solid/utility/src/sharedbuffer.cpp index accbceaf2..eb4d80318 100644 --- a/solid/utility/src/sharedbuffer.cpp +++ b/solid/utility/src/sharedbuffer.cpp @@ -1,8 +1,16 @@ #include "solid/utility/sharedbuffer.hpp" +#include "solid/system/spinlock.hpp" +#include "solid/utility/common.hpp" +#include "solid/utility/stack.hpp" +#include +#include +#include #include #include +using namespace std; + namespace solid { // SharedBuffer::Data SharedBuffer::sentinel; @@ -28,10 +36,10 @@ namespace impl { char* SharedBufferData::release(size_t& _previous_use_count) { if ((_previous_use_count = use_count_.fetch_sub(1)) == 1) { - if (make_thread_id_ == std::thread::id{}) { + if (make_thread_id_ == InvalidIndex{}) { return buffer_; } else { - return BufferManager::release(this); + return BufferPool::release(*this); } } return nullptr; @@ -52,30 +60,23 @@ char* SharedBufferData::collapse(size_t& _previous_use_count) auto pbuf = new char[new_cap]; auto pdata = new (pbuf) SharedBufferData{pbuf}; - pdata->capacity_ = _cap; //(pbuf + new_cap) - pdata->data(); + pdata->capacity_ = _cap; return pdata; } -SharedBufferBase::SharedBufferBase(const std::size_t _cap, const std::thread::id& _thr_id) +SharedBufferBase::SharedBufferBase(const std::size_t _cap, bool) { - pdata_ = BufferManager::allocate(_cap); + uint64_t own_id = InvalidIndex{}; + size_t alloc_capacity = 0; + pdata_ = BufferPool::allocate(_cap, own_id, alloc_capacity); + if (pdata_ == nullptr) [[unlikely]] { - const std::size_t new_cap = compute_capacity(_cap); + const std::size_t new_cap = compute_capacity((alloc_capacity != 0U) ? alloc_capacity : _cap); char* pbuf = new char[new_cap]; pdata_ = new (pbuf) SharedBufferData{pbuf}; - pdata_->capacity_ = _cap; //(pbuf + new_cap) - pdata_->data(); - } - pdata_->make_thread_id_ = _thr_id; -} - -std::size_t SharedBufferBase::actualCapacity() const -{ - if (*this) { - const std::size_t new_cap = compute_capacity(pdata_->capacity_); - return (pdata_->buffer_ + new_cap) - pdata_->data(); - } else { - return 0; + pdata_->capacity_ = _cap; } + pdata_->make_thread_id_ = own_id; } } // namespace impl @@ -94,7 +95,7 @@ void RingSharedBuffer::optimize() } //----------------------------------------------------------------------------- - +#if 0 struct BufferManager::LocalData { struct Entry { impl::SharedBufferData* ptop_ = nullptr; @@ -218,5 +219,384 @@ BufferManager::~BufferManager() {} { return instance().pimpl_->config_; } +#endif + +namespace { +using CacheVectorT = std::vector; + +struct RemoteStub { + CacheVectorT fill_vec_; + + [[nodiscard]] bool canPush() const + { + return fill_vec_.size() != fill_vec_.capacity(); + } + void push(impl::SharedBufferData* _rpdata) + { + fill_vec_.emplace_back(_rpdata); + } + + [[nodiscard]] bool empty() const + { + return fill_vec_.empty(); + } +}; + +struct Stub { + using CacheStackT = Stack; + using RemoteMapT = std::unordered_map; + + CacheStackT filled_stack_; + CacheStackT emptied_stack_; + RemoteMapT remote_map_; + + [[nodiscard]] bool empty() const + { + return not filled_stack_.empty() and not filled_stack_.top().empty(); + } + + auto& remote(uint64_t _own_id) + { + return remote_map_[_own_id]; + } + + impl::SharedBufferData* pop() + { + assert(not empty()); + auto* pdata = filled_stack_.top().back(); + filled_stack_.top().pop_back(); + if (filled_stack_.top().empty()) { + emptied_stack_.push(std::move(filled_stack_.top())); + filled_stack_.pop(); + } + return pdata; + } + + [[nodiscard]] bool canPush() const + { + return not filled_stack_.empty() and filled_stack_.top().size() != filled_stack_.top().capacity(); + } + + void push(impl::SharedBufferData* _rpdata) + { + filled_stack_.top().emplace_back(_rpdata); + } + + bool fetchEmpty() + { + if (not emptied_stack_.empty()) { + assert(emptied_stack_.top().capacity() != 0u); + filled_stack_.push(std::move(emptied_stack_.top())); + assert(emptied_stack_.top().capacity() == 0u); + emptied_stack_.pop(); + return true; + } + return false; + } + + bool fetchEmpty(RemoteStub& _rremote_stub) + { + assert(_rremote_stub.fill_vec_.capacity() == 0u); + if (not emptied_stack_.empty()) { + assert(emptied_stack_.top().capacity() != 0u); + _rremote_stub.fill_vec_ = std::move(emptied_stack_.top()); + assert(emptied_stack_.top().capacity() == 0u); + emptied_stack_.pop(); + return true; + } + return false; + } +}; + +uint64_t pack(uint64_t const _index, uint64_t const _unique) +{ + return _index << 32U + (_unique & 0xffffffffU); +} + +pair unpack(uint64_t const _id) +{ + return {_id >> 32U, _id & 0xffffffffU}; +} + +} // namespace + +struct BufferPool::OwnData { + uint32_t unique_{}; + std::vector stubs_; + + bool fetch(size_t const _index, Stub& _local_stub) + { + return false; + } + + bool fetchEmpty(size_t const _index, Stub& _local_stub) + { + return false; + } +}; + +struct BufferPool::LocalData { + uint64_t const own_id_{InvalidIndex{}}; + OwnData& rown_; + std::vector stubs_; + + LocalData(BufferPool::Data&); + + ~LocalData(); + + auto& own() + { + return rown_; + } + + [[nodiscard]] uint64_t ownId() const + { + return own_id_; + } +}; + +struct BufferPool::Data { + const Configuration config_; + vector own_vec_; + Stack free_own_entries_stack_; + uint32_t own_index_{0}; + std::mutex mutex_; + SpinLock* pspin_lock_array_ = nullptr; + SpinLock spin_lock_; + + Data(const BufferPool::Configuration& _config) + : config_(_config) + { + own_vec_.resize(config_.max_thread_count_); + pspin_lock_array_ = new SpinLock[config_.thread_spin_lock_count_]; + } + + ~Data() + { + // TODO: + delete[] pspin_lock_array_; + } + + auto& spinLock(size_t const _index) + { + return pspin_lock_array_[_index % config_.thread_spin_lock_count_]; + } + + [[nodiscard]] auto const& config() const + { + return config_; + } + + bool fetch(size_t const _index, Stub& _local_stub) + { + return false; + } + + bool fetchEmpty(size_t const _index, Stub& _local_stub) + { + return false; + } + + bool createEmpty(size_t const /*_index*/, Stub& _local_stub) const + { + CacheVectorT vec; + vec.reserve(config().cache_vector_capacity_); + _local_stub.emptied_stack_.push(std::move(vec)); + return true; + } + + void push(uint64_t const _own_id, size_t const _index, RemoteStub& _rremote_stub, Stub& _rstub) + { + } + + uint64_t createOwnId() + { + uint64_t id; + { + lock_guard lock(mutex_); + if (not free_own_entries_stack_.empty()) { + id = free_own_entries_stack_.top(); + free_own_entries_stack_.pop(); + } else { + solid_check(own_index_ < own_vec_.size()); + id = own_index_; + ++own_index_; + } + } + return pack(id, own_vec_[id].unique_); + } + + auto& unsafeOwn(size_t const _own_id) + { + return own_vec_[unpack(_own_id).first]; + } + + void clearOwn(size_t const _own_index) + { + auto& own = own_vec_[_own_index]; + { + lock_guard lock(spinLock(_own_index)); + ++own.unique_; + } + // after this point every push to own will fail thus own data will not change + lock_guard lock(spin_lock_); + } + + void releaseOwnId(uint64_t const _own_id) + { + auto const [index, unique] = unpack(_own_id); + (void)unique; + clearOwn(index); + { + lock_guard lock(mutex_); + free_own_entries_stack_.push(index); + } + } +}; + +BufferPool::LocalData::LocalData(BufferPool::Data& _rdata) + : own_id_(_rdata.createOwnId()) + , rown_(_rdata.unsafeOwn(own_id_)) +{ +} + +BufferPool::LocalData::~LocalData() +{ + BufferPool::data().releaseOwnId(own_id_); +} + +BufferPool::BufferPool(const BufferPool::Configuration& _config) + : pimpl_{make_pimpl(_config)} +{ +} + +BufferPool::~BufferPool() {} + +BufferPool::Data& BufferPool::data() +{ + return *instance().pimpl_; +} + +BufferPool::LocalData& BufferPool::local_data() +{ + static thread_local LocalData local_data{data()}; + return local_data; +} + +BufferPool& BufferPool::do_instance(Configuration const& _rconfig) +{ + static BufferPool bman{_rconfig}; + return bman; +} + +char* BufferPool::release(DataT& _rbuf_data) +{ + assert(_rbuf_data.make_thread_id_ != InvalidIndex{}); + + auto& rdata = data(); + + auto [index, capacity] = rdata.config().capacity_dispatch_fnc_(_rbuf_data.capacity_); + + auto& rlocal_data = local_data(); + + if (_rbuf_data.make_thread_id_ == rlocal_data.ownId()) { + auto& rstub = rlocal_data.stubs_[index]; + if (rstub.canPush()) { + rstub.push(&_rbuf_data); + return nullptr; + } + if (rstub.fetchEmpty()) { + rstub.push(&_rbuf_data); + return nullptr; + } + + if (rlocal_data.own().fetchEmpty(index, rstub)) { + rstub.fetchEmpty(); + rstub.push(&_rbuf_data); + return nullptr; + } + + if (rdata.fetchEmpty(index, rstub)) { + rstub.fetchEmpty(); + rstub.push(&_rbuf_data); + return nullptr; + } + + if (rdata.createEmpty(index, rstub)) { + rstub.fetchEmpty(); + rstub.push(&_rbuf_data); + return nullptr; + } + + } else { + auto& rstub = rlocal_data.stubs_[index]; + auto& rremote_stub = rstub.remote(_rbuf_data.make_thread_id_); + + if (rremote_stub.canPush()) { + rremote_stub.push(&_rbuf_data); + return nullptr; + } + + if (not rremote_stub.empty()) { + rdata.push(_rbuf_data.make_thread_id_, index, rremote_stub, rstub); + } + + if (rstub.fetchEmpty(rremote_stub)) { + rstub.push(&_rbuf_data); + return nullptr; + } + + if (rlocal_data.own().fetchEmpty(index, rstub)) { + rstub.fetchEmpty(rremote_stub); + rremote_stub.push(&_rbuf_data); + return nullptr; + } + + if (rdata.fetchEmpty(index, rstub)) { + rstub.fetchEmpty(rremote_stub); + rremote_stub.push(&_rbuf_data); + return nullptr; + } + + if (rdata.createEmpty(index, rstub)) { + rstub.fetchEmpty(rremote_stub); + rremote_stub.push(&_rbuf_data); + return nullptr; + } + } + + return _rbuf_data.buffer_; +} + +BufferPool::DataT* BufferPool::allocate(size_t _cap, uint64_t& _rown_id, size_t& _ralloc_capacity) +{ + auto& rdata = data(); + + auto [index, capacity] = rdata.config().capacity_dispatch_fnc_(_cap); + + if (capacity == 0U or index > rdata.config().capacity_count_) [[unlikely]] { + return nullptr; + } + + auto& rlocal_data = local_data(); + + _rown_id = rlocal_data.ownId(); + _ralloc_capacity = capacity; + + auto& rstub = rlocal_data.stubs_[index]; + + if (not rstub.empty()) { + return rstub.pop(); + } + + if (rlocal_data.own().fetch(index, rstub)) { + return rstub.pop(); + } + + if (rdata.fetch(index, rstub)) { + return rstub.pop(); + } + return nullptr; +} } // namespace solid \ No newline at end of file diff --git a/solid/utility/test/test_shared_buffer.cpp b/solid/utility/test/test_shared_buffer.cpp index a2cbf93a5..4aa1e507b 100644 --- a/solid/utility/test/test_shared_buffer.cpp +++ b/solid/utility/test/test_shared_buffer.cpp @@ -28,6 +28,8 @@ int test_shared_buffer(int argc, char* argv[]) solid_check(sb3); } + { + } #if false // TODO: { MutableSharedBuffer sb = make_mutable_buffer(1000); @@ -133,20 +135,7 @@ int test_shared_buffer(int argc, char* argv[]) SharedBuffer sb2 = BufferManager::make(i); solid_check(sb1.capacity() == i); solid_check(sb2.capacity() == i); - cout << i << " " << sb1.capacity() << " " << sb1.actualCapacity() << " " << sb2.capacity() << " " << sb2.actualCapacity() << endl; } #endif - { - SharedBuffer empty_buf; - solid_check(empty_buf.capacity() == 0); - cout << "Empty buffer actualCapacity = " << empty_buf.actualCapacity() << endl; - solid_check(empty_buf.actualCapacity() == 0); - } - { - SharedBuffer zero_buf = make_shared_buffer(0); - solid_check(zero_buf.capacity() == 0); - cout << "Zero buffer actualCapacity = " << zero_buf.actualCapacity() << endl; - solid_check(zero_buf.actualCapacity() != 0 && zero_buf.actualCapacity() < 0xffffffff); - } return 0; } \ No newline at end of file diff --git a/solid/utility/threadpool.hpp b/solid/utility/threadpool.hpp index 0ffb4bf4f..9156b54f7 100644 --- a/solid/utility/threadpool.hpp +++ b/solid/utility/threadpool.hpp @@ -11,6 +11,7 @@ #pragma once #include #include +#include #include #include #include @@ -58,6 +59,12 @@ struct ThreadPoolStatistic : solid::Statistic { ThreadPoolStatistic(); + auto now() + { + using namespace std::chrono; + return high_resolution_clock::now(); + } + void createContext() { ++create_context_count_; @@ -103,13 +110,16 @@ struct ThreadPoolStatistic : solid::Statistic { solid_statistic_max(max_consume_all_count_, _count); } - void pushOne(const bool _with_context, const uint64_t _duration_us) + template + void pushOne(const bool _with_context, TimePos const _start) { + using namespace std::chrono; + const uint64_t duration = duration_cast(now() - _start).count(); ++push_one_count_[_with_context]; - solid_statistic_min(push_one_latency_min_us_, _duration_us); - solid_statistic_max(push_one_latency_max_us_, _duration_us); - push_one_latency_sum_us_ += _duration_us; + solid_statistic_min(push_one_latency_min_us_, duration); + solid_statistic_max(push_one_latency_max_us_, duration); + push_one_latency_sum_us_ += duration; } void pushAll(const bool _should_wake) { @@ -146,6 +156,11 @@ struct ThreadPoolStatistic : solid::Statistic { struct EmptyThreadPoolStatistic : solid::Statistic { + static int now() + { + return 0; + } + void createContext() {} void deleteContext() {} @@ -492,13 +507,11 @@ class ThreadPool : NonCopyable { } } - void notifyWhilePushOne(std::chrono::time_point const& _start, uint64_t& _rduration) noexcept + void notifyWhilePushOne() noexcept { - using namespace std::chrono; event_ = to_underlying(EventE::Fill); ++consume_count_; std::atomic_notify_all(&consume_count_); - _rduration = duration_cast(steady_clock::now() - _start).count(); } void waitWhileStop(Stats& _rstats, const AtomicCounterValueT _count, const size_t _spin_count) noexcept @@ -1267,7 +1280,7 @@ template void ThreadPool::doPushOne(Tsk&& _task, ContextStub* _pctx) { using namespace std::chrono; - const auto start = steady_clock::now(); + const auto start = statistic_.now(); const auto [index, count] = pushOneIndex(); auto& rstub = one_.tasks_[index]; @@ -1281,10 +1294,8 @@ void ThreadPool::doPushOne(Tsk&& _task, ContextStub* _p _pctx->acquire(); rstub.context_produce_id_ = _pctx->produce_id_.fetch_add(1); } - uint64_t duration; - rstub.notifyWhilePushOne(start, duration); - // const uint64_t duration = duration_cast(steady_clock::now() - start).count(); - statistic_.pushOne(_pctx != nullptr, duration); + rstub.notifyWhilePushOne(); + statistic_.pushOne(_pctx != nullptr, start); } //----------------------------------------------------------------------------- // NOTE: diff --git a/tutorials/mprpc_echo/mprpc_echo_client.cpp b/tutorials/mprpc_echo/mprpc_echo_client.cpp index e87a274ae..ea59c3b3d 100644 --- a/tutorials/mprpc_echo/mprpc_echo_client.cpp +++ b/tutorials/mprpc_echo/mprpc_echo_client.cpp @@ -83,7 +83,7 @@ int main(int argc, char* argv[]) auto proto = frame::mprpc::serialization_v3::create_protocol( reflection::v1::metadata::factory, [&](auto& _rmap) { - auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const& _rtype) { + auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const&) { _rmap.template registerMessage(_id, _name, rpc_echo_client::complete_message); }; rpc_echo::configure_protocol(lambda); diff --git a/tutorials/mprpc_echo/mprpc_echo_client_pool.cpp b/tutorials/mprpc_echo/mprpc_echo_client_pool.cpp index df50ec71b..28bea1382 100644 --- a/tutorials/mprpc_echo/mprpc_echo_client_pool.cpp +++ b/tutorials/mprpc_echo/mprpc_echo_client_pool.cpp @@ -87,7 +87,7 @@ int main(int argc, char* argv[]) auto proto = frame::mprpc::serialization_v3::create_protocol( reflection::v1::metadata::factory, [&](auto& _rmap) { - auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const& _rtype) { + auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const&) { _rmap.template registerMessage(_id, _name, rpc_echo_client::complete_message); }; rpc_echo::configure_protocol(lambda); diff --git a/tutorials/mprpc_echo/mprpc_echo_server.cpp b/tutorials/mprpc_echo/mprpc_echo_server.cpp index dd776a379..be5561a1d 100644 --- a/tutorials/mprpc_echo/mprpc_echo_server.cpp +++ b/tutorials/mprpc_echo/mprpc_echo_server.cpp @@ -83,7 +83,7 @@ int main(int argc, char* argv[]) auto proto = frame::mprpc::serialization_v3::create_protocol( reflection::v1::metadata::factory, [&](auto& _rmap) { - auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const& _rtype) { + auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const&) { _rmap.template registerMessage(_id, _name, rpc_echo_server::complete_message); }; rpc_echo::configure_protocol(lambda); diff --git a/tutorials/mprpc_file/mprpc_file_client.cpp b/tutorials/mprpc_file/mprpc_file_client.cpp index b5d7d7fe4..c8428e864 100644 --- a/tutorials/mprpc_file/mprpc_file_client.cpp +++ b/tutorials/mprpc_file/mprpc_file_client.cpp @@ -90,7 +90,7 @@ int main(int argc, char* argv[]) auto proto = frame::mprpc::serialization_v3::create_protocol( reflection::v1::metadata::factory, [&](auto& _rmap) { - auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const& _rtype) { + auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const&) { _rmap.template registerMessage(_id, _name, rpc_file_client::complete_message); }; rpc_file::configure_protocol(lambda); diff --git a/tutorials/mprpc_file/mprpc_file_server.cpp b/tutorials/mprpc_file/mprpc_file_server.cpp index cd63f23e1..b418dc645 100644 --- a/tutorials/mprpc_file/mprpc_file_server.cpp +++ b/tutorials/mprpc_file/mprpc_file_server.cpp @@ -157,7 +157,7 @@ int main(int argc, char* argv[]) auto proto = frame::mprpc::serialization_v3::create_protocol( reflection::v1::metadata::factory, [&](auto& _rmap) { - auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const& _rtype) { + auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const&) { _rmap.template registerMessage(_id, _name, rpc_file_server::complete_message); }; rpc_file::configure_protocol(lambda); diff --git a/tutorials/mprpc_request/mprpc_request_client.cpp b/tutorials/mprpc_request/mprpc_request_client.cpp index 40dfc6a27..04f24f19d 100644 --- a/tutorials/mprpc_request/mprpc_request_client.cpp +++ b/tutorials/mprpc_request/mprpc_request_client.cpp @@ -88,7 +88,7 @@ int main(int argc, char* argv[]) auto proto = frame::mprpc::serialization_v3::create_protocol( reflection::v1::metadata::factory, [&](auto& _rmap) { - auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const& _rtype) { + auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const&) { _rmap.template registerMessage(_id, _name, rpc_request_client::complete_message); }; rpc_request::configure_protocol(lambda); diff --git a/tutorials/mprpc_request/mprpc_request_server.cpp b/tutorials/mprpc_request/mprpc_request_server.cpp index 99684fad9..73199b11f 100644 --- a/tutorials/mprpc_request/mprpc_request_server.cpp +++ b/tutorials/mprpc_request/mprpc_request_server.cpp @@ -158,7 +158,7 @@ int main(int argc, char* argv[]) auto proto = frame::mprpc::serialization_v3::create_protocol( reflection::v1::metadata::factory, [&](auto& _rmap) { - auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const& _rtype) { + auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const&) { _rmap.template registerMessage(_id, _name, rpc_request_server::complete_message); }; rpc_request::configure_protocol(lambda); diff --git a/tutorials/mprpc_request_ssl/mprpc_request_client.cpp b/tutorials/mprpc_request_ssl/mprpc_request_client.cpp index 76390e18b..dcda5b8fc 100644 --- a/tutorials/mprpc_request_ssl/mprpc_request_client.cpp +++ b/tutorials/mprpc_request_ssl/mprpc_request_client.cpp @@ -104,7 +104,7 @@ int main(int argc, char* argv[]) auto proto = frame::mprpc::serialization_v3::create_protocol( reflection::v1::metadata::factory, [&](auto& _rmap) { - auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const& _rtype) { + auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const&) { using TypeT = T; if constexpr (std::is_base_of_v) { diff --git a/tutorials/mprpc_request_ssl/mprpc_request_server.cpp b/tutorials/mprpc_request_ssl/mprpc_request_server.cpp index ef439a3f4..c6cdab81e 100644 --- a/tutorials/mprpc_request_ssl/mprpc_request_server.cpp +++ b/tutorials/mprpc_request_ssl/mprpc_request_server.cpp @@ -326,7 +326,7 @@ int main(int argc, char* argv[]) auto proto = frame::mprpc::serialization_v3::create_protocol( reflection::v1::metadata::factory, [&](auto& _rmap) { - auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const& _rtype) { + auto lambda = [&](const uint8_t _id, const std::string_view _name, type_identity const&) { using TypeT = T; if constexpr (std::is_base_of_v) { From fb7963a19438bc65b330cb290c95b16d43f4358a Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Thu, 11 Sep 2025 20:36:51 +0300 Subject: [PATCH 07/56] utility: fix intrusive_ptr casting --- solid/reflection/v1/reflection.hpp | 13 ++-- solid/utility/cacheable.hpp | 36 +++++++++- solid/utility/cast.hpp | 1 - solid/utility/intrusiveptr.hpp | 83 ++++++++++++------------ solid/utility/test/test_intrusiveptr.cpp | 4 +- 5 files changed, 88 insertions(+), 49 deletions(-) diff --git a/solid/reflection/v1/reflection.hpp b/solid/reflection/v1/reflection.hpp index 2f2f21aaa..a5e1fc488 100644 --- a/solid/reflection/v1/reflection.hpp +++ b/solid/reflection/v1/reflection.hpp @@ -15,6 +15,7 @@ #include "solid/reflection/v1/reflector.hpp" #include "solid/reflection/v1/typetraits.hpp" +#ifndef __cpp_explicit_this_parameter #define SOLID_REFLECT_V1(reflector, rthis, context) \ template \ void solidReflectV1(Reflector& _rr, Context& _rctx) const \ @@ -28,11 +29,13 @@ } \ template \ static void solidReflectV1(Reflector& reflector, T& rthis, Context& context) - -namespace solid { -namespace reflection { +#else +#define SOLID_REFLECT_V1(reflector, rthis, context) \ + template \ + static void solidReflectV1(Reflector& reflector, this T& rthis, Context& context) +#endif +namespace solid::reflection { using namespace v1; -} // namespace reflection -} // namespace solid +} // namespace solid::reflection diff --git a/solid/utility/cacheable.hpp b/solid/utility/cacheable.hpp index 448857c7d..e3a9e97f0 100644 --- a/solid/utility/cacheable.hpp +++ b/solid/utility/cacheable.hpp @@ -8,6 +8,7 @@ // See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt. // +#include "solid/system/exception.hpp" #include "solid/utility/cast.hpp" #include "solid/utility/intrusiveptr.hpp" #include "solid/utility/stack.hpp" @@ -20,7 +21,7 @@ class Cacheable { virtual void cacheableClear() {} public: - virtual ~Cacheable() {} + virtual ~Cacheable() = default; }; class SharedCacheable : public Cacheable, public std::enable_shared_from_this { @@ -80,6 +81,15 @@ class IntrusiveCacheable : public Cacheable, public IntrusiveThreadSafeBase { } } + IntrusivePtr doDetach() + { + IntrusivePtr ptr = std::move(next_); + if (ptr) { + next_ = std::move(ptr->next_); + } + return ptr; + } + public: void cache() { @@ -105,6 +115,30 @@ class IntrusiveCacheable : public Cacheable, public IntrusiveThreadSafeBase { { doAttach(static_pointer_cast(std::move(_other))); } + + template + IntrusivePtr cacheableDetachAs() + { + return static_pointer_cast(doDetach()); + } + + template + IntrusivePtr cacheableDetachAllAs() + { + return static_pointer_cast(std::move(next_)); + } + + ~IntrusiveCacheable() override + { + auto next = std::move(next_); + while (next) { + auto tmp = std::move(next->next_); + assert(not next->next_); + assert(next.useCount() == 1U); + next.reset(); + next = std::move(tmp); + } + } }; #ifdef __cpp_concepts diff --git a/solid/utility/cast.hpp b/solid/utility/cast.hpp index 85695ceda..ee56009ec 100644 --- a/solid/utility/cast.hpp +++ b/solid/utility/cast.hpp @@ -9,7 +9,6 @@ // #pragma once -#include "solid/utility/innerlist.hpp" #include namespace solid { diff --git a/solid/utility/intrusiveptr.hpp b/solid/utility/intrusiveptr.hpp index 3204a8b97..7c9280e80 100644 --- a/solid/utility/intrusiveptr.hpp +++ b/solid/utility/intrusiveptr.hpp @@ -10,7 +10,9 @@ #pragma once #include +#include #include +#include namespace solid { @@ -18,7 +20,7 @@ struct IntrusiveThreadSafePolicy; class IntrusiveThreadSafeBase { friend struct IntrusiveThreadSafePolicy; - mutable std::atomic_size_t use_count_{0}; + mutable std::atomic_size_t use_count_{1}; protected: auto useCount() const @@ -118,6 +120,28 @@ class IntrusivePtrBase { protected: IntrusivePtrBase() = default; + IntrusivePtrBase(T* _ptr) + : ptr_(_ptr) + { + assert(ptr_ == nullptr or intrusive_ptr_use_count(*ptr_) == 1U); + } + + IntrusivePtrBase(T* _ptr, const bool _do_acquire) + : ptr_(_ptr) + { + if (_ptr && _do_acquire) { + intrusive_ptr_acquire(*_ptr); + } + } + + IntrusivePtrBase(T* _ptr, const std::true_type) + : ptr_(_ptr) + { + if (_ptr) { + intrusive_ptr_acquire(*_ptr); + } + } + IntrusivePtrBase(const IntrusivePtrBase& _other) : ptr_(_other.ptr_) { @@ -142,7 +166,7 @@ class IntrusivePtrBase { template IntrusivePtrBase(IntrusivePtrBase&& _other) - : ptr_(static_cast(_other.detach())) + : ptr_(static_cast(_other.detach())) { } @@ -174,22 +198,6 @@ class IntrusivePtrBase { IntrusivePtrBase{std::move(_other)}.swap(*this); } - IntrusivePtrBase(T* _ptr) - : ptr_(_ptr) - { - if (_ptr) { - intrusive_ptr_acquire(*_ptr); - } - } - - IntrusivePtrBase(T* _ptr, const bool _do_acquire) - : ptr_(_ptr) - { - if (_ptr && _do_acquire) { - intrusive_ptr_acquire(*_ptr); - } - } - T* detach() noexcept { T* ret = ptr_; @@ -325,6 +333,11 @@ class IntrusivePtr : public impl::IntrusivePtrBase { template friend IntrusivePtr dynamic_pointer_cast(IntrusivePtr&& _rp) noexcept; + IntrusivePtr(T* _ptr, std::true_type const _acquire) + : BaseT(_ptr, _acquire) + { + } + IntrusivePtr(T* _ptr) : BaseT(_ptr) { @@ -412,10 +425,6 @@ class MutableIntrusivePtr : public impl::IntrusivePtrBase { template friend MutableIntrusivePtr make_mutable_intrusive(Args&&... _args); template - friend MutableIntrusivePtr static_pointer_cast(const MutableIntrusivePtr& _rp) noexcept; - template - friend MutableIntrusivePtr dynamic_pointer_cast(const MutableIntrusivePtr& _rp) noexcept; - template friend MutableIntrusivePtr static_pointer_cast(MutableIntrusivePtr&& _rp) noexcept; template friend MutableIntrusivePtr dynamic_pointer_cast(MutableIntrusivePtr&& _rp) noexcept; @@ -554,6 +563,11 @@ class ConstIntrusivePtr : public impl::IntrusivePtrBase { template friend ConstIntrusivePtr dynamic_pointer_cast(ConstIntrusivePtr&& _rp) noexcept; + ConstIntrusivePtr(T* _ptr, std::true_type const _acquire) + : BaseT(_ptr, _acquire) + { + } + ConstIntrusivePtr(T* _ptr) : BaseT(_ptr) { @@ -567,24 +581,23 @@ class ConstIntrusivePtr : public impl::IntrusivePtrBase { template inline IntrusivePtr make_intrusive(Args&&... _args) { - // return IntrusivePtr(new TT(std::forward(_args)...)); return IntrusivePtr(impl::intrusive_ptr_create(std::forward(_args)...)); } template inline IntrusivePtr static_pointer_cast(const IntrusivePtr& _rp) noexcept { - return IntrusivePtr(static_cast(_rp.get())); + return IntrusivePtr(static_cast(_rp.get()), std::true_type{}); } template inline IntrusivePtr dynamic_pointer_cast(const IntrusivePtr& _rp) noexcept { - return IntrusivePtr(dynamic_cast(_rp.get())); + return IntrusivePtr(dynamic_cast(_rp.get()), std::true_type{}); } template inline IntrusivePtr static_pointer_cast(IntrusivePtr&& _rp) noexcept { - return IntrusivePtr(static_cast(_rp.detach())); + return IntrusivePtr(std::move(_rp)); } template @@ -608,21 +621,11 @@ inline MutableIntrusivePtr make_mutable_intrusive(Args&&... _args) // return IntrusivePtr(new TT(std::forward(_args)...)); return MutableIntrusivePtr(make_intrusive(std::forward(_args)...)); } -template -inline MutableIntrusivePtr static_pointer_cast(const MutableIntrusivePtr& _rp) noexcept -{ - return MutableIntrusivePtr(static_cast(_rp.get())); -} -template -inline MutableIntrusivePtr dynamic_pointer_cast(const MutableIntrusivePtr& _rp) noexcept -{ - return MutableIntrusivePtr(dynamic_cast(_rp.get())); -} template inline MutableIntrusivePtr static_pointer_cast(MutableIntrusivePtr&& _rp) noexcept { - return MutableIntrusivePtr(static_cast(_rp.detach())); + return MutableIntrusivePtr(std::move(_rp)); } template @@ -643,18 +646,18 @@ inline MutableIntrusivePtr dynamic_pointer_cast(MutableIntrusivePtr&& _r template inline ConstIntrusivePtr static_pointer_cast(const ConstIntrusivePtr& _rp) noexcept { - return ConstIntrusivePtr(static_cast(_rp.get())); + return ConstIntrusivePtr(static_cast(_rp.get()), std::true_type{}); } template inline ConstIntrusivePtr dynamic_pointer_cast(const ConstIntrusivePtr& _rp) noexcept { - return ConstIntrusivePtr(dynamic_cast(_rp.get())); + return ConstIntrusivePtr(dynamic_cast(_rp.get()), std::true_type{}); } template inline ConstIntrusivePtr static_pointer_cast(ConstIntrusivePtr&& _rp) noexcept { - return ConstIntrusivePtr(static_cast(_rp.detach())); + return ConstIntrusivePtr(std::move(_rp)); } template diff --git a/solid/utility/test/test_intrusiveptr.cpp b/solid/utility/test/test_intrusiveptr.cpp index 4ca3e40cd..af1f11508 100644 --- a/solid/utility/test/test_intrusiveptr.cpp +++ b/solid/utility/test/test_intrusiveptr.cpp @@ -43,7 +43,7 @@ struct TestWithCounter { private: friend class TestIntrusivePolicy; - mutable atomic use_count_{0}; + mutable atomic use_count_{1}; }; template @@ -58,7 +58,7 @@ struct TestIntrusivePolicy { { return _p.use_count_.fetch_sub(1) == 1; } - static size_t useCount(const TestWithCounter& _p) noexcept + static size_t use_count(const TestWithCounter& _p) noexcept { return _p.use_count_.load(std::memory_order_relaxed); } From 7fce57515581294dc6cd4935fe2b9fdf9ba0e625 Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Tue, 23 Sep 2025 22:36:16 +0300 Subject: [PATCH 08/56] adding c++23 support --- CMakeLists.txt | 28 ++++++++++------- cmake/check/cpp23.cpp | 22 ++++++++++++++ .../mprpc/test/test_clientserver_stop.cpp | 4 +-- solid/reflection/v1/reflection.hpp | 2 +- solid/utility/common.hpp | 30 +++++++++++++++++++ solid/utility/queue.hpp | 14 ++++----- solid/utility/stack.hpp | 5 ++-- solid/utility/threadpool.hpp | 8 ++--- 8 files changed, 86 insertions(+), 27 deletions(-) create mode 100644 cmake/check/cpp23.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7485b1fb8..63e232185 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,19 +33,25 @@ find_package(Threads REQUIRED) #----------------------------------------------------------------- if(NOT CMAKE_CXX_STANDARD) - file (READ "${CMAKE_CURRENT_SOURCE_DIR}/cmake/check/cpp20.cpp" source_code) + file (READ "${CMAKE_CURRENT_SOURCE_DIR}/cmake/check/cpp23.cpp" source_code) - set(CMAKE_CXX_STANDARD 20) + set(CMAKE_CXX_STANDARD 23) include(CheckCXXSourceCompiles) - CHECK_CXX_SOURCE_COMPILES("${source_code}" SOLID_COMPILE_CXX20) - if(NOT SOLID_COMPILE_CXX20) - set(CMAKE_CXX_STANDARD 17) - set(CMAKE_CXX_STANDARD_REQUIRED ON) - file (READ "${CMAKE_CURRENT_SOURCE_DIR}/cmake/check/cpp17.cpp" source_code) - CHECK_CXX_SOURCE_COMPILES("${source_code}" SOLID_COMPILE_CXX17) - - if(NOT SOLID_COMPILE_CXX17) - message(FATAL_ERROR "SolidFrame needs at least CXX17!") + CHECK_CXX_SOURCE_COMPILES("${source_code}" SOLID_COMPILE_CXX23) + if(NOT SOLID_COMPILE_CXX23) + file (READ "${CMAKE_CURRENT_SOURCE_DIR}/cmake/check/cpp20.cpp" source_code) + + set(CMAKE_CXX_STANDARD 20) + CHECK_CXX_SOURCE_COMPILES("${source_code}" SOLID_COMPILE_CXX20) + if(NOT SOLID_COMPILE_CXX20) + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + file (READ "${CMAKE_CURRENT_SOURCE_DIR}/cmake/check/cpp17.cpp" source_code) + CHECK_CXX_SOURCE_COMPILES("${source_code}" SOLID_COMPILE_CXX17) + + if(NOT SOLID_COMPILE_CXX17) + message(FATAL_ERROR "SolidFrame needs at least CXX17!") + endif() endif() endif() endif() diff --git a/cmake/check/cpp23.cpp b/cmake/check/cpp23.cpp new file mode 100644 index 000000000..3cc5a1a3a --- /dev/null +++ b/cmake/check/cpp23.cpp @@ -0,0 +1,22 @@ +#include +#include + +using namespace std; + +struct base { + template + void f(this Self&& self) + { + print("{0}", typeid(Self).name()); + } +}; + +struct derived : base {}; + +int main() +{ + derived my_derived; + my_derived.f(); + + return 0; +} \ No newline at end of file diff --git a/solid/frame/mprpc/test/test_clientserver_stop.cpp b/solid/frame/mprpc/test/test_clientserver_stop.cpp index 71eb69ab3..b9b902f91 100644 --- a/solid/frame/mprpc/test/test_clientserver_stop.cpp +++ b/solid/frame/mprpc/test/test_clientserver_stop.cpp @@ -61,7 +61,7 @@ std::string TestErrorCategory::message(int _ev) const case 0: oss << "Success"; break; - case to_underlying(TestErrorE::Dummy): + case solid::to_underlying(TestErrorE::Dummy): oss << " Dummy"; break; default: @@ -71,7 +71,7 @@ std::string TestErrorCategory::message(int _ev) const return oss.str(); } -const ErrorConditionT error_test_dummy(to_underlying(TestErrorE::Dummy), test_category); +const ErrorConditionT error_test_dummy(solid::to_underlying(TestErrorE::Dummy), test_category); struct InitStub { size_t size; diff --git a/solid/reflection/v1/reflection.hpp b/solid/reflection/v1/reflection.hpp index a5e1fc488..7f2367e74 100644 --- a/solid/reflection/v1/reflection.hpp +++ b/solid/reflection/v1/reflection.hpp @@ -32,7 +32,7 @@ #else #define SOLID_REFLECT_V1(reflector, rthis, context) \ template \ - static void solidReflectV1(Reflector& reflector, this T& rthis, Context& context) + void solidReflectV1(this T& rthis, Reflector& reflector, Context& context) #endif namespace solid::reflection { diff --git a/solid/utility/common.hpp b/solid/utility/common.hpp index deeb38b3e..ee62207f5 100644 --- a/solid/utility/common.hpp +++ b/solid/utility/common.hpp @@ -11,6 +11,7 @@ #pragma once #include "solid/system/common.hpp" +#include #include #ifdef __cpp_lib_bitops #include @@ -293,4 +294,33 @@ class Padded : public Base { #endif +template +struct AlignedStorage { + static constexpr size_t size() + { + return sizeof(T); + } + + alignas(T) std::byte data_[size()]; + + std::byte* data() + { + return data_; + } + + std::byte const* data() const + { + return data_; + } + + T* cast() + { + return std::launder(reinterpret_cast(data())); + } + T const* cast() const + { + return std::launder(reinterpret_cast(data())); + } +}; + } // namespace solid diff --git a/solid/utility/queue.hpp b/solid/utility/queue.hpp index 92a46a27c..c4d7c4117 100644 --- a/solid/utility/queue.hpp +++ b/solid/utility/queue.hpp @@ -10,11 +10,11 @@ #pragma once -#include -#include - #include "solid/system/cassert.hpp" #include "solid/system/convertors.hpp" +#include "solid/utility/common.hpp" +#include +#include namespace solid { @@ -31,7 +31,7 @@ class Queue { static constexpr const size_t node_size = bits_to_count(NBits); struct Node { - using Storage = typename std::aligned_storage::type; + using Storage = AlignedStorage; Node(Node* _pnext = nullptr) : pnext_(_pnext) @@ -190,10 +190,10 @@ class Queue { if (pcurrent_node) { pcurrent_node->pnext_ = new Node; pcurrent_node = pcurrent_node->pnext_; - return std::launder(reinterpret_cast(&pcurrent_node->data_[0])); + return pcurrent_node->data_[0].cast(); } else { pcurrent_node = new Node; - return (pfront_ = std::launder(reinterpret_cast(&pcurrent_node->data_[0]))); + return (pfront_ = pcurrent_node->data_[0].cast()); } } } @@ -205,7 +205,7 @@ class Queue { pcurrent_node->pnext_ = ptop_cached_nodes_; ptop_cached_nodes_ = pcurrent_node; // cache the node if (pnext_node) { - return std::launder(reinterpret_cast(&pnext_node->data_[0])); + return pnext_node->data_[0].cast(); } else { solid_assert_log(!size_, generic_logger); pback_ = nullptr; diff --git a/solid/utility/stack.hpp b/solid/utility/stack.hpp index 19b41d50f..2728fea8e 100644 --- a/solid/utility/stack.hpp +++ b/solid/utility/stack.hpp @@ -13,6 +13,7 @@ #include "solid/system/convertors.hpp" #include #include +#include namespace solid { @@ -29,7 +30,7 @@ class Stack { static constexpr const size_t node_size = bits_to_count(NBits); struct Node { - using Storage = typename std::aligned_storage::type; + using Storage = AlignedStorage; Node(Node* _pprev = nullptr) : pprev_(_pprev) @@ -156,7 +157,7 @@ class Stack { pcurrent_node->pprev_ = ptop_cached_nodes_; ptop_cached_nodes_ = pcurrent_node; // cache the node if (pprev_node) { - return std::launder(reinterpret_cast(&pprev_node->data_[node_size - 1])); + return pprev_node->data_[node_size - 1].cast(); } else { solid_assert_log(!size_, generic_logger); return nullptr; diff --git a/solid/utility/threadpool.hpp b/solid/utility/threadpool.hpp index 9156b54f7..f1416f41d 100644 --- a/solid/utility/threadpool.hpp +++ b/solid/utility/threadpool.hpp @@ -310,22 +310,22 @@ typename std::decay::type decay_copy(T&& v) template class alignas(hardware_destructive_interference_size) TaskData { - std::aligned_storage_t data_; + AlignedStorage data_; public: Task& task() noexcept { - return *std::launder(reinterpret_cast(&data_)); + return *data_.cast(); } template void task(T&& _rt) { - ::new (&data_) Task(std::forward(_rt)); + ::new (data_.data()) Task(std::forward(_rt)); } void destroy() { - std::destroy_at(std::launder(reinterpret_cast(&data_))); + std::destroy_at(data_.cast()); } }; From de4b808518428e5e3b98c079bc797fce1d89fee5 Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Fri, 17 Oct 2025 18:29:20 +0300 Subject: [PATCH 09/56] workin on performance improvements on: aioreactor, nanotime, threadpool --- solid/frame/aio/aioreactor.hpp | 2 +- solid/frame/aio/src/aioreactor.cpp | 19 +++++++++---------- solid/system/nanotime.hpp | 2 +- solid/utility/threadpool.hpp | 16 ++++++++-------- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/solid/frame/aio/aioreactor.hpp b/solid/frame/aio/aioreactor.hpp index 689234db8..529236baa 100644 --- a/solid/frame/aio/aioreactor.hpp +++ b/solid/frame/aio/aioreactor.hpp @@ -132,7 +132,7 @@ class Reactor : public frame::ReactorBase { public: using StatisticT = ReactorStatistic; - using EventFunctionT = solid_function_t(void(ReactorContext&, EventBase&&)); + using EventFunctionT = solid::Function; bool start(); void stop() override; diff --git a/solid/frame/aio/src/aioreactor.cpp b/solid/frame/aio/src/aioreactor.cpp index d74d6e16c..bd9cabf2d 100644 --- a/solid/frame/aio/src/aioreactor.cpp +++ b/solid/frame/aio/src/aioreactor.cpp @@ -431,7 +431,6 @@ void Reactor::run() bool running = true; int waitmsec; NanoTime waittime; - size_t waitcnt = 0; while (running) { impl_->current_time_ = NanoTime::nowSteady(); @@ -442,27 +441,30 @@ void Reactor::run() solid_log(logger, Verbose, "epoll_wait wait = " << waittime << ' ' << impl_->reactor_fd_ << ' ' << impl_->event_vec_.size()); selcnt = epoll_pwait2(impl_->reactor_fd_, impl_->event_vec_.data(), static_cast(impl_->event_vec_.size()), waittime != NanoTime::max() ? &waittime : nullptr, nullptr); - if (waittime.seconds() != 0 && waittime.nanoSeconds() != 0) { - ++waitcnt; - } + #elif defined(SOLID_USE_EPOLL) waitmsec = impl_->computeWaitDuration(impl_->current_time_, current_exec_size_ == 0 && pending_wake_count_.load() == 0); solid_log(logger, Verbose, "epoll_wait wait = " << waitmsec); selcnt = epoll_wait(impl_->reactor_fd_, impl_->event_vec_.data(), static_cast(impl_->event_vec_.size()), waitmsec); + #elif defined(SOLID_USE_KQUEUE) waittime = impl_->computeWaitDuration(impl_->current_time_, current_exec_size_ == 0 && pending_wake_count_.load() == 0); solid_log(logger, Verbose, "kqueue wait = " << waittime); selcnt = kevent(impl_->reactor_fd_, nullptr, 0, impl_->event_vec_.data(), static_cast(impl_->event_vec_.size()), waittime != NanoTime::max() ? &waittime : nullptr); + #elif defined(SOLID_USE_WSAPOLL) waitmsec = impl_->computeWaitDuration(impl_->current_time_, current_exec_size_ == 0 && pending_wake_count_.load() == 0); solid_log(logger, Verbose, "wsapoll wait msec = " << waitmsec); selcnt = WSAPoll(impl_->event_vec_.data(), impl_->event_vec_.size(), waitmsec); + #endif - impl_->current_time_ = NanoTime::nowSteady(); + if (waittime) { + impl_->current_time_ = NanoTime::nowSteady(); + } #ifdef SOLID_AIO_TRACE_DURATION const auto start = high_resolution_clock::now(); #endif @@ -473,6 +475,7 @@ void Reactor::run() #endif crtload += selcnt; doCompleteIo(impl_->current_time_, selcnt); + impl_->current_time_ = NanoTime::nowSteady(); } else if (selcnt < 0 && errno != EINTR) { solid_log(logger, Error, "epoll_wait errno = " << last_system_error().message()); running = false; @@ -483,18 +486,15 @@ void Reactor::run() #ifdef SOLID_AIO_TRACE_DURATION const auto elapsed_io = duration_cast(high_resolution_clock::now() - start).count(); #endif - impl_->current_time_ = NanoTime::nowSteady(); doCompleteTimer(impl_->current_time_); #ifdef SOLID_AIO_TRACE_DURATION const auto elapsed_timer = duration_cast(high_resolution_clock::now() - start).count(); #endif - impl_->current_time_ = NanoTime::nowSteady(); doCompleteEvents(impl_->current_time_); // See NOTE above #ifdef SOLID_AIO_TRACE_DURATION const auto elapsed_event = duration_cast(high_resolution_clock::now() - start).count(); #endif - impl_->current_time_ = NanoTime::nowSteady(); - const auto execnt = doCompleteExec(impl_->current_time_); + const auto execnt = doCompleteExec(impl_->current_time_); #ifdef SOLID_AIO_TRACE_DURATION const auto elapsed_total = duration_cast(high_resolution_clock::now() - start).count(); @@ -505,7 +505,6 @@ void Reactor::run() (void)execnt; running = impl_->running_ || (actor_count_ != 0) || current_exec_size_ != 0; } - solid_log(logger, Warning, "reactor waitcount = " << waitcnt); impl_->event_actor_ptr_->stop(); doClearSpecific(); diff --git a/solid/system/nanotime.hpp b/solid/system/nanotime.hpp index cc138aec6..b2b2b3ebd 100644 --- a/solid/system/nanotime.hpp +++ b/solid/system/nanotime.hpp @@ -62,7 +62,7 @@ struct NanoTime : public timespec { explicit operator bool() const noexcept { - return tv_sec == 0 && tv_nsec == 0; + return tv_sec != 0 or tv_nsec != 0; } template diff --git a/solid/utility/threadpool.hpp b/solid/utility/threadpool.hpp index f1416f41d..08d77be5d 100644 --- a/solid/utility/threadpool.hpp +++ b/solid/utility/threadpool.hpp @@ -510,7 +510,7 @@ class ThreadPool : NonCopyable { void notifyWhilePushOne() noexcept { event_ = to_underlying(EventE::Fill); - ++consume_count_; + consume_count_.fetch_add(1); std::atomic_notify_all(&consume_count_); } @@ -654,19 +654,19 @@ class ThreadPool : NonCopyable { using AtomicIndexT = std::atomic_size_t; using AtomicIndexValueT = std::atomic_size_t::value_type; - alignas(hardware_destructive_interference_size * 2) AtomicIndexT push_one_index_{0}; - alignas(hardware_destructive_interference_size * 2) AtomicIndexT pop_one_index_{0}; + alignas(hardware_destructive_interference_size) AtomicIndexT push_one_index_{0}; + alignas(hardware_destructive_interference_size) AtomicIndexT pop_one_index_{0}; ThreadVectorT threads_; std::atomic running_{false}; std::tuple pushOneIndex() noexcept { - const auto index = push_one_index_.fetch_add(1); + const auto index = push_one_index_.fetch_add(1, std::memory_order_relaxed); return {index % one_.capacity_, computeCounter(index, one_.capacity_)}; } std::tuple popOneIndex() noexcept { - const auto index = pop_one_index_.fetch_add(1); + const auto index = pop_one_index_.fetch_add(1, std::memory_order_relaxed); return {index % one_.capacity_, computeCounter(index, one_.capacity_)}; } @@ -678,7 +678,7 @@ class ThreadPool : NonCopyable { void commitAllId(const uint64_t _id) { uint64_t id = _id - 1; - while (!all_.commited_index_.compare_exchange_weak(id, _id)) { + while (!all_.commited_index_.compare_exchange_weak(id, _id, std::memory_order_relaxed, std::memory_order_relaxed)) { id = _id - 1; cpu_pause(); } @@ -1228,7 +1228,7 @@ bool ThreadPool::tryConsumeAnAllTask(AtomicCounterT* _p // used by any one task. This is guranteed because when adding a new one task, // before attaching the last commited_all_index to the current one task, // we're atomicaly marking the one stub as Pushing. - const auto commited_all_index = all_.commited_index_.load(); + const auto commited_all_index = all_.commited_index_.load(std::memory_order_relaxed); if (_pcounter && _pcounter->load(/* std::memory_order_relaxed */) == _count) { // NOTE: this is to ensure that pushOnes and pushAlls from @@ -1288,7 +1288,7 @@ void ThreadPool::doPushOne(Tsk&& _task, ContextStub* _p rstub.task(std::forward(_task)); rstub.pcontext_ = _pctx; - rstub.all_id_ = all_.commited_index_.load(); + rstub.all_id_ = all_.commited_index_.load(std::memory_order_relaxed); if (_pctx) { _pctx->acquire(); From 87891adfaeee197e0956463437608577870a1cf1 Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Sun, 19 Oct 2025 11:28:58 +0300 Subject: [PATCH 10/56] working on different improvements --- solid/frame/aio/aioreactor.hpp | 46 ++++++++++++++++++------------ solid/frame/aio/src/aioreactor.cpp | 21 ++++++++------ solid/frame/reactorbase.hpp | 4 +-- solid/utility/any.hpp | 14 ++++++++- solid/utility/event.hpp | 4 +++ solid/utility/function.hpp | 17 ++++++++++- 6 files changed, 74 insertions(+), 32 deletions(-) diff --git a/solid/frame/aio/aioreactor.hpp b/solid/frame/aio/aioreactor.hpp index 529236baa..1ef2c8ae6 100644 --- a/solid/frame/aio/aioreactor.hpp +++ b/solid/frame/aio/aioreactor.hpp @@ -10,6 +10,8 @@ #pragma once +#include +#include #include #include "solid/frame/aio/aiocommon.hpp" @@ -52,6 +54,7 @@ struct ReactorStatistic : ReactorStatisticBase { std::atomic_size_t max_exec_size_; std::atomic_size_t actor_count_; std::atomic_size_t max_actor_count_; + std::atomic_size_t complete_events_total_ns_{0}; void actorCount(const size_t _count) { @@ -122,16 +125,17 @@ class Reactor : public frame::ReactorBase { #else using MutexT = mutex; #endif - const size_t wake_capacity_; - ReactorStatistic& rstatistic_; - size_t actor_count_{0}; - size_t current_exec_size_{0}; - size_t pop_wake_index_{0}; - std::atomic_size_t pending_wake_count_{0}; - std::atomic_size_t push_wake_index_{0}; + const size_t wake_capacity_; + ReactorStatistic& rstatistic_; + size_t actor_count_{0}; + size_t current_exec_size_{0}; + size_t pop_wake_index_{0}; + /* alignas(hardware_destructive_interference_size) */ std::atomic_size_t pending_wake_count_{0}; + /* alignas(hardware_destructive_interference_size) */ std::atomic_size_t push_wake_index_{0}; public: - using StatisticT = ReactorStatistic; + using StatisticT = ReactorStatistic; + // using EventFunctionT = solid::Function; using EventFunctionT = solid::Function; bool start(); @@ -144,7 +148,7 @@ class Reactor : public frame::ReactorBase { std::tuple pushWakeIndex() noexcept { - const auto index = push_wake_index_.fetch_add(1); + const auto index = push_wake_index_.fetch_add(1, std::memory_order_relaxed); return {index % wake_capacity_, frame::impl::computeCounter(index, wake_capacity_)}; } @@ -368,8 +372,8 @@ class Reactor : public impl::Reactor { using WakeStubT = impl::WakeStub; using ExecQueueT = Queue; - ExecQueueT exec_q_; - std::unique_ptr wake_arr_; + ExecQueueT exec_q_; + alignas(hardware_destructive_interference_size) std::unique_ptr wake_arr_; public: using ActorT = Actor; @@ -395,7 +399,7 @@ class Reactor : public impl::Reactor { rstub.reset(uid, _revent, std::move(_ract), &_rsvc); - notify = pending_wake_count_.fetch_add(1) == 0; + notify = pending_wake_count_.fetch_add(1, std::memory_order_relaxed) == 0; rstub.notifyWhilePush(); } @@ -424,7 +428,7 @@ class Reactor : public impl::Reactor { rstub.reset(uid, std::move(_revent), std::move(_ract), &_rsvc); - notify = pending_wake_count_.fetch_add(1) == 0; + notify = pending_wake_count_.fetch_add(1, std::memory_order_relaxed) == 0; rstub.notifyWhilePush(); } @@ -452,7 +456,7 @@ class Reactor : public impl::Reactor { rstub.reset(_ractuid, _revent); - notify = pending_wake_count_.fetch_add(1) == 0; + notify = pending_wake_count_.fetch_add(1, std::memory_order_relaxed) == 0; rstub.notifyWhilePush(); } @@ -478,7 +482,7 @@ class Reactor : public impl::Reactor { rstub.reset(_ractuid, std::move(_revent)); - notify = pending_wake_count_.fetch_add(1) == 0; + notify = pending_wake_count_.fetch_add(1, std::memory_order_relaxed) == 0; rstub.notifyWhilePush(); } @@ -524,9 +528,10 @@ class Reactor : public impl::Reactor { void doCompleteEvents(NanoTime const& _rcrttime, const UniqueId& _completion_handler_uid) override { - solid_log(logger, Verbose, ""); + // TODO:clean + // auto const start_time = std::chrono::high_resolution_clock::now(); - if (pending_wake_count_.load(/* std::memory_order_relaxed */) && !emptyFreeUids()) { + if (pending_wake_count_.load(std::memory_order_relaxed) && !emptyFreeUids()) { std::lock_guard lock(mutex()); pushFreeUids(); } @@ -543,7 +548,7 @@ class Reactor : public impl::Reactor { addActor(rstub.uid_, *rstub.pservice_, std::move(rstub.actor_ptr_)); } exec_q_.push(ExecStubT(rstub.uid_, &call_actor_on_event, _completion_handler_uid, std::move(rstub.event_))); - --pending_wake_count_; + pending_wake_count_.fetch_sub(1, std::memory_order_relaxed); ++pop_wake_index_; rstub.clear(); rstub.notifyWhilePop(); @@ -551,6 +556,10 @@ class Reactor : public impl::Reactor { break; } } + // TODO:clean + // auto const stop_time = std::chrono::high_resolution_clock::now(); + // uint64_t const ns = std::chrono::duration_cast(stop_time - start_time).count(); + // solid_statistic_add(rstatistic_.complete_events_total_ns_, ns); } size_t doCompleteExec(NanoTime const& _rcrttime) override @@ -563,7 +572,6 @@ class Reactor : public impl::Reactor { while ((sz--) != 0) { auto& rexec(exec_q_.front()); - solid_log(logger, Verbose, sz << " qsz = " << exec_q_.size()); if (isValid(rexec.actor_uid_, rexec.completion_handler_uid_)) { ctx.clearError(); update(ctx, static_cast(rexec.completion_handler_uid_.index), static_cast(rexec.actor_uid_.index)); diff --git a/solid/frame/aio/src/aioreactor.cpp b/solid/frame/aio/src/aioreactor.cpp index bd9cabf2d..4b4965628 100644 --- a/solid/frame/aio/src/aioreactor.cpp +++ b/solid/frame/aio/src/aioreactor.cpp @@ -10,6 +10,7 @@ #include #include "solid/system/common.hpp" +#include "solid/system/statistic.hpp" #if defined(SOLID_USE_EPOLL) @@ -64,9 +65,7 @@ using namespace std; -namespace solid { -namespace frame { -namespace aio { +namespace solid::frame::aio { namespace { @@ -439,9 +438,9 @@ void Reactor::run() #if defined(SOLID_USE_EPOLL2) waittime = impl_->computeWaitDuration(impl_->current_time_, current_exec_size_ == 0 && pending_wake_count_.load() == 0); - solid_log(logger, Verbose, "epoll_wait wait = " << waittime << ' ' << impl_->reactor_fd_ << ' ' << impl_->event_vec_.size()); - selcnt = epoll_pwait2(impl_->reactor_fd_, impl_->event_vec_.data(), static_cast(impl_->event_vec_.size()), waittime != NanoTime::max() ? &waittime : nullptr, nullptr); - + // solid_log(logger, Verbose, "epoll_wait wait = " << waittime << ' ' << impl_->reactor_fd_ << ' ' << impl_->event_vec_.size()); + selcnt = epoll_pwait2(impl_->reactor_fd_, impl_->event_vec_.data(), static_cast(impl_->event_vec_.size()), waittime != NanoTime::max() ? &waittime : nullptr, nullptr); + auto const start_time = std::chrono::high_resolution_clock::now(); #elif defined(SOLID_USE_EPOLL) waitmsec = impl_->computeWaitDuration(impl_->current_time_, current_exec_size_ == 0 && pending_wake_count_.load() == 0); @@ -487,6 +486,7 @@ void Reactor::run() const auto elapsed_io = duration_cast(high_resolution_clock::now() - start).count(); #endif doCompleteTimer(impl_->current_time_); + #ifdef SOLID_AIO_TRACE_DURATION const auto elapsed_timer = duration_cast(high_resolution_clock::now() - start).count(); #endif @@ -495,6 +495,10 @@ void Reactor::run() const auto elapsed_event = duration_cast(high_resolution_clock::now() - start).count(); #endif const auto execnt = doCompleteExec(impl_->current_time_); + + auto const stop_time = std::chrono::high_resolution_clock::now(); + uint64_t const ns = std::chrono::duration_cast(stop_time - start_time).count(); + solid_statistic_add(rstatistic_.complete_events_total_ns_, ns); #ifdef SOLID_AIO_TRACE_DURATION const auto elapsed_total = duration_cast(high_resolution_clock::now() - start).count(); @@ -1441,6 +1445,7 @@ std::ostream& ReactorStatistic::print(std::ostream& _ros) const _ros << " max_exec_size = " << max_exec_size_; _ros << " actor_count = " << actor_count_; _ros << " max_actor_count = " << max_actor_count_; + _ros << " complete_events_total_ms = " << (complete_events_total_ns_ / 1000000u); return _ros; } @@ -1458,6 +1463,4 @@ void ReactorStatistic::clear() max_actor_count_ = 0; } -} // namespace aio -} // namespace frame -} // namespace solid +} // namespace solid::frame::aio diff --git a/solid/frame/reactorbase.hpp b/solid/frame/reactorbase.hpp index 6a3be8295..644978878 100644 --- a/solid/frame/reactorbase.hpp +++ b/solid/frame/reactorbase.hpp @@ -56,10 +56,11 @@ inline constexpr static auto computeCounter(const IndexT _index, const size_t _c return (_index / _capacity) & std::numeric_limits::max(); } -struct WakeStubBase { +class WakeStubBase { AtomicCounterT produce_count_{0}; AtomicCounterT consume_count_{static_cast(-1)}; +public: template void waitWhilePush(Statistic& _rstats, const AtomicCounterValueT _count, const size_t _spin_count = 1) noexcept { @@ -80,7 +81,6 @@ struct WakeStubBase { void notifyWhilePush() noexcept { ++consume_count_; - std::atomic_notify_all(&consume_count_); } void notifyWhilePop() noexcept diff --git a/solid/utility/any.hpp b/solid/utility/any.hpp index 6eb02c89c..0aa983ab5 100644 --- a/solid/utility/any.hpp +++ b/solid/utility/any.hpp @@ -9,7 +9,7 @@ // #pragma once - +#define SOLID_THROW_ON_BIG_ANY #include #include #include @@ -176,6 +176,9 @@ RepresentationE do_copy( _rpsmall_rtti = &small_rtti; return RepresentationE::Small; } else { +#if defined(SOLID_THROW_ON_BIG_ANY) + solid_throw("Big Any"); +#endif _rpto_big = ::new T(*static_cast(_pfrom)); _rpbig_rtti = &big_rtti; return RepresentationE::Big; @@ -204,11 +207,17 @@ RepresentationE do_move( _rpsmall_rtti = &small_rtti; return RepresentationE::Small; } else { +#if defined(SOLID_THROW_ON_BIG_ANY) + solid_throw("Big Any"); +#endif _rpto_big = ::new T{std::move(*static_cast(_pfrom))}; _rpbig_rtti = &big_rtti; return RepresentationE::Big; } } else if constexpr (std::is_move_constructible_v) { +#if defined(SOLID_THROW_ON_BIG_ANY) + solid_throw("Big Any"); +#endif _rpto_big = ::new T{std::move(*static_cast(_pfrom))}; _rpbig_rtti = &big_rtti; return RepresentationE::Big; @@ -649,6 +658,9 @@ class Any { return rval; } else { +#if defined(SOLID_THROW_ON_BIG_ANY) + solid_throw("Big Any"); +#endif T* const ptr = ::new T(std::forward(_args)...); storage_.big_.ptr_ = ptr; storage_.big_.prtti_ = &any_impl::big_rtti; diff --git a/solid/utility/event.hpp b/solid/utility/event.hpp index eddf6e8e2..f38c8fc3f 100644 --- a/solid/utility/event.hpp +++ b/solid/utility/event.hpp @@ -9,6 +9,7 @@ // #pragma once +#define SOLID_THROW_ON_BIG_EVENT #include #include @@ -282,6 +283,9 @@ class EventBase { template T& doEmplaceBig(Args&&... _args) { +#if defined(SOLID_THROW_ON_BIG_EVENT) + solid_throw("Big Event"); +#endif T* const ptr = ::new T(std::forward(_args)...); pdata_ = ptr; rtti_.pbig_ = &any_impl::big_rtti; diff --git a/solid/utility/function.hpp b/solid/utility/function.hpp index 9771d9891..855d2add0 100644 --- a/solid/utility/function.hpp +++ b/solid/utility/function.hpp @@ -8,7 +8,7 @@ // See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt. // #pragma once - +#define SOLID_THROW_ON_BIG_FUNCTION #include #include #include @@ -156,11 +156,17 @@ RepresentationE do_copy( _rpsmall_rtti = &small_rtti; return RepresentationE::Small; } else { +#if defined(SOLID_THROW_ON_BIG_FUNCTION) + solid_throw("Big Function"); +#endif _rpto_big = ::new T(*static_cast(_pfrom)); _rpbig_rtti = &big_rtti; return RepresentationE::Big; } } else if constexpr (std::is_trivially_constructible_v || std::is_copy_constructible_v) { +#if defined(SOLID_THROW_ON_BIG_FUNCTION) + solid_throw("Big Function"); +#endif _rpto_big = ::new T(*static_cast(_pfrom)); _rpbig_rtti = &big_rtti; return RepresentationE::Big; @@ -184,11 +190,17 @@ RepresentationE do_move( _rpsmall_rtti = &small_rtti; return RepresentationE::Small; } else { +#if defined(SOLID_THROW_ON_BIG_FUNCTION) + solid_throw("Big Function"); +#endif _rpto_big = ::new T{std::move(*static_cast(_pfrom))}; _rpbig_rtti = &big_rtti; return RepresentationE::Big; } } else if constexpr (std::is_move_constructible_v) { +#if defined(SOLID_THROW_ON_BIG_FUNCTION) + solid_throw("Big Function"); +#endif _rpto_big = ::new T{std::move(*static_cast(_pfrom))}; _rpbig_rtti = &big_rtti; return RepresentationE::Big; @@ -533,6 +545,9 @@ class Function { return rval; } else { +#if defined(SOLID_THROW_ON_BIG_FUNCTION) + solid_throw("Big Function"); +#endif T* const ptr = ::new T(std::forward(_args)...); storage_.big_.ptr_ = ptr; storage_.big_.prtti_ = &fnc_impl::big_rtti; From 64d4d083a803d838a132011d0710b21d484d83ec Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Sat, 25 Oct 2025 10:17:32 +0300 Subject: [PATCH 11/56] keep working on improving both function and aioreactorx --- solid/frame/aio/aioreactor.hpp | 42 ++- solid/frame/aio/src/aioreactor.cpp | 79 +++--- solid/utility/any.hpp | 26 +- solid/utility/event.hpp | 22 +- solid/utility/function.hpp | 263 ++++++++++-------- .../utility/test/test_function_any_speed.cpp | 2 +- 6 files changed, 229 insertions(+), 205 deletions(-) diff --git a/solid/frame/aio/aioreactor.hpp b/solid/frame/aio/aioreactor.hpp index 1ef2c8ae6..22588fa4b 100644 --- a/solid/frame/aio/aioreactor.hpp +++ b/solid/frame/aio/aioreactor.hpp @@ -130,12 +130,11 @@ class Reactor : public frame::ReactorBase { size_t actor_count_{0}; size_t current_exec_size_{0}; size_t pop_wake_index_{0}; - /* alignas(hardware_destructive_interference_size) */ std::atomic_size_t pending_wake_count_{0}; + /* alignas(hardware_destructive_interference_size) */ std::atomic_size_t pending_wake_count_{1u}; /* alignas(hardware_destructive_interference_size) */ std::atomic_size_t push_wake_index_{0}; public: - using StatisticT = ReactorStatistic; - // using EventFunctionT = solid::Function; + using StatisticT = ReactorStatistic; using EventFunctionT = solid::Function; bool start(); @@ -251,7 +250,6 @@ class Reactor : public frame::ReactorBase { void doCompleteIo(NanoTime const& _rcrttime, const size_t _sz); void doCompleteTimer(NanoTime const& _rcrttime); - void doCompleteEvents(ReactorContext const& _rctx); void doCompleteEvents(NanoTime const& _rcrttime); void doStoreSpecific(); void doClearSpecific(); @@ -399,9 +397,9 @@ class Reactor : public impl::Reactor { rstub.reset(uid, _revent, std::move(_ract), &_rsvc); - notify = pending_wake_count_.fetch_add(1, std::memory_order_relaxed) == 0; - rstub.notifyWhilePush(); + + notify = pending_wake_count_.fetch_add(1, std::memory_order_release) == 0; } if (notify) { { @@ -428,9 +426,9 @@ class Reactor : public impl::Reactor { rstub.reset(uid, std::move(_revent), std::move(_ract), &_rsvc); - notify = pending_wake_count_.fetch_add(1, std::memory_order_relaxed) == 0; - rstub.notifyWhilePush(); + + notify = pending_wake_count_.fetch_add(1, std::memory_order_release) == 0; } if (notify) { @@ -456,9 +454,9 @@ class Reactor : public impl::Reactor { rstub.reset(_ractuid, _revent); - notify = pending_wake_count_.fetch_add(1, std::memory_order_relaxed) == 0; - rstub.notifyWhilePush(); + + notify = pending_wake_count_.fetch_add(1, std::memory_order_release) == 0; } if (notify) { { @@ -482,9 +480,9 @@ class Reactor : public impl::Reactor { rstub.reset(_ractuid, std::move(_revent)); - notify = pending_wake_count_.fetch_add(1, std::memory_order_relaxed) == 0; - rstub.notifyWhilePush(); + + notify = pending_wake_count_.fetch_add(1, std::memory_order_release) == 0; } if (notify) { { @@ -528,15 +526,8 @@ class Reactor : public impl::Reactor { void doCompleteEvents(NanoTime const& _rcrttime, const UniqueId& _completion_handler_uid) override { - // TODO:clean - // auto const start_time = std::chrono::high_resolution_clock::now(); - - if (pending_wake_count_.load(std::memory_order_relaxed) && !emptyFreeUids()) { - std::lock_guard lock(mutex()); - pushFreeUids(); - } - ReactorContext ctx(context(_rcrttime)); + bool has_events = false; while (true) { const size_t index = pop_wake_index_ % wake_capacity_; @@ -548,18 +539,19 @@ class Reactor : public impl::Reactor { addActor(rstub.uid_, *rstub.pservice_, std::move(rstub.actor_ptr_)); } exec_q_.push(ExecStubT(rstub.uid_, &call_actor_on_event, _completion_handler_uid, std::move(rstub.event_))); - pending_wake_count_.fetch_sub(1, std::memory_order_relaxed); ++pop_wake_index_; + has_events = true; rstub.clear(); rstub.notifyWhilePop(); } else { break; } } - // TODO:clean - // auto const stop_time = std::chrono::high_resolution_clock::now(); - // uint64_t const ns = std::chrono::duration_cast(stop_time - start_time).count(); - // solid_statistic_add(rstatistic_.complete_events_total_ns_, ns); + + if (has_events and not emptyFreeUids()) { + std::lock_guard lock(mutex()); + pushFreeUids(); + } } size_t doCompleteExec(NanoTime const& _rcrttime) override diff --git a/solid/frame/aio/src/aioreactor.cpp b/solid/frame/aio/src/aioreactor.cpp index 4b4965628..dec64fc0f 100644 --- a/solid/frame/aio/src/aioreactor.cpp +++ b/solid/frame/aio/src/aioreactor.cpp @@ -7,6 +7,7 @@ // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt. // +#include #include #include "solid/system/common.hpp" @@ -406,6 +407,12 @@ bool Reactor::start() } } +//----------------------------------------------------------------------------- +inline void Reactor::doCompleteEvents(NanoTime const& _rcrttime) +{ + doCompleteEvents(_rcrttime, impl_->dummyCompletionHandlerUid()); +} + //----------------------------------------------------------------------------- /*NOTE: @@ -420,7 +427,7 @@ bool Reactor::start() to be delivered to the actor. */ -// #define SOLID_AIO_TRACE_DURATION +#define SOLID_AIO_TRACE_DURATION void Reactor::run() { using namespace std::chrono; @@ -430,33 +437,47 @@ void Reactor::run() bool running = true; int waitmsec; NanoTime waittime; + auto previous_wake_count = pending_wake_count_.load(); while (running) { impl_->current_time_ = NanoTime::nowSteady(); - crtload = actor_count_ + impl_->device_count_ + current_exec_size_; + crtload = actor_count_ + impl_->device_count_ + current_exec_size_; + bool can_wait = current_exec_size_ == 0u; + { + decltype(previous_wake_count) new_count = not can_wait; + auto current_wake_count = pending_wake_count_.exchange(new_count, std::memory_order_acquire); + + can_wait = can_wait and (current_wake_count == previous_wake_count); + previous_wake_count = new_count; + } + #if defined(SOLID_USE_EPOLL2) - waittime = impl_->computeWaitDuration(impl_->current_time_, current_exec_size_ == 0 && pending_wake_count_.load() == 0); + + waittime + = impl_->computeWaitDuration(impl_->current_time_, can_wait); // solid_log(logger, Verbose, "epoll_wait wait = " << waittime << ' ' << impl_->reactor_fd_ << ' ' << impl_->event_vec_.size()); - selcnt = epoll_pwait2(impl_->reactor_fd_, impl_->event_vec_.data(), static_cast(impl_->event_vec_.size()), waittime != NanoTime::max() ? &waittime : nullptr, nullptr); - auto const start_time = std::chrono::high_resolution_clock::now(); + selcnt = epoll_pwait2(impl_->reactor_fd_, impl_->event_vec_.data(), static_cast(impl_->event_vec_.size()), waittime != NanoTime::max() ? &waittime : nullptr, nullptr); #elif defined(SOLID_USE_EPOLL) - waitmsec = impl_->computeWaitDuration(impl_->current_time_, current_exec_size_ == 0 && pending_wake_count_.load() == 0); + waitmsec + = impl_->computeWaitDuration(impl_->current_time_, can_wait); solid_log(logger, Verbose, "epoll_wait wait = " << waitmsec); selcnt = epoll_wait(impl_->reactor_fd_, impl_->event_vec_.data(), static_cast(impl_->event_vec_.size()), waitmsec); #elif defined(SOLID_USE_KQUEUE) - waittime = impl_->computeWaitDuration(impl_->current_time_, current_exec_size_ == 0 && pending_wake_count_.load() == 0); + waittime + = impl_->computeWaitDuration(impl_->current_time_, can_wait); solid_log(logger, Verbose, "kqueue wait = " << waittime); selcnt = kevent(impl_->reactor_fd_, nullptr, 0, impl_->event_vec_.data(), static_cast(impl_->event_vec_.size()), waittime != NanoTime::max() ? &waittime : nullptr); #elif defined(SOLID_USE_WSAPOLL) - waitmsec = impl_->computeWaitDuration(impl_->current_time_, current_exec_size_ == 0 && pending_wake_count_.load() == 0); + waitmsec + = impl_->computeWaitDuration(impl_->current_time_, can_wait); solid_log(logger, Verbose, "wsapoll wait msec = " << waitmsec); selcnt = WSAPoll(impl_->event_vec_.data(), impl_->event_vec_.size(), waitmsec); @@ -464,9 +485,9 @@ void Reactor::run() if (waittime) { impl_->current_time_ = NanoTime::nowSteady(); } -#ifdef SOLID_AIO_TRACE_DURATION - const auto start = high_resolution_clock::now(); -#endif + + doCompleteEvents(impl_->current_time_); // See NOTE above + #if defined(SOLID_USE_WSAPOLL) if (selcnt > 0 || impl_->connect_vec_.size()) { #else @@ -482,31 +503,18 @@ void Reactor::run() } else { solid_log(logger, Verbose, "epoll_wait done"); } -#ifdef SOLID_AIO_TRACE_DURATION - const auto elapsed_io = duration_cast(high_resolution_clock::now() - start).count(); -#endif - doCompleteTimer(impl_->current_time_); -#ifdef SOLID_AIO_TRACE_DURATION - const auto elapsed_timer = duration_cast(high_resolution_clock::now() - start).count(); -#endif - doCompleteEvents(impl_->current_time_); // See NOTE above -#ifdef SOLID_AIO_TRACE_DURATION - const auto elapsed_event = duration_cast(high_resolution_clock::now() - start).count(); + doCompleteTimer(impl_->current_time_); +#if defined(SOLID_AIO_TRACE_DURATION) + auto const start_time = std::chrono::high_resolution_clock::now(); #endif - const auto execnt = doCompleteExec(impl_->current_time_); + doCompleteExec(impl_->current_time_); +#if defined(SOLID_AIO_TRACE_DURATION) auto const stop_time = std::chrono::high_resolution_clock::now(); uint64_t const ns = std::chrono::duration_cast(stop_time - start_time).count(); solid_statistic_add(rstatistic_.complete_events_total_ns_, ns); -#ifdef SOLID_AIO_TRACE_DURATION - const auto elapsed_total = duration_cast(high_resolution_clock::now() - start).count(); - - if (elapsed_total >= 6000) { - solid_log(logger, Warning, "reactor loop duration: io " << elapsed_io << " timers " << elapsed_timer << " events " << elapsed_event << " total " << elapsed_total << " execnt " << execnt); - } #endif - (void)execnt; running = impl_->running_ || (actor_count_ != 0) || current_exec_size_ != 0; } @@ -911,18 +919,6 @@ void Reactor::doCompleteTimer(NanoTime const& _rcrttime) }); } -//----------------------------------------------------------------------------- -void Reactor::doCompleteEvents(ReactorContext const& _rctx) -{ - doCompleteEvents(_rctx.nanoTime(), impl_->dummyCompletionHandlerUid()); -} - -void Reactor::doCompleteEvents(NanoTime const& _rcrttime) -{ - ReactorContext ctx(*this, _rcrttime); - doCompleteEvents(ctx); -} - //----------------------------------------------------------------------------- /*static*/ void Reactor::call_actor_on_event(ReactorContext& _rctx, EventBase&& _uevent) @@ -1392,7 +1388,6 @@ void EventHandler::write(impl::Reactor& _rreactor) rthis.contextBind(_rctx); rthis.reactor(_rctx).modDevice(_rctx, rthis.dev_, ReactorWaitRequestE::Read); #endif - rthis.reactor(_rctx).doCompleteEvents(_rctx); } //----------------------------------------------------------------------------- diff --git a/solid/utility/any.hpp b/solid/utility/any.hpp index 0aa983ab5..74e51e786 100644 --- a/solid/utility/any.hpp +++ b/solid/utility/any.hpp @@ -9,7 +9,7 @@ // #pragma once -#define SOLID_THROW_ON_BIG_ANY +// #define SOLID_THROW_ON_BIG_ANY #include #include #include @@ -22,18 +22,8 @@ #include "solid/utility/typetraits.hpp" namespace solid { -inline constexpr size_t any_default_data_size = 3 * sizeof(void*); -inline constexpr size_t any_size_from_sizeof(const size_t _sizeof) -{ - return _sizeof - sizeof(void*); -} -template -inline constexpr const T& any_max(const T& a, const T& b) -{ - return (a < b) ? b : a; -} -template +template class Any; template @@ -277,9 +267,11 @@ const void* do_get_if(const std::type_index& _type_index, const void* _pdata) constexpr size_t compute_small_capacity(const size_t _req_capacity) { + static constexpr size_t default_total_size = 32u; + const size_t end_capacity = sizeof(uintptr_t) + sizeof(void*); - const size_t req_capacity = any_max(_req_capacity, any_max(end_capacity, sizeof(max_align_t)) - end_capacity); - const size_t tot_capacity = padded_size(req_capacity + sizeof(uintptr_t) + sizeof(void*), alignof(max_align_t)); + const size_t req_capacity = std::max(_req_capacity, std::max(end_capacity, sizeof(max_align_t)) - end_capacity); + const size_t tot_capacity = std::max(default_total_size, padded_size(req_capacity + sizeof(uintptr_t) + sizeof(void*), alignof(max_align_t))); return tot_capacity - end_capacity; } @@ -288,7 +280,7 @@ constexpr size_t compute_small_capacity(const size_t _req_capacity) template class Any { - static constexpr size_t small_capacity = any_impl::compute_small_capacity(any_max(sizeof(void*) * 3, DataSize)); + static constexpr size_t small_capacity = any_impl::compute_small_capacity(DataSize); static constexpr size_t big_padding = small_capacity - sizeof(void*); struct Small { @@ -679,12 +671,12 @@ inline void swap(Any& _a1, Any& _a2) noexcept _a1.swap(_a2); } -template +template Any make_any(Args&&... _args) { return Any{std::in_place_type, std::forward(_args)...}; } -template +template Any make_any(std::initializer_list _ilist, Args&&... _args) { return Any{std::in_place_type, _ilist, std::forward(_args)...}; diff --git a/solid/utility/event.hpp b/solid/utility/event.hpp index f38c8fc3f..6c1bae3c9 100644 --- a/solid/utility/event.hpp +++ b/solid/utility/event.hpp @@ -9,6 +9,7 @@ // #pragma once +#include #define SOLID_THROW_ON_BIG_EVENT #include @@ -58,8 +59,10 @@ class EventBase { void resetData() { switch (representation()) { - case any_impl::RepresentationE::Small: - rtti_.psmall_->pdestroy_fnc_(pdata_); + [[likely]] case any_impl::RepresentationE::Small: + if (rtti_.psmall_->pdestroy_fnc_) { + rtti_.psmall_->pdestroy_fnc_(pdata_); + } break; case any_impl::RepresentationE::Big: rtti_.pbig_->pdestroy_fnc_(pdata_); @@ -456,9 +459,22 @@ class Event<0> : public EventBase { } }; +namespace event_impl { +constexpr size_t compute_small_capacity(const size_t _req_capacity) +{ + static constexpr size_t default_total_size = 32u; + + const size_t end_capacity = sizeof(uintptr_t) + sizeof(void*); + const size_t req_capacity = std::max(_req_capacity, std::max(end_capacity, sizeof(max_align_t)) - end_capacity); + const size_t tot_capacity = std::max(default_total_size, padded_size(req_capacity + sizeof(uintptr_t) + sizeof(void*), alignof(max_align_t))); + + return tot_capacity - end_capacity; +} +} // namespace event_impl + template class Event : public EventBase { - static constexpr size_t small_capacity = any_impl::compute_small_capacity(any_max(sizeof(void*), SmallSize)); + static constexpr size_t small_capacity = event_impl::compute_small_capacity(SmallSize); union { unsigned char data_[small_capacity]; max_align_t dummy_; diff --git a/solid/utility/function.hpp b/solid/utility/function.hpp index 855d2add0..c42425bc7 100644 --- a/solid/utility/function.hpp +++ b/solid/utility/function.hpp @@ -8,12 +8,14 @@ // See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt. // #pragma once +#include +#include +#include #define SOLID_THROW_ON_BIG_FUNCTION #include #include #include #include -#include #include #include "solid/system/exception.hpp" @@ -22,18 +24,18 @@ #include "solid/utility/typetraits.hpp" namespace solid { + +#if 0 // TODO:remove inline constexpr size_t function_default_data_size = 3 * sizeof(void*); -inline constexpr size_t function_size_from_sizeof(const size_t _sizeof) -{ - return _sizeof - sizeof(void*); -} template inline constexpr const T& function_max(const T& a, const T& b) { return (a < b) ? b : a; } -template +#endif + +template class Function; // undefined template @@ -53,8 +55,9 @@ enum struct RepresentationE : uintptr_t { Small, Big, }; -constexpr uintptr_t representation_mask = 3; -constexpr uintptr_t representation_and_flags_mask = representation_mask /* + (3 << 2)*/; +constexpr uintptr_t representation_mask = 3; +constexpr uintptr_t representation_and_flags_mask = representation_mask; +constexpr uintptr_t reversed_representation_and_flags_mask = ~representation_mask; template struct SmallRTTI; @@ -65,8 +68,8 @@ struct BigRTTI { using SmallRTTIT = SmallRTTI; using DestroyFncT = void(void*); - using CopyFncT = RepresentationE(const void*, void*, const size_t, const SmallRTTIT*&, void*&, const BigRTTIT*&); - using MoveFncT = RepresentationE(void*, void*, const size_t, const SmallRTTIT*&, void*&, const BigRTTIT*&); + using CopyFncT = RepresentationE(const void*, void*, const size_t, uintptr_t&, void*&, uintptr_t&); + using MoveFncT = RepresentationE(void*, void*, const size_t, uintptr_t&, void*&, uintptr_t&); using InvokeFncT = R(const void*, ArgTypes&&...); template @@ -87,15 +90,15 @@ template struct SmallRTTI { using BigRTTIT = BigRTTI; using SmallRTTIT = SmallRTTI; - using DestroyFncT = void(void*) noexcept; - using CopyFncT = RepresentationE(const void*, void*, const size_t, const SmallRTTIT*&, void*&, const BigRTTIT*&); - using MoveFncT = RepresentationE(void*, void*, const size_t, const SmallRTTIT*&, void*&, const BigRTTIT*&); + using DestroyFncT = void(void*); + using CopyFncT = RepresentationE(const void*, void*, const size_t, uintptr_t&, void*&, uintptr_t&); + using MoveFncT = RepresentationE(void*, void*, const size_t, uintptr_t&, void*&, uintptr_t&); using InvokeFncT = R(const void*, ArgTypes&&...); template - static void destroy(void* const _what) noexcept + static void destroy(void* const _what) { - static_cast(_what)->~T(); + std::destroy_at(static_cast(_what)); } InvokeFncT* pinvoke_fnc_; @@ -109,58 +112,64 @@ struct SmallRTTI { template R do_invoke(const void* _pvalue, ArgTypes&&... _args) { - return std::invoke(*const_cast(static_cast(_pvalue)), std::forward(_args)...); + return std::invoke(*const_cast(static_cast(_pvalue)), static_cast(_args)... /* std::forward(_args)... */); } template RepresentationE do_copy( const void* _pfrom, - void* _pto_small, const size_t _small_cap, const SmallRTTI*& _rpsmall_rtti, - void*& _rpto_big, const BigRTTI*& _rpbig_rtti); + void* _pto_small, const size_t _small_cap, uintptr_t& _rpsmall_rtti, + void*& _rpto_big, uintptr_t& _rpbig_rtti); template RepresentationE do_move( void* _pfrom, - void* _pto_small, const size_t _small_cap, const SmallRTTI*& _rpsmall_rtti, - void*& _rpto_big, const BigRTTI*& _rpbig_rtti); + void* _pto_small, const size_t _small_cap, uintptr_t& _rpsmall_rtti, + void*& _rpto_big, uintptr_t& _rpbig_rtti); template RepresentationE do_move_big( void* _pfrom, - void* _pto_small, const size_t _small_cap, const SmallRTTI*& _rpsmall_rtti, - void*& _rpto_big, const BigRTTI*& _rpbig_rtti); + void* _pto_small, const size_t _small_cap, uintptr_t& _rpsmall_rtti, + void*& _rpto_big, uintptr_t& _rpbig_rtti); template inline constexpr BigRTTI big_rtti = { - &do_invoke, - &BigRTTI::template destroy, &do_copy, &do_move_big, - std::is_copy_constructible_v, std::is_move_constructible_v}; + .pinvoke_fnc_ = &do_invoke, + .pdestroy_fnc_ = &BigRTTI::template destroy, + .pcopy_fnc_ = &do_copy, + .pmove_fnc_ = &do_move_big, + .is_copyable_ = std::is_copy_constructible_v, + .is_movable_ = std::is_move_constructible_v}; template inline constexpr SmallRTTI small_rtti = { - &do_invoke, - &SmallRTTI::template destroy, &do_copy, &do_move, - std::is_copy_constructible_v, std::is_move_constructible_v}; + .pinvoke_fnc_ = &do_invoke, + .pdestroy_fnc_ = std::is_trivially_copyable_v ? nullptr : &SmallRTTI::template destroy, + .pcopy_fnc_ = &do_copy, + .pmove_fnc_ = &do_move, + .is_copyable_ = std::is_copy_constructible_v, + .is_movable_ = std::is_move_constructible_v}; template RepresentationE do_copy( const void* _pfrom, - void* _pto_small, const size_t _small_cap, const SmallRTTI*& _rpsmall_rtti, - void*& _rpto_big, const BigRTTI*& _rpbig_rtti) + void* _pto_small, const size_t _small_cap, uintptr_t& _rpsmall_rtti, + void*& _rpto_big, uintptr_t& _rpbig_rtti) { if constexpr (alignof(T) <= alignof(max_align_t) && std::is_copy_constructible_v) { if (sizeof(T) <= _small_cap) { T& rdst = *static_cast(_pto_small); const T& rsrc = *static_cast(_pfrom); ::new (const_cast(static_cast(std::addressof(rdst)))) T(rsrc); - _rpsmall_rtti = &small_rtti; + _rpsmall_rtti = reinterpret_cast(&small_rtti); return RepresentationE::Small; } else { #if defined(SOLID_THROW_ON_BIG_FUNCTION) solid_throw("Big Function"); #endif _rpto_big = ::new T(*static_cast(_pfrom)); - _rpbig_rtti = &big_rtti; + _rpbig_rtti = reinterpret_cast(&big_rtti); return RepresentationE::Big; } } else if constexpr (std::is_trivially_constructible_v || std::is_copy_constructible_v) { @@ -168,7 +177,7 @@ RepresentationE do_copy( solid_throw("Big Function"); #endif _rpto_big = ::new T(*static_cast(_pfrom)); - _rpbig_rtti = &big_rtti; + _rpbig_rtti = reinterpret_cast(&big_rtti); return RepresentationE::Big; } else { solid_throw("Function: contained value not copyable"); @@ -179,22 +188,22 @@ RepresentationE do_copy( template RepresentationE do_move( void* _pfrom, - void* _pto_small, const size_t _small_cap, const SmallRTTI*& _rpsmall_rtti, - void*& _rpto_big, const BigRTTI*& _rpbig_rtti) + void* _pto_small, const size_t _small_cap, uintptr_t& _rpsmall_rtti, + void*& _rpto_big, uintptr_t& _rpbig_rtti) { if constexpr (alignof(T) <= alignof(max_align_t) && std::is_move_constructible_v) { if (sizeof(T) <= _small_cap) { T& rdst = *static_cast(_pto_small); T& rsrc = *static_cast(_pfrom); ::new (const_cast(static_cast(std::addressof(rdst)))) T{std::move(rsrc)}; - _rpsmall_rtti = &small_rtti; + _rpsmall_rtti = reinterpret_cast(&small_rtti); return RepresentationE::Small; } else { #if defined(SOLID_THROW_ON_BIG_FUNCTION) solid_throw("Big Function"); #endif _rpto_big = ::new T{std::move(*static_cast(_pfrom))}; - _rpbig_rtti = &big_rtti; + _rpbig_rtti = reinterpret_cast(&big_rtti); return RepresentationE::Big; } } else if constexpr (std::is_move_constructible_v) { @@ -202,7 +211,7 @@ RepresentationE do_move( solid_throw("Big Function"); #endif _rpto_big = ::new T{std::move(*static_cast(_pfrom))}; - _rpbig_rtti = &big_rtti; + _rpbig_rtti = reinterpret_cast(&big_rtti); return RepresentationE::Big; } else { solid_throw("Function: contained value not movable"); @@ -213,33 +222,35 @@ RepresentationE do_move( template RepresentationE do_move_big( void* _pfrom, - void* _pto_small, const size_t _small_cap, const SmallRTTI*& _rpsmall_rtti, - void*& _rpto_big, const BigRTTI*& _rpbig_rtti) + void* _pto_small, const size_t _small_cap, uintptr_t& _rpsmall_rtti, + void*& _rpto_big, uintptr_t& _rpbig_rtti) { if constexpr (alignof(T) <= alignof(max_align_t) && std::is_move_constructible_v) { if (sizeof(T) <= _small_cap) { T& rdst = *static_cast(_pto_small); T& rsrc = *static_cast(_pfrom); ::new (const_cast(static_cast(std::addressof(rdst)))) T{std::move(rsrc)}; - _rpsmall_rtti = &small_rtti; + _rpsmall_rtti = reinterpret_cast(&small_rtti); return RepresentationE::Small; } else { _rpto_big = static_cast(_pfrom); //::new T{ std::move(*static_cast(_pfrom)) }; - _rpbig_rtti = &big_rtti; + _rpbig_rtti = reinterpret_cast(&big_rtti); return RepresentationE::Big; } } else { _rpto_big = static_cast(_pfrom); //::new T{ std::move(*static_cast(_pfrom)) }; - _rpbig_rtti = &big_rtti; + _rpbig_rtti = reinterpret_cast(&big_rtti); return RepresentationE::Big; } } constexpr size_t compute_small_capacity(const size_t _req_capacity) { - const size_t end_capacity = sizeof(uintptr_t) + sizeof(void*); - const size_t req_capacity = function_max(_req_capacity, function_max(end_capacity, sizeof(max_align_t)) - end_capacity); - const size_t tot_capacity = padded_size(req_capacity + sizeof(uintptr_t) + sizeof(void*), alignof(max_align_t)); + static constexpr size_t default_total_size = 32u; + + const size_t end_capacity = sizeof(void*); + const size_t req_capacity = std::max(_req_capacity, std::max(end_capacity, sizeof(max_align_t)) - end_capacity); + const size_t tot_capacity = std::max(default_total_size, padded_size(req_capacity + sizeof(void*), alignof(max_align_t))); return tot_capacity - end_capacity; } @@ -247,18 +258,40 @@ constexpr size_t compute_small_capacity(const size_t _req_capacity) template class Function { - static constexpr size_t small_capacity = fnc_impl::compute_small_capacity(function_max(sizeof(void*) * 3, DataSize)); + static constexpr size_t small_capacity = fnc_impl::compute_small_capacity(DataSize); static constexpr size_t big_padding = small_capacity - sizeof(void*); struct Small { - unsigned char data_[small_capacity]; - const fnc_impl::SmallRTTI* prtti_; + using RTTI_T = fnc_impl::SmallRTTI; + unsigned char data_[small_capacity]; + uintptr_t prtti_ = 0; + + auto* rtti() const noexcept + { + return reinterpret_cast(prtti_ & fnc_impl::reversed_representation_and_flags_mask); + } + + void rtti(uintptr_t const _ptr) + { + prtti_ = (_ptr & fnc_impl::reversed_representation_and_flags_mask) | to_underlying(fnc_impl::RepresentationE::Small); + } }; struct Big { - unsigned char padding_[big_padding]; - void* ptr_; - const fnc_impl::BigRTTI* prtti_; + using RTTI_T = fnc_impl::BigRTTI; + unsigned char padding_[big_padding]; + void* ptr_; + uintptr_t prtti_; + + auto* rtti() const noexcept + { + return reinterpret_cast(prtti_ & fnc_impl::reversed_representation_and_flags_mask); + } + + void rtti(uintptr_t const _ptr) + { + prtti_ = (_ptr & fnc_impl::reversed_representation_and_flags_mask) | to_underlying(fnc_impl::RepresentationE::Small); + } }; struct Storage { @@ -266,14 +299,11 @@ class Function { Small small_; Big big_; }; - uintptr_t type_data_; }; - // static_assert(sizeof(_Storage_t) == _Any_trivial_space_size + sizeof(void*)); - // static_assert(is_standard_layout_v<_Storage_t>); union { - Storage storage_{}; - max_align_t dummy_; + Storage storage_{}; + std::max_align_t dummy_; }; template friend class Function; @@ -281,18 +311,17 @@ class Function { private: fnc_impl::RepresentationE representation() const noexcept { - return static_cast(storage_.type_data_ & fnc_impl::representation_and_flags_mask); + auto const retval = static_cast(storage_.small_.prtti_ & fnc_impl::representation_and_flags_mask); + assert(retval == static_cast(storage_.big_.prtti_ & fnc_impl::representation_and_flags_mask)); + return retval; } void representation(const fnc_impl::RepresentationE _repr) noexcept { - storage_.type_data_ &= (~fnc_impl::representation_and_flags_mask); - storage_.type_data_ |= static_cast(_repr); - } - - const std::type_info* typeInfo() const noexcept - { - return reinterpret_cast(storage_.type_data_ & ~fnc_impl::representation_and_flags_mask); + // storage_.small_.prtti_ &= (~fnc_impl::representation_and_flags_mask); + // storage_.small_.prtti_ |= static_cast(_repr); + storage_.small_.prtti_ = (storage_.small_.prtti_ & (~fnc_impl::representation_and_flags_mask)) | to_underlying(_repr); + assert(_repr == static_cast(storage_.big_.prtti_ & fnc_impl::representation_and_flags_mask)); } public: @@ -334,7 +363,7 @@ class Function { { doMoveFrom(_other); } - +#if 0 template >>, std::negation, std::in_place_type_t>> /*, std::is_copy_constructible>*/ >, @@ -342,22 +371,36 @@ class Function { = 0> Function(const T& _value) { - doEmplace>(std::move(_value)); + doEmplace>(_value); } - +#endif template >>, std::negation, std::in_place_type_t>> /*, std::is_copy_constructible>*/ >, int> = 0> - Function(T&& _rvalue) + Function(T _value) { - doEmplace>(std::forward(_rvalue)); + assert(std::is_trivially_copyable_v>); + doEmplace(std::move(_value)); } ~Function() noexcept { - reset(); + switch (representation()) { + [[likely]] case fnc_impl::RepresentationE::Small: + if (auto const* prtti = storage_.small_.rtti(); prtti->pdestroy_fnc_) { + prtti->pdestroy_fnc_(&storage_.small_.data_); + } + break; + case fnc_impl::RepresentationE::Big: + storage_.big_.rtti()->pdestroy_fnc_(storage_.big_.ptr_); + break; + case fnc_impl::RepresentationE::None: + [[fallthrough]]; + default: + break; + } } ThisT& operator=(const ThisT& _other) @@ -398,26 +441,29 @@ class Function { void reset() noexcept { switch (representation()) { - case fnc_impl::RepresentationE::Small: - storage_.small_.prtti_->pdestroy_fnc_(&storage_.small_.data_); + [[likely]] case fnc_impl::RepresentationE::Small: + if (auto const* prtti = storage_.small_.rtti(); prtti->pdestroy_fnc_) { + prtti->pdestroy_fnc_(&storage_.small_.data_); + } break; case fnc_impl::RepresentationE::Big: - storage_.big_.prtti_->pdestroy_fnc_(storage_.big_.ptr_); + storage_.big_.rtti()->pdestroy_fnc_(storage_.big_.ptr_); break; case fnc_impl::RepresentationE::None: + [[fallthrough]]; default: break; } - storage_.type_data_ = 0; + storage_.small_.prtti_ = 0; } R operator()(ArgTypes... _args) const { if (has_value()) { - if (is_small()) { - return storage_.small_.prtti_->pinvoke_fnc_(&storage_.small_.data_, std::forward(_args)...); + if (is_small()) [[likely]] { + return storage_.small_.rtti()->pinvoke_fnc_(&storage_.small_.data_, static_cast(_args)... /* std::forward(_args)... */); } else { - return storage_.big_.prtti_->pinvoke_fnc_(storage_.big_.ptr_, std::forward(_args)...); + return storage_.big_.rtti()->pinvoke_fnc_(storage_.big_.ptr_, static_cast(_args)... /* std::forward(_args)... */); } } else { throw std::bad_function_call(); @@ -432,7 +478,7 @@ class Function { bool has_value() const noexcept { - return storage_.type_data_ != 0; + return storage_.small_.prtti_ != 0; } bool empty() const noexcept { @@ -444,36 +490,31 @@ class Function { return has_value(); } - const std::type_info& type() const noexcept - { - const std::type_info* const pinfo = typeInfo(); - return pinfo ? *pinfo : typeid(void); - } - bool is_movable() const { if (is_small()) { - return storage_.small_.prtti_->is_movable_; + return storage_.small_.rtti()->is_movable_; } else if (is_big()) { - return storage_.big_.prtti_->is_copyable_; + return storage_.big_.rtti()->is_copyable_; } return true; } bool is_copyable() const { if (is_small()) { - return storage_.small_.prtti_->is_copyable_; + return storage_.small_.rtti()->is_copyable_; } else if (is_big()) { - return storage_.big_.prtti_->is_copyable_; + return storage_.big_.rtti()->is_copyable_; } return true; } - bool is_small() const + [[nodiscard]] bool is_small() const { return representation() == fnc_impl::RepresentationE::Small; } - bool is_big() const + + [[nodiscard]] bool is_big() const { return representation() == fnc_impl::RepresentationE::Big; } @@ -482,25 +523,21 @@ class Function { template void doMoveFrom(Function& _other) { - storage_.type_data_ = _other.storage_.type_data_; representation(fnc_impl::RepresentationE::None); switch (_other.representation()) { case fnc_impl::RepresentationE::Small: { - const auto repr = _other.storage_.small_.prtti_->pmove_fnc_( + const auto repr = _other.storage_.small_.rtti()->pmove_fnc_( _other.storage_.small_.data_, storage_.small_.data_, small_capacity, storage_.small_.prtti_, storage_.big_.ptr_, storage_.big_.prtti_); representation(repr); } break; case fnc_impl::RepresentationE::Big: { - const auto repr = _other.storage_.big_.prtti_->pmove_fnc_( + const auto repr = _other.storage_.big_.rtti()->pmove_fnc_( _other.storage_.big_.ptr_, storage_.small_.data_, small_capacity, storage_.small_.prtti_, storage_.big_.ptr_, storage_.big_.prtti_); representation(repr); - if (repr == fnc_impl::RepresentationE::Big) { - _other.storage_.type_data_ = 0; - } } break; default: break; @@ -510,18 +547,17 @@ class Function { template void doCopyFrom(const Function& _other) { - storage_.type_data_ = _other.storage_.type_data_; representation(fnc_impl::RepresentationE::None); switch (_other.representation()) { case fnc_impl::RepresentationE::Small: { - const auto repr = _other.storage_.small_.prtti_->pcopy_fnc_( + const auto repr = _other.storage_.small_.rtti()->pcopy_fnc_( _other.storage_.small_.data_, storage_.small_.data_, small_capacity, storage_.small_.prtti_, storage_.big_.ptr_, storage_.big_.prtti_); representation(repr); } break; case fnc_impl::RepresentationE::Big: { - const auto repr = _other.storage_.big_.prtti_->pcopy_fnc_( + const auto repr = _other.storage_.big_.rtti()->pcopy_fnc_( _other.storage_.big_.ptr_, storage_.small_.data_, small_capacity, storage_.small_.prtti_, storage_.big_.ptr_, storage_.big_.prtti_); @@ -532,28 +568,21 @@ class Function { } } - template - T& doEmplace(Args&&... _args) + template + void doEmplace(Fnc _fun) { - if constexpr (is_small_type()) { - auto& rval = reinterpret_cast(storage_.small_.data_); - - ::new (const_cast(static_cast(std::addressof(rval)))) T{std::forward(_args)...}; - storage_.small_.prtti_ = &fnc_impl::small_rtti; - storage_.type_data_ = reinterpret_cast(&typeid(T)); - representation(fnc_impl::RepresentationE::Small); - - return rval; + using FncT = std::remove_cvref_t; + if constexpr (is_small_type()) { + auto& rval = reinterpret_cast(storage_.small_.data_); + std::construct_at(std::addressof(rval), std::move(_fun)); + storage_.small_.rtti(reinterpret_cast(&fnc_impl::small_rtti)); } else { #if defined(SOLID_THROW_ON_BIG_FUNCTION) solid_throw("Big Function"); #endif - T* const ptr = ::new T(std::forward(_args)...); - storage_.big_.ptr_ = ptr; - storage_.big_.prtti_ = &fnc_impl::big_rtti; - storage_.type_data_ = reinterpret_cast(&typeid(T)); - representation(fnc_impl::RepresentationE::Big); - return *ptr; + FncT* const ptr = ::new FncT(std::move(_fun)); + storage_.big_.ptr_ = ptr; + storage_.big_.rtti(reinterpret_cast(&fnc_impl::big_rtti)); } } }; diff --git a/solid/utility/test/test_function_any_speed.cpp b/solid/utility/test/test_function_any_speed.cpp index ab29a545f..540923986 100644 --- a/solid/utility/test/test_function_any_speed.cpp +++ b/solid/utility/test/test_function_any_speed.cpp @@ -18,7 +18,7 @@ struct Event { #ifdef EVENT_USE_STD_ANY using AnyT = std::any; #else - static constexpr size_t any_size = sizeof(void*) == 8 ? any_size_from_sizeof(64 - sizeof(void*) - sizeof(uintptr_t)) : any_size_from_sizeof(32 - sizeof(void*) - sizeof(uintptr_t)); + static constexpr size_t any_size = 1; // sizeof(void*) == 8 ? any_size_from_sizeof(64 - sizeof(void*) - sizeof(uintptr_t)) : any_size_from_sizeof(32 - sizeof(void*) - sizeof(uintptr_t)); using AnyT = Any; #endif Event(); From 576ffbb6e85374c870d3b66af5938b98a4cbc961 Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Sat, 25 Oct 2025 12:59:05 +0300 Subject: [PATCH 12/56] utility: function small switch to references to function in rtti --- solid/utility/function.hpp | 104 +++++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 38 deletions(-) diff --git a/solid/utility/function.hpp b/solid/utility/function.hpp index c42425bc7..a986cd311 100644 --- a/solid/utility/function.hpp +++ b/solid/utility/function.hpp @@ -58,6 +58,8 @@ enum struct RepresentationE : uintptr_t { constexpr uintptr_t representation_mask = 3; constexpr uintptr_t representation_and_flags_mask = representation_mask; constexpr uintptr_t reversed_representation_and_flags_mask = ~representation_mask; +constexpr uintptr_t representation_small = to_underlying(RepresentationE::Small); +constexpr uintptr_t representation_big = to_underlying(RepresentationE::Big); template struct SmallRTTI; @@ -78,10 +80,10 @@ struct BigRTTI { ::delete static_cast(_what); } - InvokeFncT* pinvoke_fnc_; - DestroyFncT* pdestroy_fnc_; - CopyFncT* pcopy_fnc_; - MoveFncT* pmove_fnc_; + InvokeFncT& invoke_fnc_; + DestroyFncT& destroy_fnc_; + CopyFncT& copy_fnc_; + MoveFncT& move_fnc_; const bool is_copyable_; const bool is_movable_; }; @@ -101,10 +103,10 @@ struct SmallRTTI { std::destroy_at(static_cast(_what)); } - InvokeFncT* pinvoke_fnc_; + InvokeFncT& invoke_fnc_; DestroyFncT* pdestroy_fnc_; - CopyFncT* pcopy_fnc_; - MoveFncT* pmove_fnc_; + CopyFncT& copy_fnc_; + MoveFncT& move_fnc_; const bool is_copyable_; const bool is_movable_; }; @@ -135,19 +137,19 @@ RepresentationE do_move_big( template inline constexpr BigRTTI big_rtti = { - .pinvoke_fnc_ = &do_invoke, - .pdestroy_fnc_ = &BigRTTI::template destroy, - .pcopy_fnc_ = &do_copy, - .pmove_fnc_ = &do_move_big, + .invoke_fnc_ = do_invoke, + .destroy_fnc_ = &BigRTTI::template destroy, + .copy_fnc_ = &do_copy, + .move_fnc_ = &do_move_big, .is_copyable_ = std::is_copy_constructible_v, .is_movable_ = std::is_move_constructible_v}; template inline constexpr SmallRTTI small_rtti = { - .pinvoke_fnc_ = &do_invoke, + .invoke_fnc_ = do_invoke, .pdestroy_fnc_ = std::is_trivially_copyable_v ? nullptr : &SmallRTTI::template destroy, - .pcopy_fnc_ = &do_copy, - .pmove_fnc_ = &do_move, + .copy_fnc_ = do_copy, + .move_fnc_ = do_move, .is_copyable_ = std::is_copy_constructible_v, .is_movable_ = std::is_move_constructible_v}; @@ -246,7 +248,7 @@ RepresentationE do_move_big( constexpr size_t compute_small_capacity(const size_t _req_capacity) { - static constexpr size_t default_total_size = 32u; + constexpr size_t default_total_size = 32u; const size_t end_capacity = sizeof(void*); const size_t req_capacity = std::max(_req_capacity, std::max(end_capacity, sizeof(max_align_t)) - end_capacity); @@ -263,34 +265,35 @@ class Function { struct Small { using RTTI_T = fnc_impl::SmallRTTI; - unsigned char data_[small_capacity]; uintptr_t prtti_ = 0; + unsigned char data_[small_capacity]; - auto* rtti() const noexcept + [[nodiscard]] auto* rtti() const noexcept { return reinterpret_cast(prtti_ & fnc_impl::reversed_representation_and_flags_mask); } void rtti(uintptr_t const _ptr) { - prtti_ = (_ptr & fnc_impl::reversed_representation_and_flags_mask) | to_underlying(fnc_impl::RepresentationE::Small); + prtti_ = _ptr | fnc_impl::representation_small; } }; struct Big { using RTTI_T = fnc_impl::BigRTTI; - unsigned char padding_[big_padding]; - void* ptr_; uintptr_t prtti_; + void* ptr_; + unsigned char padding_[big_padding]; + - auto* rtti() const noexcept + [[nodiscard]] auto* rtti() const noexcept { return reinterpret_cast(prtti_ & fnc_impl::reversed_representation_and_flags_mask); } void rtti(uintptr_t const _ptr) { - prtti_ = (_ptr & fnc_impl::reversed_representation_and_flags_mask) | to_underlying(fnc_impl::RepresentationE::Small); + prtti_ = _ptr | fnc_impl::representation_big; } }; @@ -363,15 +366,27 @@ class Function { { doMoveFrom(_other); } -#if 0 +#if 1 template >>, std::negation, std::in_place_type_t>> /*, std::is_copy_constructible>*/ >, int> = 0> - Function(const T& _value) + Function(const T& _fun) { - doEmplace>(_value); + using FncT = std::remove_cvref_t>; + if constexpr (is_small_type()) { + storage_.small_.rtti(reinterpret_cast(&fnc_impl::small_rtti)); + auto& rval = reinterpret_cast(storage_.small_.data_); + std::construct_at(std::addressof(rval), _fun); + } else { +#if defined(SOLID_THROW_ON_BIG_FUNCTION) + solid_throw("Big Function"); +#endif + FncT* const ptr = ::new FncT(_fun); + storage_.big_.ptr_ = ptr; + storage_.big_.rtti(reinterpret_cast(&fnc_impl::big_rtti)); + } } #endif template >>, std::negation, std::in_place_type_t>> /*, @@ -379,10 +394,22 @@ class Function { >, int> = 0> - Function(T _value) + Function(T&& _fun) { - assert(std::is_trivially_copyable_v>); - doEmplace(std::move(_value)); + using FncT = std::remove_cvref_t; + if constexpr (is_small_type()) { + storage_.small_.rtti(reinterpret_cast(&fnc_impl::small_rtti)); + auto& rval = reinterpret_cast(storage_.small_.data_); + std::construct_at(std::addressof(rval), std::move(_fun)); + //new (&rval) FncT(std::move(_fun)); + } else { +#if defined(SOLID_THROW_ON_BIG_FUNCTION) + solid_throw("Big Function"); +#endif + FncT* const ptr = ::new FncT(std::move(_fun)); + storage_.big_.ptr_ = ptr; + storage_.big_.rtti(reinterpret_cast(&fnc_impl::big_rtti)); + } } ~Function() noexcept @@ -394,7 +421,7 @@ class Function { } break; case fnc_impl::RepresentationE::Big: - storage_.big_.rtti()->pdestroy_fnc_(storage_.big_.ptr_); + storage_.big_.rtti()->destroy_fnc_(storage_.big_.ptr_); break; case fnc_impl::RepresentationE::None: [[fallthrough]]; @@ -447,7 +474,7 @@ class Function { } break; case fnc_impl::RepresentationE::Big: - storage_.big_.rtti()->pdestroy_fnc_(storage_.big_.ptr_); + storage_.big_.rtti()->destroy_fnc_(storage_.big_.ptr_); break; case fnc_impl::RepresentationE::None: [[fallthrough]]; @@ -461,9 +488,9 @@ class Function { { if (has_value()) { if (is_small()) [[likely]] { - return storage_.small_.rtti()->pinvoke_fnc_(&storage_.small_.data_, static_cast(_args)... /* std::forward(_args)... */); + return storage_.small_.rtti()->invoke_fnc_(&storage_.small_.data_, static_cast(_args)... /* std::forward(_args)... */); } else { - return storage_.big_.rtti()->pinvoke_fnc_(storage_.big_.ptr_, static_cast(_args)... /* std::forward(_args)... */); + return storage_.big_.rtti()->invoke_fnc_(storage_.big_.ptr_, static_cast(_args)... /* std::forward(_args)... */); } } else { throw std::bad_function_call(); @@ -526,14 +553,14 @@ class Function { representation(fnc_impl::RepresentationE::None); switch (_other.representation()) { case fnc_impl::RepresentationE::Small: { - const auto repr = _other.storage_.small_.rtti()->pmove_fnc_( + const auto repr = _other.storage_.small_.rtti()->move_fnc_( _other.storage_.small_.data_, storage_.small_.data_, small_capacity, storage_.small_.prtti_, storage_.big_.ptr_, storage_.big_.prtti_); representation(repr); } break; case fnc_impl::RepresentationE::Big: { - const auto repr = _other.storage_.big_.rtti()->pmove_fnc_( + const auto repr = _other.storage_.big_.rtti()->move_fnc_( _other.storage_.big_.ptr_, storage_.small_.data_, small_capacity, storage_.small_.prtti_, storage_.big_.ptr_, storage_.big_.prtti_); @@ -550,14 +577,14 @@ class Function { representation(fnc_impl::RepresentationE::None); switch (_other.representation()) { case fnc_impl::RepresentationE::Small: { - const auto repr = _other.storage_.small_.rtti()->pcopy_fnc_( + const auto repr = _other.storage_.small_.rtti()->copy_fnc_( _other.storage_.small_.data_, storage_.small_.data_, small_capacity, storage_.small_.prtti_, storage_.big_.ptr_, storage_.big_.prtti_); representation(repr); } break; case fnc_impl::RepresentationE::Big: { - const auto repr = _other.storage_.big_.rtti()->pcopy_fnc_( + const auto repr = _other.storage_.big_.rtti()->copy_fnc_( _other.storage_.big_.ptr_, storage_.small_.data_, small_capacity, storage_.small_.prtti_, storage_.big_.ptr_, storage_.big_.prtti_); @@ -573,9 +600,10 @@ class Function { { using FncT = std::remove_cvref_t; if constexpr (is_small_type()) { - auto& rval = reinterpret_cast(storage_.small_.data_); - std::construct_at(std::addressof(rval), std::move(_fun)); storage_.small_.rtti(reinterpret_cast(&fnc_impl::small_rtti)); + auto& rval = reinterpret_cast(storage_.small_.data_); + //std::construct_at(std::addressof(rval), std::move(_fun)); + new (&rval) FncT(std::move(_fun)); } else { #if defined(SOLID_THROW_ON_BIG_FUNCTION) solid_throw("Big Function"); From c17f0c8a561098bc66be006267c6a4e8447d8dc6 Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Thu, 30 Oct 2025 18:26:17 +0200 Subject: [PATCH 13/56] utility: refactor event and any plus experimenting with function improvements --- solid/frame/aio/aioreactor.hpp | 2 +- solid/frame/mprpc/mprpcservice.hpp | 2 +- solid/frame/reactor.hpp | 2 +- solid/utility/any.hpp | 472 +++++++++++------- solid/utility/event.hpp | 303 ++++++----- solid/utility/function.hpp | 41 +- solid/utility/test/test_any.cpp | 16 +- solid/utility/test/test_event.cpp | 6 +- .../utility/test/test_function_any_speed.cpp | 4 +- solid/utility/test/test_queue.cpp | 4 +- 10 files changed, 519 insertions(+), 333 deletions(-) diff --git a/solid/frame/aio/aioreactor.hpp b/solid/frame/aio/aioreactor.hpp index 22588fa4b..51320b599 100644 --- a/solid/frame/aio/aioreactor.hpp +++ b/solid/frame/aio/aioreactor.hpp @@ -577,7 +577,7 @@ class Reactor : public impl::Reactor { }; constexpr size_t reactor_default_event_small_size = std::max(sizeof(Function), sizeof(std::function)); -using ReactorEventT = Event; +using ReactorEventT = Event; using ReactorT = Reactor; //----------------------------------------------------------------------------- diff --git a/solid/frame/mprpc/mprpcservice.hpp b/solid/frame/mprpc/mprpcservice.hpp index 70fd2af39..0dac96ac9 100644 --- a/solid/frame/mprpc/mprpcservice.hpp +++ b/solid/frame/mprpc/mprpcservice.hpp @@ -45,7 +45,7 @@ class SocketStub; } // namespace openssl constexpr size_t event_small_size = 32; -using EventT = Event; +using EventT = Event; extern const Event<> pool_event_connect; extern const Event<> pool_event_disconnect; diff --git a/solid/frame/reactor.hpp b/solid/frame/reactor.hpp index 2b1c34c3a..a186f70b3 100644 --- a/solid/frame/reactor.hpp +++ b/solid/frame/reactor.hpp @@ -532,7 +532,7 @@ class Reactor : public impl::Reactor { }; constexpr size_t reactor_default_event_small_size = std::max(sizeof(Function), sizeof(std::function)); -using ReactorEventT = Event; +using ReactorEventT = Event; using ReactorT = Reactor; } // namespace frame diff --git a/solid/utility/any.hpp b/solid/utility/any.hpp index 74e51e786..9746e4cac 100644 --- a/solid/utility/any.hpp +++ b/solid/utility/any.hpp @@ -23,7 +23,12 @@ namespace solid { -template +constexpr size_t any_default_size = 32 - sizeof(std::uintptr_t); +constexpr size_t any_default_align = sizeof(std::uintptr_t); + +template + requires(SmallSize > 0 and SmallSize >= SmallAlign + and (SmallSize % SmallAlign == 0) and std::popcount(SmallAlign) == 1) class Any; template @@ -43,22 +48,57 @@ enum struct RepresentationE : uintptr_t { Small, Big, }; -constexpr uintptr_t representation_mask = 3; -constexpr uintptr_t representation_and_flags_mask = representation_mask; +constexpr uintptr_t representation_mask = 3; +constexpr uintptr_t representation_and_flags_mask = representation_mask; +constexpr uintptr_t reversed_representation_and_flags_mask = ~representation_mask; + +inline RepresentationE representation(uintptr_t const _rtti) noexcept +{ + return static_cast(_rtti & representation_mask); +} + +inline uintptr_t representation(uintptr_t const _rtti, RepresentationE const _repr) noexcept +{ + return (_rtti & (~representation_and_flags_mask)) | to_underlying(_repr); +} + +inline uintptr_t representation(void const* _rtti, RepresentationE const _repr) noexcept +{ + return (reinterpret_cast(_rtti) & (~representation_and_flags_mask)) | to_underlying(_repr); +} struct SmallRTTI; +struct BigRTTI; + +struct BaseRTTI { + using DestroyFncT = void(void*) noexcept; + using CopyFncT = uintptr_t(const void*, void*, size_t, size_t, void*&); + using MoveFncT = uintptr_t(void*, void*, size_t, size_t, void*&); + using GetIfFncT = const void*(const std::type_index&, const void*); + using GetTypeInfoT = std::type_info const*() noexcept; -struct BigRTTI { - using DestroyFncT = void(void*); - using CopyFncT = RepresentationE(const void*, void*, const size_t, const SmallRTTI*&, void*&, const BigRTTI*&); - using MoveFncT = RepresentationE(void*, void*, const size_t, const SmallRTTI*&, void*&, const BigRTTI*&); - using GetIfFncT = const void*(const std::type_index&, const void*); + CopyFncT& copy_fnc_; + MoveFncT& move_fnc_; + GetIfFncT& get_if_fnc_; + GetTypeInfoT& get_type_info_fnc_; + const bool is_copyable_; + const bool is_movable_; + const bool is_tuple_; + + static BaseRTTI const& get(uintptr_t const _rtti) noexcept + { + return *reinterpret_cast(_rtti & reversed_representation_and_flags_mask); + } +}; + +struct BigRTTI : BaseRTTI { + + DestroyFncT& destroy_fnc_; template static void destroy(void* const _what) noexcept { - //::delete static_cast(_what); - std::destroy_at(std::launder(static_cast(_what))); + ::delete static_cast(_what); } template @@ -67,67 +107,80 @@ struct BigRTTI { return ::new T(std::move(*static_cast(_from))); } - DestroyFncT* pdestroy_fnc_; - CopyFncT* pcopy_fnc_; - MoveFncT* pmove_fnc_; - GetIfFncT* pget_if_fnc_; - const bool is_copyable_; - const bool is_movable_; - const bool is_tuple_; + static BigRTTI const& get(uintptr_t const _rtti) noexcept + { + return *reinterpret_cast(_rtti & reversed_representation_and_flags_mask); + } }; -struct SmallRTTI { - using DestroyFncT = void(void*) noexcept; - using CopyFncT = RepresentationE(const void*, void*, const size_t, const SmallRTTI*&, void*&, const BigRTTI*&); - using MoveFncT = RepresentationE(void*, void*, const size_t, const SmallRTTI*&, void*&, const BigRTTI*&); - using GetIfFncT = const void*(const std::type_index&, const void*); +struct SmallRTTI : BaseRTTI { + + DestroyFncT* pdestroy_fnc_; template static void destroy(void* const _what) noexcept { - static_cast(_what)->~T(); + std::destroy_at(std::launder(static_cast(_what))); } static void dummy_destroy(void* const _what) noexcept { } - DestroyFncT* pdestroy_fnc_; - CopyFncT* pcopy_fnc_; - MoveFncT* pmove_fnc_; - GetIfFncT* pget_if_fnc_; - const bool is_copyable_; - const bool is_movable_; - const bool is_tuple_; + + static SmallRTTI const& get(uintptr_t const _rtti) noexcept + { + return *reinterpret_cast(_rtti & reversed_representation_and_flags_mask); + } }; template -RepresentationE do_copy( - const void* _pfrom, - void* _pto_small, const size_t _small_cap, const SmallRTTI*& _rpsmall_rtti, - void*& _rpto_big, const BigRTTI*& _rpbig_rtti); +uintptr_t do_copy( + const void*, + void*, size_t, size_t, + void*&); template -RepresentationE do_move( - void* _pfrom, - void* _pto_small, const size_t _small_cap, const SmallRTTI*& _rpsmall_rtti, - void*& _rpto_big, const BigRTTI*& _rpbig_rtti); +uintptr_t do_move( + void*, + void*, size_t, size_t, + void*&); template -RepresentationE do_move_big( - void* _pfrom, - void* _pto_small, const size_t _small_cap, const SmallRTTI*& _rpsmall_rtti, - void*& _rpto_big, const BigRTTI*& _rpbig_rtti); +uintptr_t do_move_big( + void*, + void*, size_t, size_t, + void*&); template -const void* do_get_if(const std::type_index& _type_index, const void* _pdata); +const void* do_get_if(const std::type_index&, const void*); + +template +std::type_info const* get_type_info() noexcept; template inline constexpr BigRTTI big_rtti = { - &BigRTTI::destroy, &do_copy, &do_move_big, &do_get_if, std::is_copy_constructible_v, std::is_move_constructible_v, is_specialization_v}; + {do_copy, + do_move_big, + do_get_if, + get_type_info, + std::is_copy_constructible_v, + std::is_move_constructible_v, + is_specialization_v}, + BigRTTI::destroy}; +//&BigRTTI::destroy, &do_copy, &do_move_big, &do_get_if, std::is_copy_constructible_v, std::is_move_constructible_v, is_specialization_v}; template inline constexpr SmallRTTI small_rtti = { - &SmallRTTI::destroy, &do_copy, &do_move, &do_get_if, std::is_copy_constructible_v, std::is_move_constructible_v, is_specialization_v}; - + {do_copy, + do_move, + do_get_if, + get_type_info, + std::is_copy_constructible_v, + std::is_move_constructible_v, + is_specialization_v}, + &SmallRTTI::destroy}; +//&SmallRTTI::destroy, &do_copy, &do_move, &do_get_if, std::is_copy_constructible_v, std::is_move_constructible_v, is_specialization_v}; + +#if 0 // TODO:remove inline RepresentationE do_dummy_copy( const void* _pfrom, void* _pto_small, const size_t _small_cap, const SmallRTTI*& _rpsmall_rtti, @@ -151,94 +204,104 @@ inline const void* do_dummy_get_if(const std::type_index& _type_index, const voi inline constexpr SmallRTTI dummy_small_rtti = { &SmallRTTI::dummy_destroy, &do_dummy_copy, &do_dummy_move, &do_dummy_get_if, false, false, false}; +#endif template -RepresentationE do_copy( +uintptr_t do_copy( const void* _pfrom, - void* _pto_small, const size_t _small_cap, const SmallRTTI*& _rpsmall_rtti, - void*& _rpto_big, const BigRTTI*& _rpbig_rtti) + void* _pto_small, const size_t _small_cap, const size_t _small_align, + void*& _rpto_big) { - if constexpr (alignof(T) <= alignof(max_align_t) && std::is_copy_constructible_v) { - if (sizeof(T) <= _small_cap) { + if constexpr (std::is_copy_constructible_v) { + if (sizeof(T) <= _small_cap and alignof(T) <= _small_align) { T& rdst = *static_cast(_pto_small); const T& rsrc = *static_cast(_pfrom); ::new (const_cast(static_cast(std::addressof(rdst)))) T(rsrc); - _rpsmall_rtti = &small_rtti; - return RepresentationE::Small; + return representation(&small_rtti, RepresentationE::Small); + //_rpsmall_rtti = &small_rtti; + // return RepresentationE::Small; } else { #if defined(SOLID_THROW_ON_BIG_ANY) solid_throw("Big Any"); #endif - _rpto_big = ::new T(*static_cast(_pfrom)); - _rpbig_rtti = &big_rtti; - return RepresentationE::Big; + _rpto_big = ::new T(*static_cast(_pfrom)); + return representation(&big_rtti, RepresentationE::Big); + //_rpbig_rtti = &big_rtti; + // return RepresentationE::Big; } } else if constexpr (std::is_trivially_constructible_v || std::is_copy_constructible_v) { - _rpto_big = ::new T(*static_cast(_pfrom)); - _rpbig_rtti = &big_rtti; - return RepresentationE::Big; + _rpto_big = ::new T(*static_cast(_pfrom)); + return representation(&big_rtti, RepresentationE::Big); + //_rpbig_rtti = &big_rtti; + // return RepresentationE::Big; } else { solid_throw("Any: contained value not copyable"); - return RepresentationE::None; + return 0; } } template -RepresentationE do_move( +uintptr_t do_move( void* _pfrom, - void* _pto_small, const size_t _small_cap, const SmallRTTI*& _rpsmall_rtti, - void*& _rpto_big, const BigRTTI*& _rpbig_rtti) + void* _pto_small, const size_t _small_cap, const size_t _small_align, + void*& _rpto_big) { - if constexpr (alignof(T) <= alignof(max_align_t) && std::is_move_constructible_v) { - if (sizeof(T) <= _small_cap) { + if constexpr (std::is_move_constructible_v) { + if (sizeof(T) <= _small_cap and alignof(T) <= _small_align) { T& rdst = *static_cast(_pto_small); T& rsrc = *static_cast(_pfrom); ::new (const_cast(static_cast(std::addressof(rdst)))) T{std::move(rsrc)}; - _rpsmall_rtti = &small_rtti; - return RepresentationE::Small; + return representation(&small_rtti, RepresentationE::Small); + //_rpsmall_rtti = &small_rtti; + // return RepresentationE::Small; } else { #if defined(SOLID_THROW_ON_BIG_ANY) solid_throw("Big Any"); #endif - _rpto_big = ::new T{std::move(*static_cast(_pfrom))}; - _rpbig_rtti = &big_rtti; - return RepresentationE::Big; + _rpto_big = ::new T{std::move(*static_cast(_pfrom))}; + return representation(&big_rtti, RepresentationE::Big); + //_rpbig_rtti = &big_rtti; + // return RepresentationE::Big; } } else if constexpr (std::is_move_constructible_v) { #if defined(SOLID_THROW_ON_BIG_ANY) solid_throw("Big Any"); #endif - _rpto_big = ::new T{std::move(*static_cast(_pfrom))}; - _rpbig_rtti = &big_rtti; - return RepresentationE::Big; + _rpto_big = ::new T{std::move(*static_cast(_pfrom))}; + return representation(&big_rtti, RepresentationE::Big); + //_rpbig_rtti = &big_rtti; + // return RepresentationE::Big; } else { solid_throw("Any: contained value not movable"); - return RepresentationE::None; + return 0; } } template -RepresentationE do_move_big( +uintptr_t do_move_big( void* _pfrom, - void* _pto_small, const size_t _small_cap, const SmallRTTI*& _rpsmall_rtti, - void*& _rpto_big, const BigRTTI*& _rpbig_rtti) + void* _pto_small, const size_t _small_cap, const size_t _small_align, + void*& _rpto_big) { if constexpr (alignof(T) <= alignof(max_align_t) && std::is_move_constructible_v) { - if (sizeof(T) <= _small_cap) { + if (sizeof(T) <= _small_cap and alignof(T) <= _small_align) { T& rdst = *static_cast(_pto_small); T& rsrc = *static_cast(_pfrom); ::new (const_cast(static_cast(std::addressof(rdst)))) T{std::move(rsrc)}; - _rpsmall_rtti = &small_rtti; - return RepresentationE::Small; + return representation(&small_rtti, RepresentationE::Small); + //_rpsmall_rtti = &small_rtti; + // return RepresentationE::Small; } else { - _rpto_big = static_cast(_pfrom); //::new T{ std::move(*static_cast(_pfrom)) }; - _rpbig_rtti = &big_rtti; - return RepresentationE::Big; + _rpto_big = static_cast(_pfrom); + return representation(&big_rtti, RepresentationE::Big); + //_rpbig_rtti = &big_rtti; + // return RepresentationE::Big; } } else { - _rpto_big = static_cast(_pfrom); //::new T{ std::move(*static_cast(_pfrom)) }; - _rpbig_rtti = &big_rtti; - return RepresentationE::Big; + _rpto_big = static_cast(_pfrom); + return representation(&big_rtti, RepresentationE::Big); + //_rpbig_rtti = &big_rtti; + // return RepresentationE::Big; } } @@ -265,84 +328,71 @@ const void* do_get_if(const std::type_index& _type_index, const void* _pdata) return nullptr; } -constexpr size_t compute_small_capacity(const size_t _req_capacity) +template +std::type_info const* get_type_info() noexcept { - static constexpr size_t default_total_size = 32u; - - const size_t end_capacity = sizeof(uintptr_t) + sizeof(void*); - const size_t req_capacity = std::max(_req_capacity, std::max(end_capacity, sizeof(max_align_t)) - end_capacity); - const size_t tot_capacity = std::max(default_total_size, padded_size(req_capacity + sizeof(uintptr_t) + sizeof(void*), alignof(max_align_t))); - - return tot_capacity - end_capacity; + return &typeid(T); } } // namespace any_impl -template +template + requires(SmallSize > 0 and SmallSize >= SmallAlign + and (SmallSize % SmallAlign == 0) and std::popcount(SmallAlign) == 1) class Any { - static constexpr size_t small_capacity = any_impl::compute_small_capacity(DataSize); - static constexpr size_t big_padding = small_capacity - sizeof(void*); struct Small { - unsigned char data_[small_capacity]; - const any_impl::SmallRTTI* prtti_; + alignas(SmallAlign) unsigned char data_[SmallSize]; }; struct Big { - unsigned char padding_[big_padding]; - void* ptr_; - const any_impl::BigRTTI* prtti_; - }; - - struct Storage { - union { - Small small_; - Big big_; - }; - uintptr_t type_data_; + void* pdata_; }; + uintptr_t rtti_ = 0; union { - Storage storage_{}; - max_align_t dummy_; + Small small_; + Big big_; }; - template + + template + requires(S > 0 and S >= A + and (S % A == 0) and std::popcount(A) == 1) friend class Any; private: - any_impl::RepresentationE representation() const noexcept - { - return static_cast(storage_.type_data_ & any_impl::representation_and_flags_mask); - } - - void representation(const any_impl::RepresentationE _repr) noexcept - { - storage_.type_data_ &= (~any_impl::representation_and_flags_mask); - storage_.type_data_ |= static_cast(_repr); - } - const std::type_info* typeInfo() const noexcept { - return reinterpret_cast(storage_.type_data_ & ~any_impl::representation_and_flags_mask); + // return reinterpret_cast(storage_.type_data_ & ~any_impl::representation_and_flags_mask); + auto const rtti = rtti_; + if (rtti) [[likely]] { + return any_impl::BaseRTTI::get(rtti).get_type_info_fnc_(); + } + return nullptr; } public: - using ThisT = Any; + using ThisT = Any; static constexpr size_t smallCapacity() { - return small_capacity; + return SmallSize; + } + + static constexpr size_t smallAlign() + { + return SmallAlign; } template static constexpr bool is_small_type() { - return alignof(T) <= alignof(max_align_t) && sizeof(T) <= small_capacity; + return alignof(T) <= smallAlign() && sizeof(T) <= smallCapacity(); } constexpr Any() noexcept { - storage_.type_data_ = 0; + rtti_ = 0; } Any(const ThisT& _other) @@ -367,11 +417,8 @@ class Any { doMoveFrom(_other); } - template >>, std::negation, std::in_place_type_t>> /*, - std::is_copy_constructible>*/ - >, - int> - = 0> + template < + class T, std::enable_if_t>>, std::negation, std::in_place_type_t>>>, int> = 0> Any(T&& _rvalue) { doEmplace>(std::forward(_rvalue)); @@ -461,18 +508,22 @@ class Any { void reset() noexcept { - switch (representation()) { - case any_impl::RepresentationE::Small: - storage_.small_.prtti_->pdestroy_fnc_(&storage_.small_.data_); - break; - case any_impl::RepresentationE::Big: - storage_.big_.prtti_->pdestroy_fnc_(storage_.big_.ptr_); - break; + auto const rtti = rtti_; + switch (any_impl::representation(rtti)) { + [[likely]] case any_impl::RepresentationE::Small: { + auto& rrtti = any_impl::SmallRTTI::get(rtti); + if (rrtti.pdestroy_fnc_) { + rrtti.pdestroy_fnc_(small_.data_); + } + } break; + case any_impl::RepresentationE::Big: { + any_impl::BigRTTI::get(rtti).destroy_fnc_(big_.pdata_); + } break; case any_impl::RepresentationE::None: default: break; } - storage_.type_data_ = 0; + rtti_ = 0u; } template @@ -483,7 +534,7 @@ class Any { bool has_value() const noexcept { - return storage_.type_data_ != 0; + return rtti_ != 0u; } explicit operator bool() const noexcept @@ -511,9 +562,9 @@ class Any { } if constexpr (is_small_type()) { - return reinterpret_cast(&storage_.small_.data_); + return reinterpret_cast(&small_.data_); } else { - return static_cast(storage_.big_.ptr_); + return static_cast(big_.pdata_); } } @@ -526,14 +577,12 @@ class Any { template const T* get_if() const noexcept { - switch (representation()) { - case any_impl::RepresentationE::Small: - return static_cast(storage_.small_.prtti_->pget_if_fnc_(std::type_index(typeid(T)), &storage_.small_.data_)); - case any_impl::RepresentationE::Big: - return static_cast(storage_.big_.prtti_->pget_if_fnc_(std::type_index(typeid(T)), storage_.big_.ptr_)); - default: - return nullptr; + auto const rtti = rtti_; + if (rtti) [[likely]] { + void const* pdata = any_impl::representation(rtti) == any_impl::RepresentationE::Small ? small_.data_ : big_.pdata_; + return static_cast(any_impl::BaseRTTI::get(rtti).get_if_fnc_(std::type_index(typeid(T)), pdata)); } + return nullptr; } template @@ -544,46 +593,91 @@ class Any { bool is_movable() const { + auto const rtti = rtti_; + if (rtti) [[likely]] { + return any_impl::BaseRTTI::get(rtti).is_movable_; + } + return true; +#if 0 if (is_small()) { return storage_.small_.prtti_->is_movable_; } else if (is_big()) { return storage_.big_.prtti_->is_movable_; } return true; +#endif } bool is_copyable() const { + auto const rtti = rtti_; + if (rtti) [[likely]] { + return any_impl::BaseRTTI::get(rtti).is_copyable_; + } + return true; +#if 0 if (is_small()) { return storage_.small_.prtti_->is_copyable_; } else if (is_big()) { return storage_.big_.prtti_->is_copyable_; } return true; +#endif } bool is_tuple() const { + auto const rtti = rtti_; + if (rtti) [[likely]] { + return any_impl::BaseRTTI::get(rtti).is_tuple_; + } + return false; +#if 0 if (is_small()) { return storage_.small_.prtti_->is_tuple_; } else if (is_big()) { return storage_.big_.prtti_->is_tuple_; } return false; +#endif } bool is_small() const { - return representation() == any_impl::RepresentationE::Small; + return any_impl::representation(rtti_) == any_impl::RepresentationE::Small; } bool is_big() const { - return representation() == any_impl::RepresentationE::Big; + return any_impl::representation(rtti_) == any_impl::RepresentationE::Big; } private: - template - void doMoveFrom(Any& _other) + template + void doMoveFrom(Any& _other) { + auto const rtti = _other.rtti_; + + switch (any_impl::representation(rtti)) { + case any_impl::RepresentationE::Small: { + rtti_ = any_impl::BaseRTTI::get(rtti).move_fnc_( + _other.small_.data_, + small_.data_, smallCapacity(), smallAlign(), + big_.pdata_); + _other.reset(); + } break; + case any_impl::RepresentationE::Big: { + rtti_ = any_impl::BaseRTTI::get(rtti).move_fnc_( + _other.big_.pdata_, + small_.data_, smallCapacity(), smallAlign(), + big_.pdata_); + if (is_big()) { + _other.rtti_ = 0u; + } + _other.reset(); + } break; + default: + break; + } +#if 0 storage_.type_data_ = _other.storage_.type_data_; representation(any_impl::RepresentationE::None); switch (_other.representation()) { @@ -591,7 +685,7 @@ class Any { const auto repr = _other.storage_.small_.prtti_->pmove_fnc_( _other.storage_.small_.data_, storage_.small_.data_, small_capacity, storage_.small_.prtti_, - storage_.big_.ptr_, storage_.big_.prtti_); + storage_.big_.pdata_, storage_.big_.prtti_); representation(repr); _other.reset(); } break; @@ -610,11 +704,32 @@ class Any { default: break; } +#endif } - template - void doCopyFrom(const Any& _other) + template + void doCopyFrom(const Any& _other) { + auto const rtti = _other.rtti_; + + switch (any_impl::representation(rtti)) { + case any_impl::RepresentationE::Small: { + rtti_ = any_impl::BaseRTTI::get(rtti).copy_fnc_( + _other.small_.data_, + small_.data_, smallCapacity(), smallAlign(), + big_.pdata_); + } break; + case any_impl::RepresentationE::Big: { + rtti_ = any_impl::BaseRTTI::get(rtti).copy_fnc_( + _other.big_.pdata_, + small_.data_, smallCapacity(), smallAlign(), + big_.pdata_); + } break; + default: + break; + } + +#if 0 storage_.type_data_ = _other.storage_.type_data_; representation(any_impl::RepresentationE::None); switch (_other.representation()) { @@ -635,29 +750,34 @@ class Any { default: break; } +#endif } template T& doEmplace(Args&&... _args) { if constexpr (is_small_type()) { - auto& rval = reinterpret_cast(storage_.small_.data_); + auto& rval = reinterpret_cast(small_.data_); ::new (const_cast(static_cast(std::addressof(rval)))) T{std::forward(_args)...}; - storage_.small_.prtti_ = &any_impl::small_rtti; - storage_.type_data_ = reinterpret_cast(&typeid(T)); - representation(any_impl::RepresentationE::Small); + + rtti_ = representation(&any_impl::small_rtti, any_impl::RepresentationE::Small); + // storage_.small_.prtti_ = &any_impl::small_rtti; + // storage_.type_data_ = reinterpret_cast(&typeid(T)); + // representation(any_impl::RepresentationE::Small); return rval; } else { #if defined(SOLID_THROW_ON_BIG_ANY) solid_throw("Big Any"); #endif - T* const ptr = ::new T(std::forward(_args)...); - storage_.big_.ptr_ = ptr; - storage_.big_.prtti_ = &any_impl::big_rtti; - storage_.type_data_ = reinterpret_cast(&typeid(T)); - representation(any_impl::RepresentationE::Big); + T* const ptr = ::new T(std::forward(_args)...); + big_.pdata_ = ptr; + rtti_ = representation(&any_impl::big_rtti, any_impl::RepresentationE::Big); + + // storage_.big_.prtti_ = &any_impl::big_rtti; + // storage_.type_data_ = reinterpret_cast(&typeid(T)); + // representation(any_impl::RepresentationE::Big); return *ptr; } } @@ -665,21 +785,21 @@ class Any { //----------------------------------------------------------------------------- -template -inline void swap(Any& _a1, Any& _a2) noexcept +template +inline void swap(Any& _a1, Any& _a2) noexcept { _a1.swap(_a2); } -template -Any make_any(Args&&... _args) +template +auto make_any(Args&&... _args) { - return Any{std::in_place_type, std::forward(_args)...}; + return Any{std::in_place_type, std::forward(_args)...}; } -template -Any make_any(std::initializer_list _ilist, Args&&... _args) +template +auto make_any(std::initializer_list _ilist, Args&&... _args) { - return Any{std::in_place_type, _ilist, std::forward(_args)...}; + return Any{std::in_place_type, _ilist, std::forward(_args)...}; } //----------------------------------------------------------------------------- diff --git a/solid/utility/event.hpp b/solid/utility/event.hpp index 6c1bae3c9..5e6b4c19b 100644 --- a/solid/utility/event.hpp +++ b/solid/utility/event.hpp @@ -44,12 +44,8 @@ class EventBase { const EventCategoryBase* pcategory_; uintptr_t id_; - uintptr_t type_data_ = 0; - union { - const any_impl::SmallRTTI* psmall_; - const any_impl::BigRTTI* pbig_; - } rtti_; - void* pdata_ = nullptr; + uintptr_t rtti_ = 0u; + void* pdata_ = nullptr; public: std::ostream& print(std::ostream& _ros) const; @@ -58,26 +54,28 @@ class EventBase { void resetData() { - switch (representation()) { - [[likely]] case any_impl::RepresentationE::Small: - if (rtti_.psmall_->pdestroy_fnc_) { - rtti_.psmall_->pdestroy_fnc_(pdata_); + auto const rtti = rtti_; + switch (any_impl::representation(rtti)) { + [[likely]] case any_impl::RepresentationE::Small: { + auto& rrtti = any_impl::SmallRTTI::get(rtti); + if (rrtti.pdestroy_fnc_) { + rrtti.pdestroy_fnc_(pdata_); } - break; - case any_impl::RepresentationE::Big: - rtti_.pbig_->pdestroy_fnc_(pdata_); - break; + } break; + case any_impl::RepresentationE::Big: { + any_impl::BigRTTI::get(rtti).destroy_fnc_(pdata_); + } break; case any_impl::RepresentationE::None: default: break; } - pdata_ = nullptr; - type_data_ = 0; + rtti_ = 0u; + pdata_ = nullptr; } bool hasData() const noexcept { - return type_data_ != 0; + return rtti_ == 0u; } bool operator==(const EventBase& _rother) const; @@ -89,12 +87,6 @@ class EventBase { return !empty(); } - const std::type_info& type() const noexcept - { - const std::type_info* const pinfo = typeInfo(); - return pinfo ? *pinfo : typeid(void); - } - template const T* cast() const noexcept { @@ -115,14 +107,11 @@ class EventBase { template const T* get_if() const noexcept { - switch (representation()) { - case any_impl::RepresentationE::Small: - return static_cast(rtti_.psmall_->pget_if_fnc_(std::type_index(typeid(T)), pdata_)); - case any_impl::RepresentationE::Big: - return static_cast(rtti_.pbig_->pget_if_fnc_(std::type_index(typeid(T)), pdata_)); - default: - return nullptr; + auto const rtti = rtti_; + if (rtti) [[likely]] { + return static_cast(any_impl::BaseRTTI::get(rtti).get_if_fnc_(std::type_index(typeid(T)), pdata_)); } + return nullptr; } template @@ -133,40 +122,70 @@ class EventBase { bool is_movable() const { - if (is_small()) { - return rtti_.psmall_->is_movable_; - } else if (is_big()) { - return rtti_.pbig_->is_movable_; +#if 0 + auto const lrtti = rtti_; + switch (any_impl::representation(lrtti)) { + case any_impl::RepresentationE::Small: + return any_impl::SmallRTTI::get(lrtti).is_movable_; + case any_impl::RepresentationE::Big: + return any_impl::BigRTTI::get(lrtti).is_movable_; + default: + return true; + } +#endif + auto const rtti = rtti_; + if (rtti) [[likely]] { + return any_impl::BaseRTTI::get(rtti).is_movable_; } return true; } bool is_copyable() const { - if (is_small()) { - return rtti_.psmall_->is_copyable_; - } else if (is_big()) { - return rtti_.pbig_->is_copyable_; +#if 0 + auto const lrtti = rtti_; + switch (any_impl::representation(lrtti)) { + case any_impl::RepresentationE::Small: + return any_impl::SmallRTTI::get(lrtti).is_copyable_; + case any_impl::RepresentationE::Big: + return any_impl::BigRTTI::get(lrtti).is_copyable_; + default: + return true; + } +#endif + auto const rtti = rtti_; + if (rtti) [[likely]] { + return any_impl::BaseRTTI::get(rtti).is_copyable_; } return true; } bool is_tuple() const { - if (is_small()) { - return rtti_.psmall_->is_tuple_; - } else if (is_big()) { - return rtti_.pbig_->is_tuple_; +#if 0 + auto const lrtti = rtti_; + switch (any_impl::representation(lrtti)) { + case any_impl::RepresentationE::Small: + return any_impl::SmallRTTI::get(lrtti).is_tuple_; + case any_impl::RepresentationE::Big: + return any_impl::BigRTTI::get(lrtti).is_tuple_; + default: + return false; + } +#endif + auto const rtti = rtti_; + if (rtti) [[likely]] { + return any_impl::BaseRTTI::get(rtti).is_tuple_; } return false; } bool is_small() const { - return representation() == any_impl::RepresentationE::Small; + return any_impl::representation(rtti_) == any_impl::RepresentationE::Small; } bool is_big() const { - return representation() == any_impl::RepresentationE::Big; + return any_impl::representation(rtti_) == any_impl::RepresentationE::Big; } protected: @@ -177,14 +196,13 @@ class EventBase { , id_(_id) { - rtti_.psmall_ = &any_impl::dummy_small_rtti; } EventBase(const EventBase& _other) : pcategory_(_other.pcategory_) , id_(_other.id_) { - rtti_.psmall_ = _other.rtti_.psmall_; + rtti_ = _other.rtti_; } ~EventBase() @@ -192,20 +210,23 @@ class EventBase { reset(); } - any_impl::RepresentationE representation() const noexcept - { - return static_cast(type_data_ & any_impl::representation_and_flags_mask); - } - - void representation(const any_impl::RepresentationE _repr) noexcept + const std::type_info* typeInfo() const noexcept { - type_data_ &= (~any_impl::representation_and_flags_mask); - type_data_ |= static_cast(_repr); + // return reinterpret_cast(type_data_ & ~any_impl::representation_and_flags_mask); + auto const rtti = rtti_; + if (rtti) [[likely]] { + return any_impl::BaseRTTI::get(rtti).get_type_info_fnc_(); + } + return nullptr; } - const std::type_info* typeInfo() const noexcept + const std::type_info& type() const noexcept { - return reinterpret_cast(type_data_ & ~any_impl::representation_and_flags_mask); + auto const rtti = rtti_; + if (rtti) [[likely]] { + return *any_impl::BaseRTTI::get(rtti).get_type_info_fnc_(); + } + return typeid(void); } void reset(const EventBase& _other) @@ -215,10 +236,24 @@ class EventBase { resetData(); } - void doMoveFrom(void* _psmall_data, const size_t _small_capacity, EventBase& _other) + void doMoveFrom(void* _psmall_data, const size_t _small_capacity, const size_t _small_align, EventBase& _other) { - type_data_ = _other.type_data_; - pdata_ = _psmall_data; + pdata_ = _psmall_data; + + auto const rtti = _other.rtti_; + + if (rtti) [[likely]] { + rtti_ = any_impl::BaseRTTI::get(rtti).move_fnc_( + _other.pdata_, + _psmall_data, _small_capacity, _small_align, + pdata_); + + if (is_big()) { + _other.rtti_ = 0u; + } + _other.reset(); + } +#if 0 representation(any_impl::RepresentationE::None); switch (_other.representation()) { case any_impl::RepresentationE::Small: { @@ -244,10 +279,22 @@ class EventBase { default: break; } +#endif } - void doCopyFrom(void* _psmall_data, const size_t _small_capacity, const EventBase& _other) + void doCopyFrom(void* _psmall_data, const size_t _small_capacity, const size_t _small_align, const EventBase& _other) { + pdata_ = _psmall_data; + + auto const rtti = _other.rtti_; + + if (rtti) [[likely]] { + rtti_ = any_impl::BaseRTTI::get(rtti).copy_fnc_( + _other.pdata_, + _psmall_data, _small_capacity, _small_align, + pdata_); + } +#if 0 type_data_ = _other.type_data_; pdata_ = _psmall_data; representation(any_impl::RepresentationE::None); @@ -269,16 +316,19 @@ class EventBase { default: break; } +#endif } template - T& doEmplaceSmall(void* _psmall_data, const size_t _small_capacity, Args&&... _args) + T& doEmplaceSmall(void* _psmall_data, Args&&... _args) { - auto* pdata = ::new (_psmall_data) T{std::forward(_args)...}; - pdata_ = _psmall_data; - rtti_.psmall_ = &any_impl::small_rtti; - type_data_ = reinterpret_cast(&typeid(T)); - representation(any_impl::RepresentationE::Small); + auto* pdata = ::new (_psmall_data) T{std::forward(_args)...}; + pdata_ = _psmall_data; + rtti_ = any_impl::representation(&any_impl::small_rtti, any_impl::RepresentationE::Small); + + // rtti_.psmall_ = &any_impl::small_rtti; + // type_data_ = reinterpret_cast(&typeid(T)); + // representation(any_impl::RepresentationE::Small); return *pdata; } @@ -291,9 +341,10 @@ class EventBase { #endif T* const ptr = ::new T(std::forward(_args)...); pdata_ = ptr; - rtti_.pbig_ = &any_impl::big_rtti; - type_data_ = reinterpret_cast(&typeid(T)); - representation(any_impl::RepresentationE::Big); + rtti_ = representation(&any_impl::big_rtti, any_impl::RepresentationE::Big); + // rtti_.pbig_ = &any_impl::big_rtti; + // type_data_ = reinterpret_cast(&typeid(T)); + // representation(any_impl::RepresentationE::Big); return *ptr; } }; @@ -407,14 +458,15 @@ inline EventCategory category{ //----------------------------------------------------------------------------- // Event<> //----------------------------------------------------------------------------- -template +template + requires(SmallSize == 0 and SmallAlign == 0 or (SmallSize > 0 and SmallSize >= SmallAlign and (SmallSize % SmallAlign == 0) and std::popcount(SmallAlign) == 1)) class Event; template struct is_event; -template -struct is_event> : std::true_type { +template +struct is_event> : std::true_type { }; template <> @@ -426,7 +478,7 @@ struct is_event : std::false_type { }; template <> -class Event<0> : public EventBase { +class Event<0, 0> : public EventBase { public: using ThisT = Event<0>; @@ -435,6 +487,11 @@ class Event<0> : public EventBase { return 0; } + static constexpr size_t smallAlign() + { + return 0; + } + template static constexpr bool is_small_type() { @@ -459,6 +516,7 @@ class Event<0> : public EventBase { } }; +#if 0 // TODO:remove namespace event_impl { constexpr size_t compute_small_capacity(const size_t _req_capacity) { @@ -471,27 +529,30 @@ constexpr size_t compute_small_capacity(const size_t _req_capacity) return tot_capacity - end_capacity; } } // namespace event_impl +#endif -template +template + requires(SmallSize == 0 and SmallAlign == 0 or (SmallSize > 0 and SmallSize >= SmallAlign and (SmallSize % SmallAlign == 0) and std::popcount(SmallAlign) == 1)) class Event : public EventBase { - static constexpr size_t small_capacity = event_impl::compute_small_capacity(SmallSize); - union { - unsigned char data_[small_capacity]; - max_align_t dummy_; - }; + alignas(SmallAlign) unsigned char data_[SmallSize]; public: - using ThisT = Event; + using ThisT = Event; static constexpr size_t smallCapacity() { - return small_capacity; + return SmallSize; + } + + static constexpr size_t smallAlign() + { + return SmallAlign; } template static constexpr bool is_small_type() { - return alignof(T) <= alignof(max_align_t) && sizeof(T) <= small_capacity; + return alignof(T) <= smallAlign() && sizeof(T) <= smallCapacity(); } Event() @@ -502,27 +563,27 @@ class Event : public EventBase { Event(const ThisT& _other) : EventBase(_other) { - doCopyFrom(data_, small_capacity, _other); + doCopyFrom(data_, smallCapacity(), smallAlign(), _other); } template Event(const Event& _other) : EventBase(_other) { - doCopyFrom(data_, small_capacity, _other); + doCopyFrom(data_, smallCapacity(), smallAlign(), _other); } Event(ThisT&& _other) : EventBase(_other) { - doMoveFrom(data_, small_capacity, _other); + doMoveFrom(data_, smallCapacity(), smallAlign(), _other); } - template - Event(Event&& _other) + template + Event(Event&& _other) : EventBase(_other) { - doMoveFrom(data_, small_capacity, _other); + doMoveFrom(data_, smallCapacity(), smallAlign(), _other); } template >>, std::negation, std::in_place_type_t>>>, int> = 0> @@ -532,7 +593,7 @@ class Event : public EventBase { if constexpr (is_small_type()) { auto& rval = reinterpret_cast(data_); - doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), small_capacity, std::forward(_rvalue)); + doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), std::forward(_rvalue)); } else { doEmplaceBig>(std::forward(_rvalue)); } @@ -545,7 +606,7 @@ class Event : public EventBase { if constexpr (is_small_type()) { auto& rval = reinterpret_cast(data_); - doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), small_capacity, std::forward(_rvalue)); + doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), std::forward(_rvalue)); } else { doEmplaceBig>(std::forward(_rvalue)); } @@ -561,7 +622,7 @@ class Event : public EventBase { { if constexpr (is_small_type()) { auto& rval = reinterpret_cast(data_); - doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), small_capacity, std::forward(_args)...); + doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), std::forward(_args)...); } else { doEmplaceBig>(std::forward(_args)...); } @@ -577,7 +638,7 @@ class Event : public EventBase { { if constexpr (is_small_type()) { auto& rval = reinterpret_cast(data_); - doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), small_capacity, std::forward(_args)...); + doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), std::forward(_args)...); } else { doEmplaceBig>(std::forward(_args)...); } @@ -593,7 +654,7 @@ class Event : public EventBase { { if constexpr (is_small_type()) { auto& rval = reinterpret_cast(data_); - doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), small_capacity, _ilist, std::forward(_args)...); + doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), _ilist, std::forward(_args)...); } else { doEmplaceBig>(_ilist, std::forward(_args)...); } @@ -609,7 +670,7 @@ class Event : public EventBase { { if constexpr (is_small_type()) { auto& rval = reinterpret_cast(data_); - doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), small_capacity, _ilist, std::forward(_args)...); + doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), _ilist, std::forward(_args)...); } else { doEmplaceBig>(_ilist, std::forward(_args)...); } @@ -618,13 +679,13 @@ class Event : public EventBase { Event(const EventBase& _other) : EventBase(_other) { - doCopyFrom(data_, small_capacity, _other); + doCopyFrom(data_, smallCapacity(), smallAlign(), _other); } Event(EventBase&& _other) noexcept : EventBase(_other) { - doMoveFrom(data_, small_capacity, _other); + doMoveFrom(data_, smallCapacity(), smallAlign(), _other); } ThisT& operator=(const ThisT& _other) @@ -636,22 +697,22 @@ class Event : public EventBase { ThisT& operator=(ThisT&& _other) noexcept { reset(_other); - doMoveFrom(data_, small_capacity, _other); + doMoveFrom(data_, smallCapacity(), smallAlign(), _other); return *this; } - template - ThisT& operator=(const Event& _other) + template + ThisT& operator=(const Event& _other) { *this = ThisT{_other}; return *this; } - template - ThisT& operator=(Event&& _other) noexcept + template + ThisT& operator=(Event&& _other) noexcept { reset(_other); - doMoveFrom(data_, small_capacity, _other); + doMoveFrom(data_, smallCapacity(), smallAlign(), _other); return *this; } @@ -662,7 +723,7 @@ class Event : public EventBase { if constexpr (is_small_type()) { auto& rval = reinterpret_cast(data_); - doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), small_capacity, std::forward(_rvalue)); + doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), std::forward(_rvalue)); } else { doEmplaceBig>(std::forward(_rvalue)); } @@ -679,7 +740,7 @@ class Event : public EventBase { resetData(); if constexpr (is_small_type()) { auto& rval = reinterpret_cast(data_); - return doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), small_capacity, std::forward(_args)...); + return doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), std::forward(_args)...); } else { return doEmplaceBig>(std::forward(_args)...); } @@ -691,7 +752,7 @@ class Event : public EventBase { resetData(); if constexpr (is_small_type()) { auto& rval = reinterpret_cast(data_); - return doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), small_capacity, _ilist, std::forward(_args)...); + return doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), _ilist, std::forward(_args)...); } else { return doEmplaceBig>(_ilist, std::forward(_args)...); } @@ -700,14 +761,14 @@ class Event : public EventBase { ThisT& operator=(const EventBase& _other) { reset(_other); - doCopyFrom(data_, small_capacity, _other); + doCopyFrom(data_, smallCapacity(), smallAlign(), _other); return *this; } ThisT& operator=(EventBase&& _other) { reset(_other); - doMoveFrom(data_, small_capacity, _other); + doMoveFrom(data_, smallCapacity(), smallAlign(), _other); return *this; } }; @@ -716,49 +777,49 @@ class Event : public EventBase { // make_event //----------------------------------------------------------------------------- template , int> = 0> -inline Event<> make_event(const Events _id) +inline auto make_event(const Events _id) { return Event<>(_id); } template , int> = 0> -inline Event<> make_event(const EventCategoryBase& _category, const Events _id) +inline auto make_event(const EventCategoryBase& _category, const Events _id) { return Event<>(_category, _id); } template , int> = 0> -inline Event)> make_event(const Events _id, T&& _data) +inline auto make_event(const Events _id, T&& _data) { - return Event)>(_id, std::forward(_data)); + return Event), alignof(std::decay_t)>(_id, std::forward(_data)); } template , int> = 0> -Event)> make_event(const Events _id, Args&&... _args) +auto make_event(const Events _id, Args&&... _args) { - return Event)>{_id, std::in_place_type, std::forward(_args)...}; + return Event), alignof(std::decay_t)>{_id, std::in_place_type, std::forward(_args)...}; } template , int> = 0> -Event)> make_event(const Events _id, std::initializer_list _ilist, Args&&... _args) +auto make_event(const Events _id, std::initializer_list _ilist, Args&&... _args) { - return Event)>{_id, std::in_place_type, _ilist, std::forward(_args)...}; + return Event), alignof(std::decay_t)>{_id, std::in_place_type, _ilist, std::forward(_args)...}; } template , int> = 0> -inline Event)> make_event(const EventCategoryBase& _category, const Events _id, T&& _data) +inline auto make_event(const EventCategoryBase& _category, const Events _id, T&& _data) { - return Event)>(_category, _id, std::forward(_data)); + return Event), alignof(std::decay_t)>(_category, _id, std::forward(_data)); } template , int> = 0> -Event)> make_event(const EventCategoryBase& _category, const Events _id, Args&&... _args) +auto make_event(const EventCategoryBase& _category, const Events _id, Args&&... _args) { - return Event)>{_category, _id, std::in_place_type, std::forward(_args)...}; + return Event), alignof(std::decay_t)>{_category, _id, std::in_place_type, std::forward(_args)...}; } template , int> = 0> -Event)> make_event(const EventCategoryBase& _category, const Events _id, std::initializer_list _ilist, Args&&... _args) +auto make_event(const EventCategoryBase& _category, const Events _id, std::initializer_list _ilist, Args&&... _args) { - return Event)>{_category, _id, std::in_place_type, _ilist, std::forward(_args)...}; + return Event), alignof(std::decay_t)>{_category, _id, std::in_place_type, _ilist, std::forward(_args)...}; } //----------------------------------------------------------------------------- diff --git a/solid/utility/function.hpp b/solid/utility/function.hpp index a986cd311..e9332f5f6 100644 --- a/solid/utility/function.hpp +++ b/solid/utility/function.hpp @@ -58,8 +58,8 @@ enum struct RepresentationE : uintptr_t { constexpr uintptr_t representation_mask = 3; constexpr uintptr_t representation_and_flags_mask = representation_mask; constexpr uintptr_t reversed_representation_and_flags_mask = ~representation_mask; -constexpr uintptr_t representation_small = to_underlying(RepresentationE::Small); -constexpr uintptr_t representation_big = to_underlying(RepresentationE::Big); +constexpr uintptr_t representation_small = to_underlying(RepresentationE::Small); +constexpr uintptr_t representation_big = to_underlying(RepresentationE::Big); template struct SmallRTTI; @@ -100,7 +100,7 @@ struct SmallRTTI { template static void destroy(void* const _what) { - std::destroy_at(static_cast(_what)); + std::destroy_at(std::launder(static_cast(_what))); } InvokeFncT& invoke_fnc_; @@ -141,15 +141,15 @@ inline constexpr BigRTTI big_rtti = { .destroy_fnc_ = &BigRTTI::template destroy, .copy_fnc_ = &do_copy, .move_fnc_ = &do_move_big, - .is_copyable_ = std::is_copy_constructible_v, - .is_movable_ = std::is_move_constructible_v}; + .is_copyable_ = std::is_copy_constructible_v, + .is_movable_ = std::is_move_constructible_v}; template inline constexpr SmallRTTI small_rtti = { - .invoke_fnc_ = do_invoke, + .invoke_fnc_ = do_invoke, .pdestroy_fnc_ = std::is_trivially_copyable_v ? nullptr : &SmallRTTI::template destroy, - .copy_fnc_ = do_copy, - .move_fnc_ = do_move, + .copy_fnc_ = do_copy, + .move_fnc_ = do_move, .is_copyable_ = std::is_copy_constructible_v, .is_movable_ = std::is_move_constructible_v}; @@ -264,7 +264,7 @@ class Function { static constexpr size_t big_padding = small_capacity - sizeof(void*); struct Small { - using RTTI_T = fnc_impl::SmallRTTI; + using RTTI_T = fnc_impl::SmallRTTI; uintptr_t prtti_ = 0; unsigned char data_[small_capacity]; @@ -284,7 +284,6 @@ class Function { uintptr_t prtti_; void* ptr_; unsigned char padding_[big_padding]; - [[nodiscard]] auto* rtti() const noexcept { @@ -401,7 +400,7 @@ class Function { storage_.small_.rtti(reinterpret_cast(&fnc_impl::small_rtti)); auto& rval = reinterpret_cast(storage_.small_.data_); std::construct_at(std::addressof(rval), std::move(_fun)); - //new (&rval) FncT(std::move(_fun)); + // new (&rval) FncT(std::move(_fun)); } else { #if defined(SOLID_THROW_ON_BIG_FUNCTION) solid_throw("Big Function"); @@ -486,15 +485,21 @@ class Function { R operator()(ArgTypes... _args) const { - if (has_value()) { - if (is_small()) [[likely]] { - return storage_.small_.rtti()->invoke_fnc_(&storage_.small_.data_, static_cast(_args)... /* std::forward(_args)... */); - } else { - return storage_.big_.rtti()->invoke_fnc_(storage_.big_.ptr_, static_cast(_args)... /* std::forward(_args)... */); - } + auto const rtti = storage_.small_.prtti_; + if (auto const rtti = storage_.small_.prtti_; (rtti & fnc_impl::representation_mask) == 1) [[likely]] { + return reinterpret_cast(rtti & fnc_impl::reversed_representation_and_flags_mask)->invoke_fnc_(&storage_.small_.data_, static_cast(_args)...); } else { throw std::bad_function_call(); } +#if 0 + if (auto const repr = representation(); true /* repr == fnc_impl::RepresentationE::Small */) [[likely]] { + return storage_.small_.rtti()->invoke_fnc_(&storage_.small_.data_, static_cast(_args)... /* std::forward(_args)... */); + } else if (repr == fnc_impl::RepresentationE::Big) { + return storage_.big_.rtti()->invoke_fnc_(storage_.big_.ptr_, static_cast(_args)... /* std::forward(_args)... */); + } else { + throw std::bad_function_call(); + } +#endif } template @@ -602,7 +607,7 @@ class Function { if constexpr (is_small_type()) { storage_.small_.rtti(reinterpret_cast(&fnc_impl::small_rtti)); auto& rval = reinterpret_cast(storage_.small_.data_); - //std::construct_at(std::addressof(rval), std::move(_fun)); + // std::construct_at(std::addressof(rval), std::move(_fun)); new (&rval) FncT(std::move(_fun)); } else { #if defined(SOLID_THROW_ON_BIG_FUNCTION) diff --git a/solid/utility/test/test_any.cpp b/solid/utility/test/test_any.cpp index cfffecef5..38c08a9a2 100644 --- a/solid/utility/test/test_any.cpp +++ b/solid/utility/test/test_any.cpp @@ -245,8 +245,8 @@ int test_any(int /*argc*/, char* /*argv*/[]) solid_check(ptr.use_count() == 0); } { - Any any_t{Test{10}}; - Any<> any_0{std::move(any_t)}; + Any<8, sizeof(uintptr_t)> any_t{Test{10}}; + Any<> any_0{std::move(any_t)}; solid_check(!any_t.has_value()); solid_check(any_0.has_value()); @@ -262,7 +262,7 @@ int test_any(int /*argc*/, char* /*argv*/[]) { using Array4T = std::array; - Any<8> any{Array4T{{1, 2, 3, 4}}}; + Any<8, 8> any{Array4T{{1, 2, 3, 4}}}; solid_check((*any.cast())[0] == 1); solid_check((*any.cast())[1] == 2); solid_check((*any.cast())[2] == 3); @@ -273,7 +273,7 @@ int test_any(int /*argc*/, char* /*argv*/[]) { using Array4T = std::array; - Any<128> any(Array4T{{1, 2, 3, 4}}); + Any<128, 8> any(Array4T{{1, 2, 3, 4}}); solid_check((*any.cast())[0] == 1); solid_check((*any.cast())[1] == 2); solid_check((*any.cast())[2] == 3); @@ -285,7 +285,7 @@ int test_any(int /*argc*/, char* /*argv*/[]) { using Array4T = std::array; - Any<128> any; + Any<128, 8> any; any = Array4T{{1, 2, 3, 4}}; solid_check((*any.cast())[0] == 1); solid_check((*any.cast())[1] == 2); @@ -301,7 +301,7 @@ int test_any(int /*argc*/, char* /*argv*/[]) solid_check(arr[3] == 4); arr[3] = 10; }; - Any<128> any; + Any<128, 8> any; any = lambda; (*any.cast())("Test"); } @@ -312,7 +312,7 @@ int test_any(int /*argc*/, char* /*argv*/[]) solid_check(arr[3] == 4); arr[3] = 10; }; - Any<128> any(lambda); + Any<128, 8> any(lambda); (*any.cast())("Test"); } @@ -324,7 +324,7 @@ int test_any(int /*argc*/, char* /*argv*/[]) solid_check(arr[3] == 4); arr[3] = 10; }; - Any<128> any(std::move(lambda)); + Any<128, 8> any(std::move(lambda)); (*any.cast())("Test"); } diff --git a/solid/utility/test/test_event.cpp b/solid/utility/test/test_event.cpp index ddc6080f0..0c4525a6b 100644 --- a/solid/utility/test/test_event.cpp +++ b/solid/utility/test/test_event.cpp @@ -132,12 +132,12 @@ int test_event(int /*argc*/, char* /*argv*/[]) check_event(tuple_event); - Event<8> tuple_event8(tuple_event); + Event<8, 8> tuple_event8(tuple_event); check_event(tuple_event8); check_event(tuple_event); { - Event<8> tuple_event8(std::move(tuple_event)); + Event<8, 8> tuple_event8(std::move(tuple_event)); check_event(tuple_event8); solid_check(!tuple_event); } @@ -146,7 +146,7 @@ int test_event(int /*argc*/, char* /*argv*/[]) check_event(tuple_event8); check_event(tuple_event); - Event<10> tuple_event10; + Event<16, 8> tuple_event10; tuple_event10 = std::move(tuple_event); solid_check(!tuple_event); diff --git a/solid/utility/test/test_function_any_speed.cpp b/solid/utility/test/test_function_any_speed.cpp index 540923986..d9014fcba 100644 --- a/solid/utility/test/test_function_any_speed.cpp +++ b/solid/utility/test/test_function_any_speed.cpp @@ -18,8 +18,8 @@ struct Event { #ifdef EVENT_USE_STD_ANY using AnyT = std::any; #else - static constexpr size_t any_size = 1; // sizeof(void*) == 8 ? any_size_from_sizeof(64 - sizeof(void*) - sizeof(uintptr_t)) : any_size_from_sizeof(32 - sizeof(void*) - sizeof(uintptr_t)); - using AnyT = Any; + static constexpr size_t any_size = 32 - sizeof(uintptr_t); + using AnyT = Any; #endif Event(); Event(Event&&); diff --git a/solid/utility/test/test_queue.cpp b/solid/utility/test/test_queue.cpp index 76e6da9c6..331b33a9c 100644 --- a/solid/utility/test/test_queue.cpp +++ b/solid/utility/test/test_queue.cpp @@ -55,7 +55,7 @@ struct UniqueId { typedef solid_function_t(void(size_t&, EventBase&&)) EventFunctionT; struct ExecStub { - using EventT = Event<256>; + using EventT = Event<256, 8>; UniqueId actuid; UniqueId chnuid; EventFunctionT exefnc; @@ -120,7 +120,7 @@ int test_queue(int args, char* argv[]) } while (!eventq.empty()) { - eventq.front().exefnc(v, Event<128>(eventq.front().event)); + eventq.front().exefnc(v, Event<128, 8>(eventq.front().event)); eventq.pop(); } cout << "v = " << v << endl; From 6748e87245cb10a369a723a6b9a7ee1d569ea67c Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Fri, 31 Oct 2025 19:48:18 +0200 Subject: [PATCH 14/56] utility: improve function and clean any code --- solid/frame/mprpc/mprpcsocketstub_plain.hpp | 4 +- solid/utility/any.hpp | 193 +-------- solid/utility/function.hpp | 426 ++++++++------------ 3 files changed, 174 insertions(+), 449 deletions(-) diff --git a/solid/frame/mprpc/mprpcsocketstub_plain.hpp b/solid/frame/mprpc/mprpcsocketstub_plain.hpp index 69aae976d..9c890bc68 100644 --- a/solid/frame/mprpc/mprpcsocketstub_plain.hpp +++ b/solid/frame/mprpc/mprpcsocketstub_plain.hpp @@ -147,7 +147,7 @@ inline SocketStubPtrT create_client_socket(Configuration const& /*_rcfg*/, frame { #ifdef SOLID_HAS_ASSERT static_assert(sizeof(SocketStub) <= socket_emplace_size); - static_assert(alignof(SocketStub) == socket_emplace_align); + static_assert(alignof(SocketStub) <= socket_emplace_align); #endif if constexpr (sizeof(SocketStub) > socket_emplace_size and alignof(SocketStub) > socket_emplace_align) { return SocketStubPtrT(new SocketStub(_rproxy), SocketStub::delete_deleter); @@ -160,7 +160,7 @@ inline SocketStubPtrT create_server_socket(Configuration const& /*_rcfg*/, frame { #ifdef SOLID_HAS_ASSERT static_assert(sizeof(SocketStub) <= socket_emplace_size); - static_assert(alignof(SocketStub) == socket_emplace_align); + static_assert(alignof(SocketStub) <= socket_emplace_align); #endif if constexpr (sizeof(SocketStub) > socket_emplace_size and alignof(SocketStub) > socket_emplace_align) { return SocketStubPtrT(new SocketStub(_rproxy, std::move(_usd)), SocketStub::delete_deleter); diff --git a/solid/utility/any.hpp b/solid/utility/any.hpp index 9746e4cac..f8994ac6b 100644 --- a/solid/utility/any.hpp +++ b/solid/utility/any.hpp @@ -9,7 +9,6 @@ // #pragma once -// #define SOLID_THROW_ON_BIG_ANY #include #include #include @@ -18,7 +17,7 @@ #include "solid/system/exception.hpp" #include "solid/system/log.hpp" -#include "solid/utility/common.hpp" +#include "solid/utility/anyimpl.hpp" #include "solid/utility/typetraits.hpp" namespace solid { @@ -34,8 +33,8 @@ class Any; template struct is_any; -template -struct is_any> : std::true_type { +template +struct is_any> : std::true_type { }; template @@ -43,29 +42,6 @@ struct is_any : std::false_type { }; namespace any_impl { -enum struct RepresentationE : uintptr_t { - None = 0, - Small, - Big, -}; -constexpr uintptr_t representation_mask = 3; -constexpr uintptr_t representation_and_flags_mask = representation_mask; -constexpr uintptr_t reversed_representation_and_flags_mask = ~representation_mask; - -inline RepresentationE representation(uintptr_t const _rtti) noexcept -{ - return static_cast(_rtti & representation_mask); -} - -inline uintptr_t representation(uintptr_t const _rtti, RepresentationE const _repr) noexcept -{ - return (_rtti & (~representation_and_flags_mask)) | to_underlying(_repr); -} - -inline uintptr_t representation(void const* _rtti, RepresentationE const _repr) noexcept -{ - return (reinterpret_cast(_rtti) & (~representation_and_flags_mask)) | to_underlying(_repr); -} struct SmallRTTI; struct BigRTTI; @@ -101,12 +77,6 @@ struct BigRTTI : BaseRTTI { ::delete static_cast(_what); } - template - static void* move(void* const _from) - { - return ::new T(std::move(*static_cast(_from))); - } - static BigRTTI const& get(uintptr_t const _rtti) noexcept { return *reinterpret_cast(_rtti & reversed_representation_and_flags_mask); @@ -122,9 +92,6 @@ struct SmallRTTI : BaseRTTI { { std::destroy_at(std::launder(static_cast(_what))); } - static void dummy_destroy(void* const _what) noexcept - { - } static SmallRTTI const& get(uintptr_t const _rtti) noexcept { @@ -166,7 +133,6 @@ inline constexpr BigRTTI big_rtti = { std::is_move_constructible_v, is_specialization_v}, BigRTTI::destroy}; -//&BigRTTI::destroy, &do_copy, &do_move_big, &do_get_if, std::is_copy_constructible_v, std::is_move_constructible_v, is_specialization_v}; template inline constexpr SmallRTTI small_rtti = { @@ -177,34 +143,7 @@ inline constexpr SmallRTTI small_rtti = { std::is_copy_constructible_v, std::is_move_constructible_v, is_specialization_v}, - &SmallRTTI::destroy}; -//&SmallRTTI::destroy, &do_copy, &do_move, &do_get_if, std::is_copy_constructible_v, std::is_move_constructible_v, is_specialization_v}; - -#if 0 // TODO:remove -inline RepresentationE do_dummy_copy( - const void* _pfrom, - void* _pto_small, const size_t _small_cap, const SmallRTTI*& _rpsmall_rtti, - void*& _rpto_big, const BigRTTI*& _rpbig_rtti) -{ - return RepresentationE::None; -} - -inline RepresentationE do_dummy_move( - void* _pfrom, - void* _pto_small, const size_t _small_cap, const SmallRTTI*& _rpsmall_rtti, - void*& _rpto_big, const BigRTTI*& _rpbig_rtti) -{ - return RepresentationE::None; -} - -inline const void* do_dummy_get_if(const std::type_index& _type_index, const void* _pdata) -{ - return nullptr; -} - -inline constexpr SmallRTTI dummy_small_rtti = { - &SmallRTTI::dummy_destroy, &do_dummy_copy, &do_dummy_move, &do_dummy_get_if, false, false, false}; -#endif + std::is_trivially_copyable_v ? nullptr : &SmallRTTI::destroy}; template uintptr_t do_copy( @@ -218,22 +157,10 @@ uintptr_t do_copy( const T& rsrc = *static_cast(_pfrom); ::new (const_cast(static_cast(std::addressof(rdst)))) T(rsrc); return representation(&small_rtti, RepresentationE::Small); - //_rpsmall_rtti = &small_rtti; - // return RepresentationE::Small; } else { -#if defined(SOLID_THROW_ON_BIG_ANY) - solid_throw("Big Any"); -#endif _rpto_big = ::new T(*static_cast(_pfrom)); return representation(&big_rtti, RepresentationE::Big); - //_rpbig_rtti = &big_rtti; - // return RepresentationE::Big; } - } else if constexpr (std::is_trivially_constructible_v || std::is_copy_constructible_v) { - _rpto_big = ::new T(*static_cast(_pfrom)); - return representation(&big_rtti, RepresentationE::Big); - //_rpbig_rtti = &big_rtti; - // return RepresentationE::Big; } else { solid_throw("Any: contained value not copyable"); return 0; @@ -252,25 +179,10 @@ uintptr_t do_move( T& rsrc = *static_cast(_pfrom); ::new (const_cast(static_cast(std::addressof(rdst)))) T{std::move(rsrc)}; return representation(&small_rtti, RepresentationE::Small); - //_rpsmall_rtti = &small_rtti; - // return RepresentationE::Small; } else { -#if defined(SOLID_THROW_ON_BIG_ANY) - solid_throw("Big Any"); -#endif _rpto_big = ::new T{std::move(*static_cast(_pfrom))}; return representation(&big_rtti, RepresentationE::Big); - //_rpbig_rtti = &big_rtti; - // return RepresentationE::Big; } - } else if constexpr (std::is_move_constructible_v) { -#if defined(SOLID_THROW_ON_BIG_ANY) - solid_throw("Big Any"); -#endif - _rpto_big = ::new T{std::move(*static_cast(_pfrom))}; - return representation(&big_rtti, RepresentationE::Big); - //_rpbig_rtti = &big_rtti; - // return RepresentationE::Big; } else { solid_throw("Any: contained value not movable"); return 0; @@ -283,25 +195,19 @@ uintptr_t do_move_big( void* _pto_small, const size_t _small_cap, const size_t _small_align, void*& _rpto_big) { - if constexpr (alignof(T) <= alignof(max_align_t) && std::is_move_constructible_v) { + if constexpr (std::is_move_constructible_v) { if (sizeof(T) <= _small_cap and alignof(T) <= _small_align) { T& rdst = *static_cast(_pto_small); T& rsrc = *static_cast(_pfrom); ::new (const_cast(static_cast(std::addressof(rdst)))) T{std::move(rsrc)}; return representation(&small_rtti, RepresentationE::Small); - //_rpsmall_rtti = &small_rtti; - // return RepresentationE::Small; } else { _rpto_big = static_cast(_pfrom); return representation(&big_rtti, RepresentationE::Big); - //_rpbig_rtti = &big_rtti; - // return RepresentationE::Big; } } else { _rpto_big = static_cast(_pfrom); return representation(&big_rtti, RepresentationE::Big); - //_rpbig_rtti = &big_rtti; - // return RepresentationE::Big; } } @@ -363,7 +269,6 @@ class Any { private: const std::type_info* typeInfo() const noexcept { - // return reinterpret_cast(storage_.type_data_ & ~any_impl::representation_and_flags_mask); auto const rtti = rtti_; if (rtti) [[likely]] { return any_impl::BaseRTTI::get(rtti).get_type_info_fnc_(); @@ -598,14 +503,6 @@ class Any { return any_impl::BaseRTTI::get(rtti).is_movable_; } return true; -#if 0 - if (is_small()) { - return storage_.small_.prtti_->is_movable_; - } else if (is_big()) { - return storage_.big_.prtti_->is_movable_; - } - return true; -#endif } bool is_copyable() const { @@ -614,14 +511,6 @@ class Any { return any_impl::BaseRTTI::get(rtti).is_copyable_; } return true; -#if 0 - if (is_small()) { - return storage_.small_.prtti_->is_copyable_; - } else if (is_big()) { - return storage_.big_.prtti_->is_copyable_; - } - return true; -#endif } bool is_tuple() const @@ -631,14 +520,6 @@ class Any { return any_impl::BaseRTTI::get(rtti).is_tuple_; } return false; -#if 0 - if (is_small()) { - return storage_.small_.prtti_->is_tuple_; - } else if (is_big()) { - return storage_.big_.prtti_->is_tuple_; - } - return false; -#endif } bool is_small() const @@ -677,34 +558,6 @@ class Any { default: break; } -#if 0 - storage_.type_data_ = _other.storage_.type_data_; - representation(any_impl::RepresentationE::None); - switch (_other.representation()) { - case any_impl::RepresentationE::Small: { - const auto repr = _other.storage_.small_.prtti_->pmove_fnc_( - _other.storage_.small_.data_, - storage_.small_.data_, small_capacity, storage_.small_.prtti_, - storage_.big_.pdata_, storage_.big_.prtti_); - representation(repr); - _other.reset(); - } break; - case any_impl::RepresentationE::Big: { - const auto repr = _other.storage_.big_.prtti_->pmove_fnc_( - _other.storage_.big_.ptr_, - storage_.small_.data_, small_capacity, storage_.small_.prtti_, - storage_.big_.ptr_, storage_.big_.prtti_); - representation(repr); - if (repr == any_impl::RepresentationE::Big) { - _other.storage_.type_data_ = 0; - } else { - _other.reset(); - } - } break; - default: - break; - } -#endif } template @@ -728,29 +581,6 @@ class Any { default: break; } - -#if 0 - storage_.type_data_ = _other.storage_.type_data_; - representation(any_impl::RepresentationE::None); - switch (_other.representation()) { - case any_impl::RepresentationE::Small: { - const auto repr = _other.storage_.small_.prtti_->pcopy_fnc_( - _other.storage_.small_.data_, - storage_.small_.data_, small_capacity, storage_.small_.prtti_, - storage_.big_.ptr_, storage_.big_.prtti_); - representation(repr); - } break; - case any_impl::RepresentationE::Big: { - const auto repr = _other.storage_.big_.prtti_->pcopy_fnc_( - _other.storage_.big_.ptr_, - storage_.small_.data_, small_capacity, storage_.small_.prtti_, - storage_.big_.ptr_, storage_.big_.prtti_); - representation(repr); - } break; - default: - break; - } -#endif } template @@ -758,26 +588,13 @@ class Any { { if constexpr (is_small_type()) { auto& rval = reinterpret_cast(small_.data_); - ::new (const_cast(static_cast(std::addressof(rval)))) T{std::forward(_args)...}; - rtti_ = representation(&any_impl::small_rtti, any_impl::RepresentationE::Small); - // storage_.small_.prtti_ = &any_impl::small_rtti; - // storage_.type_data_ = reinterpret_cast(&typeid(T)); - // representation(any_impl::RepresentationE::Small); - return rval; } else { -#if defined(SOLID_THROW_ON_BIG_ANY) - solid_throw("Big Any"); -#endif T* const ptr = ::new T(std::forward(_args)...); big_.pdata_ = ptr; rtti_ = representation(&any_impl::big_rtti, any_impl::RepresentationE::Big); - - // storage_.big_.prtti_ = &any_impl::big_rtti; - // storage_.type_data_ = reinterpret_cast(&typeid(T)); - // representation(any_impl::RepresentationE::Big); return *ptr; } } diff --git a/solid/utility/function.hpp b/solid/utility/function.hpp index e9332f5f6..6f82f984c 100644 --- a/solid/utility/function.hpp +++ b/solid/utility/function.hpp @@ -10,6 +10,7 @@ #pragma once #include #include +#include #include #define SOLID_THROW_ON_BIG_FUNCTION #include @@ -20,29 +21,23 @@ #include "solid/system/exception.hpp" #include "solid/system/log.hpp" +#include "solid/utility/anyimpl.hpp" #include "solid/utility/common.hpp" #include "solid/utility/typetraits.hpp" namespace solid { -#if 0 // TODO:remove -inline constexpr size_t function_default_data_size = 3 * sizeof(void*); +constexpr size_t function_default_size = 32 - sizeof(std::uintptr_t); +constexpr size_t function_default_align = alignof(std::uintptr_t); -template -inline constexpr const T& function_max(const T& a, const T& b) -{ - return (a < b) ? b : a; -} -#endif - -template +template class Function; // undefined template struct is_function; -template -struct is_function> : std::true_type { +template +struct is_function> : std::true_type { }; template @@ -50,29 +45,33 @@ struct is_function : std::false_type { }; namespace fnc_impl { -enum struct RepresentationE : uintptr_t { - None = 0, - Small, - Big, -}; -constexpr uintptr_t representation_mask = 3; -constexpr uintptr_t representation_and_flags_mask = representation_mask; -constexpr uintptr_t reversed_representation_and_flags_mask = ~representation_mask; -constexpr uintptr_t representation_small = to_underlying(RepresentationE::Small); -constexpr uintptr_t representation_big = to_underlying(RepresentationE::Big); -template -struct SmallRTTI; +using any_impl::representation; +using any_impl::RepresentationE; +using any_impl::reversed_representation_and_flags_mask; template -struct BigRTTI { - using BigRTTIT = BigRTTI; - using SmallRTTIT = SmallRTTI; +struct BaseRTTI { + using CopyFncT = uintptr_t(const void*, void*, size_t, size_t, void*&); + using MoveFncT = uintptr_t(void*, void*, size_t, size_t, void*&); + using InvokeFncT = R(void*, ArgTypes&&...); + + InvokeFncT& invoke_fnc_; + CopyFncT& copy_fnc_; + MoveFncT& move_fnc_; + const bool is_copyable_; + const bool is_movable_; + + static BaseRTTI const& get(uintptr_t const _rtti) noexcept + { + return *reinterpret_cast(_rtti & reversed_representation_and_flags_mask); + } +}; - using DestroyFncT = void(void*); - using CopyFncT = RepresentationE(const void*, void*, const size_t, uintptr_t&, void*&, uintptr_t&); - using MoveFncT = RepresentationE(void*, void*, const size_t, uintptr_t&, void*&, uintptr_t&); - using InvokeFncT = R(const void*, ArgTypes&&...); +template +struct BigRTTI : BaseRTTI { + using DestroyFncT = void(void*) noexcept; + DestroyFncT& destroy_fnc_; template static void destroy(void* const _what) noexcept @@ -80,264 +79,193 @@ struct BigRTTI { ::delete static_cast(_what); } - InvokeFncT& invoke_fnc_; - DestroyFncT& destroy_fnc_; - CopyFncT& copy_fnc_; - MoveFncT& move_fnc_; - const bool is_copyable_; - const bool is_movable_; + static BigRTTI const& get(uintptr_t const _rtti) noexcept + { + return *reinterpret_cast(_rtti & reversed_representation_and_flags_mask); + } }; template -struct SmallRTTI { - using BigRTTIT = BigRTTI; - using SmallRTTIT = SmallRTTI; - using DestroyFncT = void(void*); - using CopyFncT = RepresentationE(const void*, void*, const size_t, uintptr_t&, void*&, uintptr_t&); - using MoveFncT = RepresentationE(void*, void*, const size_t, uintptr_t&, void*&, uintptr_t&); - using InvokeFncT = R(const void*, ArgTypes&&...); +struct SmallRTTI : BaseRTTI { + using DestroyFncT = void(void*) noexcept; + + DestroyFncT* pdestroy_fnc_; template - static void destroy(void* const _what) + static void destroy(void* const _what) noexcept { std::destroy_at(std::launder(static_cast(_what))); } - InvokeFncT& invoke_fnc_; - DestroyFncT* pdestroy_fnc_; - CopyFncT& copy_fnc_; - MoveFncT& move_fnc_; - const bool is_copyable_; - const bool is_movable_; + static SmallRTTI const& get(uintptr_t const _rtti) noexcept + { + return *reinterpret_cast(_rtti & reversed_representation_and_flags_mask); + } }; template -R do_invoke(const void* _pvalue, ArgTypes&&... _args) +R do_invoke(void* _pvalue, ArgTypes&&... _args) { - return std::invoke(*const_cast(static_cast(_pvalue)), static_cast(_args)... /* std::forward(_args)... */); + T* pfun = reinterpret_cast(_pvalue); + return std::invoke(*pfun, static_cast(_args)... /* std::forward(_args)... */); } template -RepresentationE do_copy( - const void* _pfrom, - void* _pto_small, const size_t _small_cap, uintptr_t& _rpsmall_rtti, - void*& _rpto_big, uintptr_t& _rpbig_rtti); +uintptr_t do_copy( + const void*, + void*, size_t, size_t, + void*&); template -RepresentationE do_move( - void* _pfrom, - void* _pto_small, const size_t _small_cap, uintptr_t& _rpsmall_rtti, - void*& _rpto_big, uintptr_t& _rpbig_rtti); +uintptr_t do_move( + void*, + void*, size_t, size_t, + void*&); template -RepresentationE do_move_big( - void* _pfrom, - void* _pto_small, const size_t _small_cap, uintptr_t& _rpsmall_rtti, - void*& _rpto_big, uintptr_t& _rpbig_rtti); +uintptr_t do_move_big( + void*, + void*, size_t, size_t, + void*&); template inline constexpr BigRTTI big_rtti = { - .invoke_fnc_ = do_invoke, - .destroy_fnc_ = &BigRTTI::template destroy, - .copy_fnc_ = &do_copy, - .move_fnc_ = &do_move_big, - .is_copyable_ = std::is_copy_constructible_v, - .is_movable_ = std::is_move_constructible_v}; + {do_invoke, + do_copy, + do_move_big, + std::is_copy_constructible_v, + std::is_move_constructible_v}, + BigRTTI::template destroy, +}; template inline constexpr SmallRTTI small_rtti = { - .invoke_fnc_ = do_invoke, - .pdestroy_fnc_ = std::is_trivially_copyable_v ? nullptr : &SmallRTTI::template destroy, - .copy_fnc_ = do_copy, - .move_fnc_ = do_move, - .is_copyable_ = std::is_copy_constructible_v, - .is_movable_ = std::is_move_constructible_v}; + {do_invoke, + do_copy, + do_move, + std::is_copy_constructible_v, + std::is_move_constructible_v}, + std::is_trivially_copyable_v ? nullptr : &SmallRTTI::template destroy, +}; template -RepresentationE do_copy( +uintptr_t do_copy( const void* _pfrom, - void* _pto_small, const size_t _small_cap, uintptr_t& _rpsmall_rtti, - void*& _rpto_big, uintptr_t& _rpbig_rtti) + void* _pto_small, const size_t _small_cap, const size_t _small_align, + void*& _rpto_big) { - if constexpr (alignof(T) <= alignof(max_align_t) && std::is_copy_constructible_v) { - if (sizeof(T) <= _small_cap) { + if constexpr (std::is_copy_constructible_v) { + if (sizeof(T) <= _small_cap and alignof(T) <= _small_align) { T& rdst = *static_cast(_pto_small); const T& rsrc = *static_cast(_pfrom); ::new (const_cast(static_cast(std::addressof(rdst)))) T(rsrc); - _rpsmall_rtti = reinterpret_cast(&small_rtti); - return RepresentationE::Small; + return representation(&small_rtti, RepresentationE::Small); } else { #if defined(SOLID_THROW_ON_BIG_FUNCTION) solid_throw("Big Function"); #endif - _rpto_big = ::new T(*static_cast(_pfrom)); - _rpbig_rtti = reinterpret_cast(&big_rtti); - return RepresentationE::Big; + _rpto_big = ::new T(*static_cast(_pfrom)); + return representation(&big_rtti, RepresentationE::Big); } - } else if constexpr (std::is_trivially_constructible_v || std::is_copy_constructible_v) { -#if defined(SOLID_THROW_ON_BIG_FUNCTION) - solid_throw("Big Function"); -#endif - _rpto_big = ::new T(*static_cast(_pfrom)); - _rpbig_rtti = reinterpret_cast(&big_rtti); - return RepresentationE::Big; } else { solid_throw("Function: contained value not copyable"); - return RepresentationE::None; + return 0; } } template -RepresentationE do_move( +uintptr_t do_move( void* _pfrom, - void* _pto_small, const size_t _small_cap, uintptr_t& _rpsmall_rtti, - void*& _rpto_big, uintptr_t& _rpbig_rtti) + void* _pto_small, const size_t _small_cap, const size_t _small_align, + void*& _rpto_big) { - if constexpr (alignof(T) <= alignof(max_align_t) && std::is_move_constructible_v) { - if (sizeof(T) <= _small_cap) { + if constexpr (std::is_move_constructible_v) { + if (sizeof(T) <= _small_cap and alignof(T) <= _small_align) { T& rdst = *static_cast(_pto_small); T& rsrc = *static_cast(_pfrom); ::new (const_cast(static_cast(std::addressof(rdst)))) T{std::move(rsrc)}; - _rpsmall_rtti = reinterpret_cast(&small_rtti); - return RepresentationE::Small; + return representation(&small_rtti, RepresentationE::Small); } else { #if defined(SOLID_THROW_ON_BIG_FUNCTION) solid_throw("Big Function"); #endif - _rpto_big = ::new T{std::move(*static_cast(_pfrom))}; - _rpbig_rtti = reinterpret_cast(&big_rtti); - return RepresentationE::Big; + _rpto_big = ::new T{std::move(*static_cast(_pfrom))}; + return representation(&big_rtti, RepresentationE::Big); } - } else if constexpr (std::is_move_constructible_v) { -#if defined(SOLID_THROW_ON_BIG_FUNCTION) - solid_throw("Big Function"); -#endif - _rpto_big = ::new T{std::move(*static_cast(_pfrom))}; - _rpbig_rtti = reinterpret_cast(&big_rtti); - return RepresentationE::Big; } else { solid_throw("Function: contained value not movable"); - return RepresentationE::None; + return 0u; } } template -RepresentationE do_move_big( +uintptr_t do_move_big( void* _pfrom, - void* _pto_small, const size_t _small_cap, uintptr_t& _rpsmall_rtti, - void*& _rpto_big, uintptr_t& _rpbig_rtti) + void* _pto_small, const size_t _small_cap, const size_t _small_align, + void*& _rpto_big) { - if constexpr (alignof(T) <= alignof(max_align_t) && std::is_move_constructible_v) { - if (sizeof(T) <= _small_cap) { + if constexpr (std::is_move_constructible_v) { + if (sizeof(T) <= _small_cap and alignof(T) <= _small_align) { T& rdst = *static_cast(_pto_small); T& rsrc = *static_cast(_pfrom); ::new (const_cast(static_cast(std::addressof(rdst)))) T{std::move(rsrc)}; - _rpsmall_rtti = reinterpret_cast(&small_rtti); - return RepresentationE::Small; + return representation(&small_rtti, RepresentationE::Small); } else { - _rpto_big = static_cast(_pfrom); //::new T{ std::move(*static_cast(_pfrom)) }; - _rpbig_rtti = reinterpret_cast(&big_rtti); - return RepresentationE::Big; + _rpto_big = static_cast(_pfrom); + return representation(&big_rtti, RepresentationE::Big); } } else { - _rpto_big = static_cast(_pfrom); //::new T{ std::move(*static_cast(_pfrom)) }; - _rpbig_rtti = reinterpret_cast(&big_rtti); - return RepresentationE::Big; + _rpto_big = static_cast(_pfrom); + return representation(&big_rtti, RepresentationE::Big); } } -constexpr size_t compute_small_capacity(const size_t _req_capacity) -{ - constexpr size_t default_total_size = 32u; - - const size_t end_capacity = sizeof(void*); - const size_t req_capacity = std::max(_req_capacity, std::max(end_capacity, sizeof(max_align_t)) - end_capacity); - const size_t tot_capacity = std::max(default_total_size, padded_size(req_capacity + sizeof(void*), alignof(max_align_t))); - - return tot_capacity - end_capacity; -} } // namespace fnc_impl -template -class Function { - static constexpr size_t small_capacity = fnc_impl::compute_small_capacity(DataSize); - static constexpr size_t big_padding = small_capacity - sizeof(void*); +template +class Function { + using BaseRTTI_T = fnc_impl::BaseRTTI; struct Small { - using RTTI_T = fnc_impl::SmallRTTI; - uintptr_t prtti_ = 0; - unsigned char data_[small_capacity]; - - [[nodiscard]] auto* rtti() const noexcept - { - return reinterpret_cast(prtti_ & fnc_impl::reversed_representation_and_flags_mask); - } - - void rtti(uintptr_t const _ptr) - { - prtti_ = _ptr | fnc_impl::representation_small; - } + using RTTI_T = fnc_impl::SmallRTTI; + alignas(SmallAlign) mutable unsigned char data_[SmallSize]; }; struct Big { using RTTI_T = fnc_impl::BigRTTI; - uintptr_t prtti_; - void* ptr_; - unsigned char padding_[big_padding]; - - [[nodiscard]] auto* rtti() const noexcept - { - return reinterpret_cast(prtti_ & fnc_impl::reversed_representation_and_flags_mask); - } - - void rtti(uintptr_t const _ptr) - { - prtti_ = _ptr | fnc_impl::representation_big; - } + mutable void* ptr_; }; struct Storage { + uintptr_t rtti_ = 0; union { Small small_; Big big_; }; }; - union { - Storage storage_{}; - std::max_align_t dummy_; - }; - template + Storage storage_{}; + + template friend class Function; -private: - fnc_impl::RepresentationE representation() const noexcept +public: + using ThisT = Function; + + static constexpr size_t smallCapacity() { - auto const retval = static_cast(storage_.small_.prtti_ & fnc_impl::representation_and_flags_mask); - assert(retval == static_cast(storage_.big_.prtti_ & fnc_impl::representation_and_flags_mask)); - return retval; + return SmallSize; } - void representation(const fnc_impl::RepresentationE _repr) noexcept + static constexpr size_t smallAlign() { - // storage_.small_.prtti_ &= (~fnc_impl::representation_and_flags_mask); - // storage_.small_.prtti_ |= static_cast(_repr); - storage_.small_.prtti_ = (storage_.small_.prtti_ & (~fnc_impl::representation_and_flags_mask)) | to_underlying(_repr); - assert(_repr == static_cast(storage_.big_.prtti_ & fnc_impl::representation_and_flags_mask)); + return SmallAlign; } -public: - using ThisT = Function; - template static constexpr bool is_small_type() { - return alignof(T) <= alignof(max_align_t) && sizeof(T) <= small_capacity; - } - - static constexpr size_t smallCapacity() - { - return small_capacity; + return alignof(T) <= smallAlign() && sizeof(T) <= smallCapacity(); } Function() noexcept = default; @@ -365,7 +293,7 @@ class Function { { doMoveFrom(_other); } -#if 1 + template >>, std::negation, std::in_place_type_t>> /*, std::is_copy_constructible>*/ >, @@ -375,8 +303,8 @@ class Function { { using FncT = std::remove_cvref_t>; if constexpr (is_small_type()) { - storage_.small_.rtti(reinterpret_cast(&fnc_impl::small_rtti)); - auto& rval = reinterpret_cast(storage_.small_.data_); + storage_.rtti_ = fnc_impl::representation(&fnc_impl::small_rtti, fnc_impl::RepresentationE::Small); + auto& rval = reinterpret_cast(storage_.small_.data_); std::construct_at(std::addressof(rval), _fun); } else { #if defined(SOLID_THROW_ON_BIG_FUNCTION) @@ -384,10 +312,9 @@ class Function { #endif FncT* const ptr = ::new FncT(_fun); storage_.big_.ptr_ = ptr; - storage_.big_.rtti(reinterpret_cast(&fnc_impl::big_rtti)); + storage_.rtti_ = fnc_impl::representation(&fnc_impl::big_rtti, fnc_impl::RepresentationE::Big); } } -#endif template >>, std::negation, std::in_place_type_t>> /*, std::is_copy_constructible>*/ >, @@ -397,30 +324,30 @@ class Function { { using FncT = std::remove_cvref_t; if constexpr (is_small_type()) { - storage_.small_.rtti(reinterpret_cast(&fnc_impl::small_rtti)); - auto& rval = reinterpret_cast(storage_.small_.data_); + storage_.rtti_ = fnc_impl::representation(&fnc_impl::small_rtti, fnc_impl::RepresentationE::Small); + auto& rval = reinterpret_cast(storage_.small_.data_); std::construct_at(std::addressof(rval), std::move(_fun)); - // new (&rval) FncT(std::move(_fun)); } else { #if defined(SOLID_THROW_ON_BIG_FUNCTION) solid_throw("Big Function"); #endif FncT* const ptr = ::new FncT(std::move(_fun)); storage_.big_.ptr_ = ptr; - storage_.big_.rtti(reinterpret_cast(&fnc_impl::big_rtti)); + storage_.rtti_ = fnc_impl::representation(&fnc_impl::big_rtti, fnc_impl::RepresentationE::Big); } } ~Function() noexcept { - switch (representation()) { + auto const rtti = storage_.rtti_; + switch (fnc_impl::representation(rtti)) { [[likely]] case fnc_impl::RepresentationE::Small: - if (auto const* prtti = storage_.small_.rtti(); prtti->pdestroy_fnc_) { - prtti->pdestroy_fnc_(&storage_.small_.data_); + if (auto* pf = Small::RTTI_T::get(rtti).pdestroy_fnc_) { + (*pf)(&storage_.small_.data_); } break; case fnc_impl::RepresentationE::Big: - storage_.big_.rtti()->destroy_fnc_(storage_.big_.ptr_); + Big::RTTI_T::get(rtti).destroy_fnc_(storage_.big_.ptr_); break; case fnc_impl::RepresentationE::None: [[fallthrough]]; @@ -466,40 +393,34 @@ class Function { void reset() noexcept { - switch (representation()) { + auto const rtti = storage_.rtti_; + switch (fnc_impl::representation(rtti)) { [[likely]] case fnc_impl::RepresentationE::Small: - if (auto const* prtti = storage_.small_.rtti(); prtti->pdestroy_fnc_) { - prtti->pdestroy_fnc_(&storage_.small_.data_); + if (auto* pfnc = Small::RTTI_T::get(rtti).pdestroy_fnc_) { + (*pfnc)(&storage_.small_.data_); } break; case fnc_impl::RepresentationE::Big: - storage_.big_.rtti()->destroy_fnc_(storage_.big_.ptr_); + Big::RTTI_T::get(rtti).destroy_fnc_(storage_.big_.ptr_); break; case fnc_impl::RepresentationE::None: [[fallthrough]]; default: break; } - storage_.small_.prtti_ = 0; + storage_.rtti_ = 0; } R operator()(ArgTypes... _args) const { - auto const rtti = storage_.small_.prtti_; - if (auto const rtti = storage_.small_.prtti_; (rtti & fnc_impl::representation_mask) == 1) [[likely]] { - return reinterpret_cast(rtti & fnc_impl::reversed_representation_and_flags_mask)->invoke_fnc_(&storage_.small_.data_, static_cast(_args)...); - } else { - throw std::bad_function_call(); - } -#if 0 - if (auto const repr = representation(); true /* repr == fnc_impl::RepresentationE::Small */) [[likely]] { - return storage_.small_.rtti()->invoke_fnc_(&storage_.small_.data_, static_cast(_args)... /* std::forward(_args)... */); + auto const rtti = storage_.rtti_; + if (auto const repr = fnc_impl::representation(rtti); repr == fnc_impl::RepresentationE::Small) [[likely]] { + return Small::RTTI_T::get(rtti).invoke_fnc_(&storage_.small_.data_, static_cast(_args)...); } else if (repr == fnc_impl::RepresentationE::Big) { - return storage_.big_.rtti()->invoke_fnc_(storage_.big_.ptr_, static_cast(_args)... /* std::forward(_args)... */); + return Big::RTTI_T::get(rtti).invoke_fnc_(&storage_.big_.ptr_, static_cast(_args)...); } else { throw std::bad_function_call(); } -#endif } template @@ -510,7 +431,7 @@ class Function { bool has_value() const noexcept { - return storage_.small_.prtti_ != 0; + return storage_.rtti_ != 0; } bool empty() const noexcept { @@ -524,52 +445,47 @@ class Function { bool is_movable() const { - if (is_small()) { - return storage_.small_.rtti()->is_movable_; - } else if (is_big()) { - return storage_.big_.rtti()->is_copyable_; + auto const rtti = storage_.rtti_; + if (rtti) [[likely]] { + return BaseRTTI_T::get(rtti).is_movable_; } return true; } bool is_copyable() const { - if (is_small()) { - return storage_.small_.rtti()->is_copyable_; - } else if (is_big()) { - return storage_.big_.rtti()->is_copyable_; + auto const rtti = storage_.rtti_; + if (rtti) [[likely]] { + return BaseRTTI_T::get(rtti).is_copyable_; } return true; } [[nodiscard]] bool is_small() const { - return representation() == fnc_impl::RepresentationE::Small; + return fnc_impl::representation(storage_.rtti_) == fnc_impl::RepresentationE::Small; } [[nodiscard]] bool is_big() const { - return representation() == fnc_impl::RepresentationE::Big; + return fnc_impl::representation(storage_.rtti_) == fnc_impl::RepresentationE::Big; } private: template void doMoveFrom(Function& _other) { - representation(fnc_impl::RepresentationE::None); - switch (_other.representation()) { + storage_.rtti_ = 0u; + switch (fnc_impl::representation(_other.storage_.rtti_)) { case fnc_impl::RepresentationE::Small: { - const auto repr = _other.storage_.small_.rtti()->move_fnc_( - _other.storage_.small_.data_, - storage_.small_.data_, small_capacity, storage_.small_.prtti_, - storage_.big_.ptr_, storage_.big_.prtti_); - representation(repr); + storage_.rtti_ = Small::RTTI_T::get(_other.storage_.rtti_).move_fnc_(_other.storage_.small_.data_, storage_.small_.data_, smallCapacity(), smallAlign(), storage_.big_.ptr_); + _other.reset(); } break; case fnc_impl::RepresentationE::Big: { - const auto repr = _other.storage_.big_.rtti()->move_fnc_( - _other.storage_.big_.ptr_, - storage_.small_.data_, small_capacity, storage_.small_.prtti_, - storage_.big_.ptr_, storage_.big_.prtti_); - representation(repr); + storage_.rtti_ = Big::RTTI_T::get(_other.storage_.rtti_).move_fnc_(_other.storage_.big_.ptr_, storage_.small_.data_, smallCapacity(), smallAlign(), storage_.big_.ptr_); + if (is_big()) { + _other.storage_.rtti_ = 0u; + } + _other.reset(); } break; default: break; @@ -579,21 +495,13 @@ class Function { template void doCopyFrom(const Function& _other) { - representation(fnc_impl::RepresentationE::None); - switch (_other.representation()) { + storage_.rtti_ = 0u; + switch (fnc_impl::representation(_other.storage_.rtti_)) { case fnc_impl::RepresentationE::Small: { - const auto repr = _other.storage_.small_.rtti()->copy_fnc_( - _other.storage_.small_.data_, - storage_.small_.data_, small_capacity, storage_.small_.prtti_, - storage_.big_.ptr_, storage_.big_.prtti_); - representation(repr); + storage_.rtti_ = Small::RTTI_T::get(_other.storage_.rtti_).copy_fnc_(_other.storage_.small_.data_, storage_.small_.data_, smallCapacity(), smallAlign(), storage_.big_.ptr_); } break; case fnc_impl::RepresentationE::Big: { - const auto repr = _other.storage_.big_.rtti()->copy_fnc_( - _other.storage_.big_.ptr_, - storage_.small_.data_, small_capacity, storage_.small_.prtti_, - storage_.big_.ptr_, storage_.big_.prtti_); - representation(repr); + storage_.rtti_ = Big::RTTI_T::get(_other.storage_.rtti_).copy_fnc_(_other.storage_.big_.ptr_, storage_.small_.data_, smallCapacity(), smallAlign(), storage_.big_.ptr_); } break; default: break; @@ -605,17 +513,17 @@ class Function { { using FncT = std::remove_cvref_t; if constexpr (is_small_type()) { - storage_.small_.rtti(reinterpret_cast(&fnc_impl::small_rtti)); - auto& rval = reinterpret_cast(storage_.small_.data_); - // std::construct_at(std::addressof(rval), std::move(_fun)); - new (&rval) FncT(std::move(_fun)); + storage_.rtti_ = representation(&fnc_impl::small_rtti, fnc_impl::RepresentationE::Small); + auto& rval = reinterpret_cast(storage_.small_.data_); + std::construct_at(std::addressof(rval), std::move(_fun)); + // new (&rval) FncT(std::move(_fun)); } else { #if defined(SOLID_THROW_ON_BIG_FUNCTION) solid_throw("Big Function"); #endif FncT* const ptr = ::new FncT(std::move(_fun)); storage_.big_.ptr_ = ptr; - storage_.big_.rtti(reinterpret_cast(&fnc_impl::big_rtti)); + storage_.rtti_ = representation(&fnc_impl::big_rtti, fnc_impl::RepresentationE::Big); } } }; From c883094b3d5191c5314db20572ae92c4b1793cd5 Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Sat, 1 Nov 2025 10:45:34 +0200 Subject: [PATCH 15/56] utility: added anyimpl.hpp --- solid/utility/CMakeLists.txt | 1 + solid/utility/anyimpl.hpp | 41 ++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 solid/utility/anyimpl.hpp diff --git a/solid/utility/CMakeLists.txt b/solid/utility/CMakeLists.txt index 50aa7b0a5..b09dc9209 100644 --- a/solid/utility/CMakeLists.txt +++ b/solid/utility/CMakeLists.txt @@ -11,6 +11,7 @@ set(Sources set(Headers algorithm.hpp any.hpp + anyimpl.hpp common.hpp event.hpp innerlist.hpp diff --git a/solid/utility/anyimpl.hpp b/solid/utility/anyimpl.hpp new file mode 100644 index 000000000..cbb693a2c --- /dev/null +++ b/solid/utility/anyimpl.hpp @@ -0,0 +1,41 @@ +// solid/utility/anyimpl.hpp +// +// Copyright (c) 2025 Valentin Palade (vipalade @ gmail . com) +// +// This file is part of SolidFrame framework. +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt. +// + +#pragma once + +#include "solid/utility/common.hpp" + +namespace solid::any_impl { + +enum struct RepresentationE : uintptr_t { + None = 0, + Small, + Big, +}; +constexpr uintptr_t representation_mask = 3; +constexpr uintptr_t representation_and_flags_mask = representation_mask; +constexpr uintptr_t reversed_representation_and_flags_mask = ~representation_mask; + +inline RepresentationE representation(uintptr_t const _rtti) noexcept +{ + return static_cast(_rtti & representation_mask); +} + +inline uintptr_t representation(uintptr_t const _rtti, RepresentationE const _repr) noexcept +{ + return (_rtti & (~representation_and_flags_mask)) | to_underlying(_repr); +} + +inline uintptr_t representation(void const* _rtti, RepresentationE const _repr) noexcept +{ + return (reinterpret_cast(_rtti) & (~representation_and_flags_mask)) | to_underlying(_repr); +} + +} // namespace solid::any_impl \ No newline at end of file From 672b3bb2fc32ca0c47aad6dadaebacaa178fb790 Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Sat, 1 Nov 2025 17:45:40 +0200 Subject: [PATCH 16/56] utility: no more const_cast on any, event and function + cleanup --- solid/utility/any.hpp | 8 +-- solid/utility/event.hpp | 106 ------------------------------------- solid/utility/function.hpp | 6 +-- 3 files changed, 7 insertions(+), 113 deletions(-) diff --git a/solid/utility/any.hpp b/solid/utility/any.hpp index f8994ac6b..460e7936b 100644 --- a/solid/utility/any.hpp +++ b/solid/utility/any.hpp @@ -155,7 +155,7 @@ uintptr_t do_copy( if (sizeof(T) <= _small_cap and alignof(T) <= _small_align) { T& rdst = *static_cast(_pto_small); const T& rsrc = *static_cast(_pfrom); - ::new (const_cast(static_cast(std::addressof(rdst)))) T(rsrc); + ::new (std::addressof(rdst)) T(rsrc); return representation(&small_rtti, RepresentationE::Small); } else { _rpto_big = ::new T(*static_cast(_pfrom)); @@ -177,7 +177,7 @@ uintptr_t do_move( if (sizeof(T) <= _small_cap and alignof(T) <= _small_align) { T& rdst = *static_cast(_pto_small); T& rsrc = *static_cast(_pfrom); - ::new (const_cast(static_cast(std::addressof(rdst)))) T{std::move(rsrc)}; + ::new (std::addressof(rdst)) T{std::move(rsrc)}; return representation(&small_rtti, RepresentationE::Small); } else { _rpto_big = ::new T{std::move(*static_cast(_pfrom))}; @@ -199,7 +199,7 @@ uintptr_t do_move_big( if (sizeof(T) <= _small_cap and alignof(T) <= _small_align) { T& rdst = *static_cast(_pto_small); T& rsrc = *static_cast(_pfrom); - ::new (const_cast(static_cast(std::addressof(rdst)))) T{std::move(rsrc)}; + ::new (std::addressof(rdst)) T{std::move(rsrc)}; return representation(&small_rtti, RepresentationE::Small); } else { _rpto_big = static_cast(_pfrom); @@ -588,7 +588,7 @@ class Any { { if constexpr (is_small_type()) { auto& rval = reinterpret_cast(small_.data_); - ::new (const_cast(static_cast(std::addressof(rval)))) T{std::forward(_args)...}; + ::new (std::addressof(rval)) T{std::forward(_args)...}; rtti_ = representation(&any_impl::small_rtti, any_impl::RepresentationE::Small); return rval; } else { diff --git a/solid/utility/event.hpp b/solid/utility/event.hpp index 5e6b4c19b..fe6e8566c 100644 --- a/solid/utility/event.hpp +++ b/solid/utility/event.hpp @@ -122,17 +122,6 @@ class EventBase { bool is_movable() const { -#if 0 - auto const lrtti = rtti_; - switch (any_impl::representation(lrtti)) { - case any_impl::RepresentationE::Small: - return any_impl::SmallRTTI::get(lrtti).is_movable_; - case any_impl::RepresentationE::Big: - return any_impl::BigRTTI::get(lrtti).is_movable_; - default: - return true; - } -#endif auto const rtti = rtti_; if (rtti) [[likely]] { return any_impl::BaseRTTI::get(rtti).is_movable_; @@ -141,17 +130,6 @@ class EventBase { } bool is_copyable() const { -#if 0 - auto const lrtti = rtti_; - switch (any_impl::representation(lrtti)) { - case any_impl::RepresentationE::Small: - return any_impl::SmallRTTI::get(lrtti).is_copyable_; - case any_impl::RepresentationE::Big: - return any_impl::BigRTTI::get(lrtti).is_copyable_; - default: - return true; - } -#endif auto const rtti = rtti_; if (rtti) [[likely]] { return any_impl::BaseRTTI::get(rtti).is_copyable_; @@ -161,17 +139,6 @@ class EventBase { bool is_tuple() const { -#if 0 - auto const lrtti = rtti_; - switch (any_impl::representation(lrtti)) { - case any_impl::RepresentationE::Small: - return any_impl::SmallRTTI::get(lrtti).is_tuple_; - case any_impl::RepresentationE::Big: - return any_impl::BigRTTI::get(lrtti).is_tuple_; - default: - return false; - } -#endif auto const rtti = rtti_; if (rtti) [[likely]] { return any_impl::BaseRTTI::get(rtti).is_tuple_; @@ -253,33 +220,6 @@ class EventBase { } _other.reset(); } -#if 0 - representation(any_impl::RepresentationE::None); - switch (_other.representation()) { - case any_impl::RepresentationE::Small: { - const auto repr = _other.rtti_.psmall_->pmove_fnc_( - _other.pdata_, - _psmall_data, _small_capacity, rtti_.psmall_, - pdata_, rtti_.pbig_); - representation(repr); - _other.reset(); - } break; - case any_impl::RepresentationE::Big: { - const auto repr = _other.rtti_.pbig_->pmove_fnc_( - _other.pdata_, - _psmall_data, _small_capacity, rtti_.psmall_, - pdata_, rtti_.pbig_); - representation(repr); - if (repr == any_impl::RepresentationE::Big) { - _other.type_data_ = 0; - } else { - _other.reset(); - } - } break; - default: - break; - } -#endif } void doCopyFrom(void* _psmall_data, const size_t _small_capacity, const size_t _small_align, const EventBase& _other) @@ -294,29 +234,6 @@ class EventBase { _psmall_data, _small_capacity, _small_align, pdata_); } -#if 0 - type_data_ = _other.type_data_; - pdata_ = _psmall_data; - representation(any_impl::RepresentationE::None); - switch (_other.representation()) { - case any_impl::RepresentationE::Small: { - const auto repr = _other.rtti_.psmall_->pcopy_fnc_( - _other.pdata_, - _psmall_data, _small_capacity, rtti_.psmall_, - pdata_, rtti_.pbig_); - representation(repr); - } break; - case any_impl::RepresentationE::Big: { - const auto repr = _other.rtti_.pbig_->pcopy_fnc_( - _other.pdata_, - _psmall_data, _small_capacity, rtti_.psmall_, - pdata_, rtti_.pbig_); - representation(repr); - } break; - default: - break; - } -#endif } template @@ -325,11 +242,6 @@ class EventBase { auto* pdata = ::new (_psmall_data) T{std::forward(_args)...}; pdata_ = _psmall_data; rtti_ = any_impl::representation(&any_impl::small_rtti, any_impl::RepresentationE::Small); - - // rtti_.psmall_ = &any_impl::small_rtti; - // type_data_ = reinterpret_cast(&typeid(T)); - // representation(any_impl::RepresentationE::Small); - return *pdata; } @@ -342,9 +254,6 @@ class EventBase { T* const ptr = ::new T(std::forward(_args)...); pdata_ = ptr; rtti_ = representation(&any_impl::big_rtti, any_impl::RepresentationE::Big); - // rtti_.pbig_ = &any_impl::big_rtti; - // type_data_ = reinterpret_cast(&typeid(T)); - // representation(any_impl::RepresentationE::Big); return *ptr; } }; @@ -516,21 +425,6 @@ class Event<0, 0> : public EventBase { } }; -#if 0 // TODO:remove -namespace event_impl { -constexpr size_t compute_small_capacity(const size_t _req_capacity) -{ - static constexpr size_t default_total_size = 32u; - - const size_t end_capacity = sizeof(uintptr_t) + sizeof(void*); - const size_t req_capacity = std::max(_req_capacity, std::max(end_capacity, sizeof(max_align_t)) - end_capacity); - const size_t tot_capacity = std::max(default_total_size, padded_size(req_capacity + sizeof(uintptr_t) + sizeof(void*), alignof(max_align_t))); - - return tot_capacity - end_capacity; -} -} // namespace event_impl -#endif - template requires(SmallSize == 0 and SmallAlign == 0 or (SmallSize > 0 and SmallSize >= SmallAlign and (SmallSize % SmallAlign == 0) and std::popcount(SmallAlign) == 1)) class Event : public EventBase { diff --git a/solid/utility/function.hpp b/solid/utility/function.hpp index 6f82f984c..b7a41b636 100644 --- a/solid/utility/function.hpp +++ b/solid/utility/function.hpp @@ -158,7 +158,7 @@ uintptr_t do_copy( if (sizeof(T) <= _small_cap and alignof(T) <= _small_align) { T& rdst = *static_cast(_pto_small); const T& rsrc = *static_cast(_pfrom); - ::new (const_cast(static_cast(std::addressof(rdst)))) T(rsrc); + ::new (std::addressof(rdst)) T(rsrc); return representation(&small_rtti, RepresentationE::Small); } else { #if defined(SOLID_THROW_ON_BIG_FUNCTION) @@ -183,7 +183,7 @@ uintptr_t do_move( if (sizeof(T) <= _small_cap and alignof(T) <= _small_align) { T& rdst = *static_cast(_pto_small); T& rsrc = *static_cast(_pfrom); - ::new (const_cast(static_cast(std::addressof(rdst)))) T{std::move(rsrc)}; + ::new (std::addressof(rdst)) T{std::move(rsrc)}; return representation(&small_rtti, RepresentationE::Small); } else { #if defined(SOLID_THROW_ON_BIG_FUNCTION) @@ -208,7 +208,7 @@ uintptr_t do_move_big( if (sizeof(T) <= _small_cap and alignof(T) <= _small_align) { T& rdst = *static_cast(_pto_small); T& rsrc = *static_cast(_pfrom); - ::new (const_cast(static_cast(std::addressof(rdst)))) T{std::move(rsrc)}; + ::new (std::addressof(rdst)) T{std::move(rsrc)}; return representation(&small_rtti, RepresentationE::Small); } else { _rpto_big = static_cast(_pfrom); From 19dc180df8fa9854798b8b5be300654ccdb4a257 Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Sat, 1 Nov 2025 18:21:34 +0200 Subject: [PATCH 17/56] fix some of the warnings on clang on macos --- solid/frame/mprpc/mprpcconfiguration.hpp | 2 +- solid/frame/mprpc/mprpccontext.hpp | 2 +- solid/frame/mprpc/mprpcid.hpp | 4 ++-- solid/frame/mprpc/mprpcservice.hpp | 2 +- solid/frame/mprpc/mprpcsocketstub.hpp | 2 +- solid/frame/mprpc/mprpcsocketstub_openssl.hpp | 4 ++-- solid/frame/mprpc/src/mprpcconnection.cpp | 2 +- solid/frame/mprpc/src/mprpcconnection.hpp | 2 +- solid/reflection/v1/typemap.hpp | 6 +++--- solid/serialization/v3/binarydeserializer.hpp | 6 ++---- solid/serialization/v3/binaryserializer.hpp | 2 +- solid/system/pimpl.hpp | 1 + solid/utility/event.hpp | 4 ++-- solid/utility/sharedbuffer.hpp | 2 +- 14 files changed, 20 insertions(+), 21 deletions(-) diff --git a/solid/frame/mprpc/mprpcconfiguration.hpp b/solid/frame/mprpc/mprpcconfiguration.hpp index f56ada061..71d1eee6d 100644 --- a/solid/frame/mprpc/mprpcconfiguration.hpp +++ b/solid/frame/mprpc/mprpcconfiguration.hpp @@ -45,7 +45,7 @@ constexpr size_t socket_emplace_align = 16; class Service; class Connection; class MessageWriter; -struct ConnectionContext; +class ConnectionContext; class Configuration; typedef void (*OnSecureConnectF)(frame::aio::ReactorContext&); diff --git a/solid/frame/mprpc/mprpccontext.hpp b/solid/frame/mprpc/mprpccontext.hpp index d2e54aef5..f0e07d480 100644 --- a/solid/frame/mprpc/mprpccontext.hpp +++ b/solid/frame/mprpc/mprpccontext.hpp @@ -55,7 +55,7 @@ struct ConnectionProxy { ConnectionProxy() {} private: - friend struct ConnectionContext; + friend class ConnectionContext; Service& service(frame::aio::ReactorContext& _rctx) const; Connection& connection(frame::aio::ReactorContext& _rctx) const; }; diff --git a/solid/frame/mprpc/mprpcid.hpp b/solid/frame/mprpc/mprpcid.hpp index 8f3ec727c..b6025c48a 100644 --- a/solid/frame/mprpc/mprpcid.hpp +++ b/solid/frame/mprpc/mprpcid.hpp @@ -10,7 +10,7 @@ class EngineCore; } class Service; -struct ConnectionContext; +class ConnectionContext; //! A structure to uniquely indetify an IPC connection pool /*! @@ -31,7 +31,7 @@ struct ConnectionPoolId : UniqueId { class RecipientId { friend class Service; friend class Connection; - friend struct ConnectionContext; + friend class ConnectionContext; ConnectionPoolId pool_id_; ActorIdT connection_id_; diff --git a/solid/frame/mprpc/mprpcservice.hpp b/solid/frame/mprpc/mprpcservice.hpp index 0dac96ac9..f1f997da2 100644 --- a/solid/frame/mprpc/mprpcservice.hpp +++ b/solid/frame/mprpc/mprpcservice.hpp @@ -568,7 +568,7 @@ class Service : public frame::Service { friend class Connection; friend class ClientConnection; friend class openssl::SocketStub; - friend struct ConnectionContext; + friend class ConnectionContext; Configuration const& configuration() const; ServiceStatistic& wstatistic(); diff --git a/solid/frame/mprpc/mprpcsocketstub.hpp b/solid/frame/mprpc/mprpcsocketstub.hpp index 244a7d8c4..367cf5d2a 100644 --- a/solid/frame/mprpc/mprpcsocketstub.hpp +++ b/solid/frame/mprpc/mprpcsocketstub.hpp @@ -19,7 +19,7 @@ namespace solid { namespace frame { namespace mprpc { -struct ConnectionContext; +class ConnectionContext; class SocketStub { public: diff --git a/solid/frame/mprpc/mprpcsocketstub_openssl.hpp b/solid/frame/mprpc/mprpcsocketstub_openssl.hpp index 51f7d9acd..2114b8cc0 100644 --- a/solid/frame/mprpc/mprpcsocketstub_openssl.hpp +++ b/solid/frame/mprpc/mprpcsocketstub_openssl.hpp @@ -239,7 +239,7 @@ inline SocketStubPtrT create_client_socket(mprpc::Configuration const& _rcfg, fr { #ifdef SOLID_HAS_ASSERT static_assert(sizeof(SocketStub) <= socket_emplace_size); - static_assert(alignof(SocketStub) == socket_emplace_align); + static_assert(alignof(SocketStub) <= socket_emplace_align); #endif if constexpr (sizeof(SocketStub) > socket_emplace_size and alignof(SocketStub) > socket_emplace_align) { return SocketStubPtrT(new SocketStub(_rproxy, const_cast(_rcfg.client.secure_any.cast())->context), SocketStub::delete_deleter); @@ -252,7 +252,7 @@ inline SocketStubPtrT create_server_socket(mprpc::Configuration const& _rcfg, fr { #ifdef SOLID_HAS_ASSERT static_assert(sizeof(SocketStub) <= socket_emplace_size); - static_assert(alignof(SocketStub) == socket_emplace_align); + static_assert(alignof(SocketStub) <= socket_emplace_align); #endif if constexpr (sizeof(SocketStub) > socket_emplace_size and alignof(SocketStub) > socket_emplace_align) { diff --git a/solid/frame/mprpc/src/mprpcconnection.cpp b/solid/frame/mprpc/src/mprpcconnection.cpp index 4eb43bbcb..f02a42044 100644 --- a/solid/frame/mprpc/src/mprpcconnection.cpp +++ b/solid/frame/mprpc/src/mprpcconnection.cpp @@ -2156,7 +2156,7 @@ struct RelayContext { void RelayConnection::tryPollRelayEngine(frame::aio::ReactorContext& _rctx, const Configuration& _rconfig, MessageWriter& _rmsgwriter) { if (shouldPollRelayEngine()) { - auto relay_poll_push_lambda = [this, &_rconfig, &_rmsgwriter]( + auto relay_poll_push_lambda = [&_rconfig, &_rmsgwriter]( RelayData*& _rprelay_data, const MessageId& _rengine_msg_id, MessageId& _rconn_msg_id, bool& _rmore) -> bool { diff --git a/solid/frame/mprpc/src/mprpcconnection.hpp b/solid/frame/mprpc/src/mprpcconnection.hpp index e2552e95d..f8d0a5873 100644 --- a/solid/frame/mprpc/src/mprpcconnection.hpp +++ b/solid/frame/mprpc/src/mprpcconnection.hpp @@ -273,7 +273,7 @@ class Connection : public frame::aio::Actor { ErrorConditionT pollServicePoolForUpdates(frame::aio::ReactorContext& _rctx, MessageId const& _rpool_msg_id); private: - friend struct ConnectionContext; + friend class ConnectionContext; friend class RelayEngine; friend class Service; diff --git a/solid/reflection/v1/typemap.hpp b/solid/reflection/v1/typemap.hpp index ea93df88f..274252087 100644 --- a/solid/reflection/v1/typemap.hpp +++ b/solid/reflection/v1/typemap.hpp @@ -494,20 +494,20 @@ class TypeMap : public TypeMapBase { rref.add(rval, rctx, 0, ""); } }; - type_vec_[_type_index].reflector_vec_[_index].create_shared_fnc_ = [_create_f](void* _pctx, void* _pptr, const CastFunctionT& _cast) { + type_vec_[_type_index].reflector_vec_[_index].create_shared_fnc_ = [=](void* _pctx, void* _pptr, const CastFunctionT& _cast) { typename Ref::ContextT& rctx = *reinterpret_cast(_pctx); std::shared_ptr ptr; _create_f(rctx, ptr); _cast(_pptr, &ptr); }; - type_vec_[_type_index].reflector_vec_[_index].create_unique_fnc_ = [_create_f](void* _pctx, void* _pptr, const CastFunctionT& _cast) { + type_vec_[_type_index].reflector_vec_[_index].create_unique_fnc_ = [=](void* _pctx, void* _pptr, const CastFunctionT& _cast) { typename Ref::ContextT& rctx = *reinterpret_cast(_pctx); std::unique_ptr ptr; _create_f(rctx, ptr); _cast(_pptr, &ptr); }; - type_vec_[_type_index].reflector_vec_[_index].create_intrusive_fnc_ = [_create_f](void* _pctx, void* _pptr, const CastFunctionT& _cast) { + type_vec_[_type_index].reflector_vec_[_index].create_intrusive_fnc_ = [=](void* _pctx, void* _pptr, const CastFunctionT& _cast) { if constexpr (std::is_base_of_v) { typename Ref::ContextT& rctx = *reinterpret_cast(_pctx); solid::IntrusivePtr ptr; diff --git a/solid/serialization/v3/binarydeserializer.hpp b/solid/serialization/v3/binarydeserializer.hpp index 7edd9b8d3..91d3a7fb3 100644 --- a/solid/serialization/v3/binarydeserializer.hpp +++ b/solid/serialization/v3/binarydeserializer.hpp @@ -1088,11 +1088,9 @@ class Deserializer : public DeserializerBase { } } - template >*/> -#if 1 + template requires( - !std::is_base_of_v && !std::is_floating_point_v || (std::is_pointer_v && (is_shared_ptr_v || is_unique_ptr_v || is_intrusive_ptr_v))) -#endif + (!std::is_base_of_v && !std::is_floating_point_v) || (std::is_pointer_v && (is_shared_ptr_v || is_unique_ptr_v || is_intrusive_ptr_v))) void addDispatch(const Meta& _meta, T& _rt, ContextT& _rctx, const size_t _id, const char* const _name) { if constexpr (std::is_base_of_v) { diff --git a/solid/serialization/v3/binaryserializer.hpp b/solid/serialization/v3/binaryserializer.hpp index 0148a362b..d9dbbfacf 100644 --- a/solid/serialization/v3/binaryserializer.hpp +++ b/solid/serialization/v3/binaryserializer.hpp @@ -913,7 +913,7 @@ class Serializer : public SerializerBase { template requires( - !std::is_base_of_v && !std::is_floating_point_v || (std::is_pointer_v && (is_shared_ptr_v || is_unique_ptr_v || is_intrusive_ptr_v))) + (!std::is_base_of_v && !std::is_floating_point_v) || (std::is_pointer_v && (is_shared_ptr_v || is_unique_ptr_v || is_intrusive_ptr_v))) void addDispatch(const Meta& _meta, const T& _rt, ContextT& _rctx, const size_t _id, const char* const _name) { diff --git a/solid/system/pimpl.hpp b/solid/system/pimpl.hpp index 7a8489f68..bdd7b5b6e 100644 --- a/solid/system/pimpl.hpp +++ b/solid/system/pimpl.hpp @@ -11,6 +11,7 @@ #pragma once #include +#include #include namespace solid { diff --git a/solid/utility/event.hpp b/solid/utility/event.hpp index fe6e8566c..2a456e925 100644 --- a/solid/utility/event.hpp +++ b/solid/utility/event.hpp @@ -368,7 +368,7 @@ inline EventCategory category{ // Event<> //----------------------------------------------------------------------------- template - requires(SmallSize == 0 and SmallAlign == 0 or (SmallSize > 0 and SmallSize >= SmallAlign and (SmallSize % SmallAlign == 0) and std::popcount(SmallAlign) == 1)) + requires((SmallSize == 0 and SmallAlign == 0) or (SmallSize > 0 and SmallSize >= SmallAlign and (SmallSize % SmallAlign == 0) and std::popcount(SmallAlign) == 1)) class Event; template @@ -426,7 +426,7 @@ class Event<0, 0> : public EventBase { }; template - requires(SmallSize == 0 and SmallAlign == 0 or (SmallSize > 0 and SmallSize >= SmallAlign and (SmallSize % SmallAlign == 0) and std::popcount(SmallAlign) == 1)) + requires((SmallSize == 0 and SmallAlign == 0) or (SmallSize > 0 and SmallSize >= SmallAlign and (SmallSize % SmallAlign == 0) and std::popcount(SmallAlign) == 1)) class Event : public EventBase { alignas(SmallAlign) unsigned char data_[SmallSize]; diff --git a/solid/utility/sharedbuffer.hpp b/solid/utility/sharedbuffer.hpp index 08830a898..9ec8a2740 100644 --- a/solid/utility/sharedbuffer.hpp +++ b/solid/utility/sharedbuffer.hpp @@ -687,7 +687,7 @@ class BufferManager : NonCopyable { #if 1 class BufferPool : NonCopyable { - friend class impl::SharedBufferData; + friend struct impl::SharedBufferData; friend class impl::SharedBufferBase; struct LocalData; struct OwnData; From ea4e6c6fb8f42676a82209a5fe3b69267694b77a Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Sun, 2 Nov 2025 15:14:25 +0200 Subject: [PATCH 18/56] fix warnings clang and g++ --- .../aio_echo/example_secure_echo_server.cpp | 2 +- .../frame/mprpc_echo/example_mprpc_echo.cpp | 4 +- .../example_relay_server_bi_cp.cpp | 2 +- .../utility/algorithm/example_bit_count.cpp | 2 +- .../memory_file/example_memory_file.cpp | 10 +-- .../threadpool/example_file_open_pool.cpp | 8 +- solid/frame/aio/src/aioreactor.cpp | 1 - solid/frame/aio/test/test_echo_tcp_stress.cpp | 2 +- .../alpha/client/alphaclient.cpp | 2 +- .../beta/client/betaclient.cpp | 2 +- .../gamma/client/gammaclient.cpp | 2 +- .../mprpc/test/test_clientserver_basic.cpp | 14 ++-- .../test/test_clientserver_cancel_client.cpp | 8 +- .../test/test_clientserver_cancel_server.cpp | 6 +- .../test/test_clientserver_pause_read.cpp | 8 +- .../test/test_clientserver_sendrequest.cpp | 14 ++-- .../mprpc/test/test_clientserver_split.cpp | 14 ++-- .../mprpc/test/test_clientserver_stop.cpp | 14 ++-- .../mprpc/test/test_clientserver_topic.cpp | 10 +-- .../test/test_clientserver_versioning.cpp | 2 +- .../mprpc/test/test_connection_close.cpp | 4 +- .../frame/mprpc/test/test_keepalive_fail.cpp | 14 ++-- .../mprpc/test/test_keepalive_success.cpp | 2 +- solid/frame/mprpc/test/test_pool_basic.cpp | 14 ++-- .../mprpc/test/test_pool_delay_close.cpp | 2 +- .../mprpc/test/test_pool_force_close.cpp | 6 +- .../frame/mprpc/test/test_protocol_basic.cpp | 6 +- .../mprpc/test/test_protocol_synchronous.cpp | 8 +- solid/frame/mprpc/test/test_raw_basic.cpp | 10 +-- solid/frame/mprpc/test/test_raw_proxy.cpp | 10 +-- solid/frame/mprpc/test/test_relay_basic.cpp | 12 +-- .../mprpc/test/test_relay_cancel_request.cpp | 2 +- .../mprpc/test/test_relay_cancel_response.cpp | 2 +- .../mprpc/test/test_relay_close_request.cpp | 2 +- .../mprpc/test/test_relay_close_response.cpp | 2 +- .../mprpc/test/test_relay_detect_close.cpp | 2 - ...test_relay_detect_close_while_response.cpp | 2 - .../frame/mprpc/test/test_relay_disabled.cpp | 10 +-- solid/frame/mprpc/test/test_relay_split.cpp | 12 +-- solid/frame/src/reactor.cpp | 1 - solid/serialization/v3/binarydeserializer.hpp | 6 +- solid/serialization/v3/binaryserializer.hpp | 4 +- .../v3/src/binarydeserializer.cpp | 2 +- .../serialization/v3/src/binaryserializer.cpp | 2 +- solid/serialization/v3/test/test_binary.cpp | 6 +- .../serialization/v3/test/test_container.cpp | 2 +- solid/system/pimpl.hpp | 2 +- solid/utility/event.hpp | 76 ++++++++++--------- solid/utility/memoryfile.hpp | 2 +- solid/utility/src/memoryfile.cpp | 2 +- solid/utility/src/sharedbuffer.cpp | 2 +- .../test/test_callpool_multicast_basic.cpp | 2 +- solid/utility/test/test_intrusiveptr.cpp | 6 +- solid/utility/test/test_threadpool_batch.cpp | 2 +- .../test/test_threadpool_multicast_basic.cpp | 2 +- .../test/test_threadpool_multicast_sleep.cpp | 2 +- .../test/test_threadpool_thread_context.cpp | 1 - tutorials/aio_echo/aio_echo_server.cpp | 2 +- .../mprpc_echo_relay_client.cpp | 4 +- 59 files changed, 196 insertions(+), 181 deletions(-) diff --git a/examples/frame/aio_echo/example_secure_echo_server.cpp b/examples/frame/aio_echo/example_secure_echo_server.cpp index b2412dc4d..cd0a5409d 100644 --- a/examples/frame/aio_echo/example_secure_echo_server.cpp +++ b/examples/frame/aio_echo/example_secure_echo_server.cpp @@ -277,7 +277,7 @@ bool parseArguments(Params& _par, int argc, char* argv[]) void Listener::onAccept(frame::aio::ReactorContext& _rctx, SocketDevice& _rsd) { solid_log(generic_logger, Info, ""); - unsigned repeatcnt = backlog_size(); + size_t repeatcnt = backlog_size(); do { if (!_rctx.error()) { diff --git a/examples/frame/mprpc_echo/example_mprpc_echo.cpp b/examples/frame/mprpc_echo/example_mprpc_echo.cpp index 4512fc757..cc1994abe 100644 --- a/examples/frame/mprpc_echo/example_mprpc_echo.cpp +++ b/examples/frame/mprpc_echo/example_mprpc_echo.cpp @@ -86,9 +86,7 @@ typedef std::vector MessageVectorT; struct FirstMessage; namespace { -mutex mtx; -condition_variable cnd; -Params params; +Params params; void broadcast_message(frame::mprpc::Service& _rsvc, frame::mprpc::MessagePointerT<>& _rmsgptr); } // namespace diff --git a/examples/frame/relay_server/example_relay_server_bi_cp.cpp b/examples/frame/relay_server/example_relay_server_bi_cp.cpp index 2e7f9d375..c417ab4f6 100644 --- a/examples/frame/relay_server/example_relay_server_bi_cp.cpp +++ b/examples/frame/relay_server/example_relay_server_bi_cp.cpp @@ -279,7 +279,7 @@ bool parseArguments(Params& _par, int argc, char* argv[]) void Listener::onAccept(frame::aio::ReactorContext& _rctx, SocketDevice& _rsd) { solid_log(generic_logger, Info, ""); - unsigned repeatcnt = SocketInfo::max_listen_backlog_size(); + size_t repeatcnt = SocketInfo::max_listen_backlog_size(); do { if (!_rctx.error()) { diff --git a/examples/utility/algorithm/example_bit_count.cpp b/examples/utility/algorithm/example_bit_count.cpp index 27042e271..8ecd03dfc 100644 --- a/examples/utility/algorithm/example_bit_count.cpp +++ b/examples/utility/algorithm/example_bit_count.cpp @@ -22,7 +22,7 @@ int main(int argc, char* argv[]) if (argc == 2) { cout << "Generate table for [0, 255]:" << endl; cout << '{'; - for (size_t i = 0; i < 256; ++i) { + for (uint32_t i = 0; i < 256; ++i) { if (!(i % 16)) { cout << endl << "\t"; diff --git a/examples/utility/memory_file/example_memory_file.cpp b/examples/utility/memory_file/example_memory_file.cpp index 870947eef..c4af37f07 100644 --- a/examples/utility/memory_file/example_memory_file.cpp +++ b/examples/utility/memory_file/example_memory_file.cpp @@ -43,9 +43,9 @@ int main(int argc, char* argv[]) return 0; } cout << "File size: " << fd.size() << endl; - char b[20 * 1024]; - int rv; - int rc; + char b[20 * 1024]; + ssize_t rv; + ssize_t rc; do { rv = 2 * 1024; // randomsize(); // cout<; @@ -111,14 +111,12 @@ int main(int argc, char* argv[]) {1, 100, 0}, [](const size_t, Context&) {}, [](const size_t, Context&) {}, [](FileDevice* _pfile, Context& _rctx) { int64_t sz = _pfile->size(); - int toread; - int cnt = 0; + int64_t toread; while (sz > 0) { toread = _rctx.readsz; if (toread > sz) toread = sz; - int rv = _pfile->read(_rctx.buf, toread); - cnt += rv; + ssize_t rv = _pfile->read(_rctx.buf, toread); sz -= rv; } }, diff --git a/solid/frame/aio/src/aioreactor.cpp b/solid/frame/aio/src/aioreactor.cpp index dec64fc0f..ba5a870e1 100644 --- a/solid/frame/aio/src/aioreactor.cpp +++ b/solid/frame/aio/src/aioreactor.cpp @@ -122,7 +122,6 @@ struct ActorStub { //============================================================================= constexpr size_t min_event_capacity = 32; -constexpr size_t max_event_capacity = 1024 * 64; //============================================================================= diff --git a/solid/frame/aio/test/test_echo_tcp_stress.cpp b/solid/frame/aio/test/test_echo_tcp_stress.cpp index bab2dbfcd..4a01e71c9 100644 --- a/solid/frame/aio/test/test_echo_tcp_stress.cpp +++ b/solid/frame/aio/test/test_echo_tcp_stress.cpp @@ -990,7 +990,7 @@ namespace relay { void Listener::onAccept(frame::aio::ReactorContext& _rctx, SocketDevice& _rsd) { solid_dbg(generic_logger, Info, ""); - unsigned repeatcnt = SocketInfo::max_listen_backlog_size(); + size_t repeatcnt = SocketInfo::max_listen_backlog_size(); do { if (!_rctx.error()) { diff --git a/solid/frame/mprpc/test/multiprotocol_basic/alpha/client/alphaclient.cpp b/solid/frame/mprpc/test/multiprotocol_basic/alpha/client/alphaclient.cpp index 4685d7a01..2707a2179 100644 --- a/solid/frame/mprpc/test/multiprotocol_basic/alpha/client/alphaclient.cpp +++ b/solid/frame/mprpc/test/multiprotocol_basic/alpha/client/alphaclient.cpp @@ -139,7 +139,7 @@ ErrorConditionT start( _rctx.rwait_count += 3; err = mprpcclient_ptr->sendMessage( - {"localhost"}, frame::mprpc::make_message(100000UL, make_string(100000)), + {"localhost"}, frame::mprpc::make_message(100000U, make_string(100000)), {frame::mprpc::MessageFlagsE::AwaitResponse}); if (err) { return err; diff --git a/solid/frame/mprpc/test/multiprotocol_basic/beta/client/betaclient.cpp b/solid/frame/mprpc/test/multiprotocol_basic/beta/client/betaclient.cpp index afbebeb98..81c38a4b4 100644 --- a/solid/frame/mprpc/test/multiprotocol_basic/beta/client/betaclient.cpp +++ b/solid/frame/mprpc/test/multiprotocol_basic/beta/client/betaclient.cpp @@ -134,7 +134,7 @@ ErrorConditionT start( _rctx.rwait_count += 3; err = mprpcclient_ptr->sendMessage( - {"localhost"}, frame::mprpc::make_message(100000UL, make_string(100000)), + {"localhost"}, frame::mprpc::make_message(100000U, make_string(100000)), {frame::mprpc::MessageFlagsE::AwaitResponse}); if (err) { return err; diff --git a/solid/frame/mprpc/test/multiprotocol_basic/gamma/client/gammaclient.cpp b/solid/frame/mprpc/test/multiprotocol_basic/gamma/client/gammaclient.cpp index 3c9cf98a6..00817e33e 100644 --- a/solid/frame/mprpc/test/multiprotocol_basic/gamma/client/gammaclient.cpp +++ b/solid/frame/mprpc/test/multiprotocol_basic/gamma/client/gammaclient.cpp @@ -88,7 +88,7 @@ ErrorConditionT start( _rctx.rwait_count += 3; err = mprpcclient_ptr->sendMessage( - {"localhost"}, frame::mprpc::make_message(100000UL, make_string(100000)), + {"localhost"}, frame::mprpc::make_message(100000U, make_string(100000)), {frame::mprpc::MessageFlagsE::AwaitResponse}); if (err) { return err; diff --git a/solid/frame/mprpc/test/test_clientserver_basic.cpp b/solid/frame/mprpc/test/test_clientserver_basic.cpp index f20748bb9..3841c9b21 100644 --- a/solid/frame/mprpc/test/test_clientserver_basic.cpp +++ b/solid/frame/mprpc/test/test_clientserver_basic.cpp @@ -61,11 +61,11 @@ InitStub initarray[] = { std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); -std::atomic crtreadidx(0); -std::atomic crtbackidx(0); -std::atomic crtackidx(0); -std::atomic writecount(0); +std::atomic crtwriteidx(0); +std::atomic crtreadidx(0); +std::atomic crtbackidx(0); +std::atomic crtackidx(0); +std::atomic writecount(0); size_t connection_count(0); bool running = true; @@ -247,11 +247,13 @@ void server_complete_message( ++crtreadidx; solid_dbg(generic_logger, Info, crtreadidx); - if (crtwriteidx < writecount) { + if (crtwriteidx < writecount and pmprpcclient) { err = pmprpcclient->sendMessage( {""}, frame::mprpc::make_message(crtwriteidx++), initarray[crtwriteidx % initarraysize].flags | frame::mprpc::MessageFlagsE::AwaitResponse); solid_check(!err, "Connection id should not be invalid! " << err.message()); + } else { + solid_check(pmprpcclient, "pmprpcclient should not be nullptr"); } } if (_rsent_msg_ptr) { diff --git a/solid/frame/mprpc/test/test_clientserver_cancel_client.cpp b/solid/frame/mprpc/test/test_clientserver_cancel_client.cpp index 5e1be5a2e..a0827eba8 100644 --- a/solid/frame/mprpc/test/test_clientserver_cancel_client.cpp +++ b/solid/frame/mprpc/test/test_clientserver_cancel_client.cpp @@ -73,8 +73,8 @@ typedef std::vector MessageIdVectorT; std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); -std::atomic crtreadidx(0); +std::atomic crtwriteidx(0); +std::atomic crtreadidx(0); // std::atomic crtbackidx(0); // std::atomic crtackidx(0); std::atomic writecount(0); @@ -235,13 +235,15 @@ void server_receive_message(frame::mprpc::ConnectionContext& _rctx, MessagePoint transfered_size += _rmsgptr->str.size(); ++transfered_count; - if (crtreadidx == 0) { + if (crtreadidx == 0 and pmprpcclient) { solid_dbg(generic_logger, Info, "canceling all messages"); lock_guard lock(mtx); for (auto& msguid : message_uid_vec) { solid_dbg(generic_logger, Info, "Cancel message: " << msguid); pmprpcclient->cancelMessage(recipient_id, msguid); } + } else { + solid_check(pmprpcclient, "pmprpcclient should not be nullptr"); } ++crtreadidx; diff --git a/solid/frame/mprpc/test/test_clientserver_cancel_server.cpp b/solid/frame/mprpc/test/test_clientserver_cancel_server.cpp index 76a52cd0a..aee316848 100644 --- a/solid/frame/mprpc/test/test_clientserver_cancel_server.cpp +++ b/solid/frame/mprpc/test/test_clientserver_cancel_server.cpp @@ -72,7 +72,7 @@ typedef std::vector MessageIdVectorT; std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); +std::atomic crtwriteidx(0); std::atomic crtbackidx(0); std::atomic crtackidx(0); std::atomic writecount(0); @@ -200,13 +200,15 @@ void client_receive_message(frame::mprpc::ConnectionContext& _rctx, MessagePoint transfered_size += _rmsgptr->str.size(); ++transfered_count; - if (crtbackidx == 0u) { + if (crtbackidx == 0u and pmprpcclient) { solid_dbg(generic_logger, Info, "canceling all messages"); lock_guard lock(mtx); for (const auto& msguid : message_uid_vec) { solid_dbg(generic_logger, Info, "Cancel message: " << msguid); pmprpcserver->cancelMessage(recipient_id, msguid); } + } else { + solid_check(pmprpcclient, "pmprpcclient should not be nullptr"); } ++crtbackidx; diff --git a/solid/frame/mprpc/test/test_clientserver_pause_read.cpp b/solid/frame/mprpc/test/test_clientserver_pause_read.cpp index fd4eb4b09..993e42b19 100644 --- a/solid/frame/mprpc/test/test_clientserver_pause_read.cpp +++ b/solid/frame/mprpc/test/test_clientserver_pause_read.cpp @@ -61,10 +61,10 @@ InitStub initarray[] = { std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); -std::atomic crtreadidx(0); -std::atomic crtbackidx(0); -std::atomic crtackidx(0); +std::atomic crtwriteidx(0); +std::atomic crtreadidx(0); +std::atomic crtbackidx(0); +std::atomic crtackidx(0); size_t connection_count(0); bool running = true; diff --git a/solid/frame/mprpc/test/test_clientserver_sendrequest.cpp b/solid/frame/mprpc/test/test_clientserver_sendrequest.cpp index c3e5b6edf..34bcfcc6a 100644 --- a/solid/frame/mprpc/test/test_clientserver_sendrequest.cpp +++ b/solid/frame/mprpc/test/test_clientserver_sendrequest.cpp @@ -59,11 +59,11 @@ InitStub initarray[] = { std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); -std::atomic crtreadidx(0); -std::atomic crtbackidx(0); -std::atomic crtackidx(0); -std::atomic writecount(0); +std::atomic crtwriteidx(0); +std::atomic crtreadidx(0); +std::atomic crtbackidx(0); +std::atomic crtackidx(0); +std::atomic writecount(0); size_t connection_count(0); @@ -309,7 +309,7 @@ void server_complete_request( solid_dbg(generic_logger, Info, crtreadidx); - if (crtwriteidx < writecount) { + if (crtwriteidx < writecount and pmprpcclient) { auto msgptr(frame::mprpc::make_message(crtwriteidx)); ++crtwriteidx; pmprpcclient->sendRequest( @@ -321,6 +321,8 @@ void server_complete_request( }*/ , initarray[crtwriteidx % initarraysize].flags); + } else { + solid_check(pmprpcclient, "pmprpcclient should not be nullptr"); } } diff --git a/solid/frame/mprpc/test/test_clientserver_split.cpp b/solid/frame/mprpc/test/test_clientserver_split.cpp index bdba9936a..9db5616c9 100644 --- a/solid/frame/mprpc/test/test_clientserver_split.cpp +++ b/solid/frame/mprpc/test/test_clientserver_split.cpp @@ -60,11 +60,11 @@ InitStub initarray[] = { std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); -std::atomic crtreadidx(0); -std::atomic crtbackidx(0); -std::atomic crtackidx(0); -std::atomic writecount(0); +std::atomic crtwriteidx(0); +std::atomic crtreadidx(0); +std::atomic crtbackidx(0); +std::atomic crtackidx(0); +std::atomic writecount(0); size_t connection_count(0); bool running = true; @@ -284,11 +284,13 @@ void server_complete_message( ++crtreadidx; solid_dbg(generic_logger, Info, crtreadidx); - if (crtwriteidx < writecount) { + if (crtwriteidx < writecount and pmprpcclient) { err = pmprpcclient->sendMessage( {"localhost"}, frame::mprpc::make_message(crtwriteidx++), initarray[crtwriteidx % initarraysize].flags | frame::mprpc::MessageFlagsE::AwaitResponse); solid_check(!err, "Connection id should not be invalid! " << err.message()); + } else { + solid_check(pmprpcclient, "pmprpcclient should not be nullptr"); } } if (_rsent_msg_ptr) { diff --git a/solid/frame/mprpc/test/test_clientserver_stop.cpp b/solid/frame/mprpc/test/test_clientserver_stop.cpp index b9b902f91..98f0497df 100644 --- a/solid/frame/mprpc/test/test_clientserver_stop.cpp +++ b/solid/frame/mprpc/test/test_clientserver_stop.cpp @@ -100,11 +100,11 @@ InitStub initarray[] = { std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); -std::atomic crtreadidx(0); -std::atomic crtbackidx(0); -std::atomic crtackidx(0); -std::atomic writecount(0); +std::atomic crtwriteidx(0); +std::atomic crtreadidx(0); +std::atomic crtbackidx(0); +std::atomic crtackidx(0); +std::atomic writecount(0); size_t connection_count(0); bool running = true; @@ -287,11 +287,13 @@ void server_complete_message( } solid_dbg(generic_logger, Info, crtreadidx << " " << crtwriteidx); - if (crtwriteidx < writecount) { + if (crtwriteidx < writecount and pmprpcclient) { err = pmprpcclient->sendMessage( {""}, frame::mprpc::make_message(crtwriteidx++), initarray[crtwriteidx % initarraysize].flags | frame::mprpc::MessageFlagsE::AwaitResponse | frame::mprpc::MessageFlagsE::Idempotent); solid_check(!err, "Connection id should not be invalid! " << err.message()); + } else { + solid_check(pmprpcclient, "pmprpcclient should not be nullptr"); } } if (_rsent_msg_ptr) { diff --git a/solid/frame/mprpc/test/test_clientserver_topic.cpp b/solid/frame/mprpc/test/test_clientserver_topic.cpp index 237d2ec88..2ef47bf0e 100644 --- a/solid/frame/mprpc/test/test_clientserver_topic.cpp +++ b/solid/frame/mprpc/test/test_clientserver_topic.cpp @@ -483,9 +483,9 @@ int test_clientserver_topic(int argc, char* argv[]) solid_log(logger, Warning, "========== START sending messages =========="); - if (false) { + if (/* DISABLES CODE */ (false)) { const uint64_t startms = microseconds_since_epoch(); - for (size_t i = 0; i < message_count; ++i) { + for (uint32_t i = 0; i < message_count; ++i) { mprpcclient.sendMessage(client_id, frame::mprpc::make_message(i, microseconds_since_epoch()), {frame::mprpc::MessageFlagsE::AwaitResponse}); } solid_log(logger, Warning, "========== DONE sending messages ========== " << (microseconds_since_epoch() - startms) << "us"); @@ -495,7 +495,7 @@ int test_clientserver_topic(int argc, char* argv[]) const auto start = chrono::high_resolution_clock::now(); - for (size_t i = 0; i < message_count; ++i) { + for (uint32_t i = 0; i < message_count; ++i) { this_thread::sleep_until(start + chrono::microseconds(static_cast(lin_value(0.0, stop, i, message_count)))); mprpcclient.sendMessage(client_id, frame::mprpc::make_message(i, microseconds_since_epoch()), {frame::mprpc::MessageFlagsE::AwaitResponse}); } @@ -537,7 +537,7 @@ int test_clientserver_topic(int argc, char* argv[]) } } #endif - if (0) { + if (/* DISABLES CODE */ (false)) { ofstream ofs("trace.csv"); if (ofs) { for (const auto& t : trace_dq) { @@ -692,7 +692,7 @@ void server_complete_request( static_assert(CallPoolT::is_small_one_type(), "Type not small"); - if (false) { + if (/* DISABLES CODE */ (false)) { std::lock_guard lock(trace_mtx); if (!trace_dq.empty()) { if (get<0>(trace_dq.back()) == _rctx.recipientId().connectionId().index) { diff --git a/solid/frame/mprpc/test/test_clientserver_versioning.cpp b/solid/frame/mprpc/test/test_clientserver_versioning.cpp index 3c9d751b6..1e2e4b208 100644 --- a/solid/frame/mprpc/test/test_clientserver_versioning.cpp +++ b/solid/frame/mprpc/test/test_clientserver_versioning.cpp @@ -461,7 +461,7 @@ void complete_message( if (_rctx.any().get_if()->version_ == 2) { // need to send back Response2 auto res_ptr = frame::mprpc::make_message(*_rrecv_msg_ptr); - res_ptr->error_ = _rrecv_msg_ptr->values_.size(); + res_ptr->error_ = static_cast(_rrecv_msg_ptr->values_.size()); _rctx.service().sendResponse(_rctx.recipientId(), res_ptr); } else if (_rctx.any().get_if()->request_ == 1) { auto res_ptr = frame::mprpc::make_message(*_rrecv_msg_ptr); diff --git a/solid/frame/mprpc/test/test_connection_close.cpp b/solid/frame/mprpc/test/test_connection_close.cpp index 28c2eeb54..acfe0917e 100644 --- a/solid/frame/mprpc/test/test_connection_close.cpp +++ b/solid/frame/mprpc/test/test_connection_close.cpp @@ -201,12 +201,14 @@ void client_complete_message( solid_throw("Message not back on sender!."); } - { + if (pmprpcclient) { auto msgptr(frame::mprpc::make_message()); pmprpcclient->sendMessage( _rctx.recipientId(), msgptr, {frame::mprpc::MessageFlagsE::AwaitResponse}); + } else { + solid_check(pmprpcclient, "pmprpcclient should not be nullptr"); } client_received_message = true; diff --git a/solid/frame/mprpc/test/test_keepalive_fail.cpp b/solid/frame/mprpc/test/test_keepalive_fail.cpp index 96d660563..1259078fc 100644 --- a/solid/frame/mprpc/test/test_keepalive_fail.cpp +++ b/solid/frame/mprpc/test/test_keepalive_fail.cpp @@ -62,11 +62,11 @@ InitStub initarray[] = { std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); -std::atomic crtreadidx(0); -std::atomic crtbackidx(0); -std::atomic crtackidx(0); -std::atomic writecount(0); +std::atomic crtwriteidx(0); +std::atomic crtreadidx(0); +std::atomic crtbackidx(0); +std::atomic crtackidx(0); +std::atomic writecount(0); size_t connection_count(0); @@ -250,12 +250,14 @@ void server_receive_message(frame::mprpc::ConnectionContext& _rctx, MessagePoint ++crtreadidx; solid_dbg(generic_logger, Info, crtreadidx); - if (crtwriteidx < writecount) { + if (crtwriteidx < writecount and pmprpcclient) { MessagePointerT msgptr(frame::mprpc::make_message(crtwriteidx)); ++crtwriteidx; pmprpcclient->sendMessage( {"localhost"}, msgptr, initarray[crtwriteidx % initarraysize].flags | frame::mprpc::MessageFlagsE::AwaitResponse); + } else { + solid_check(pmprpcclient, "pointer should not be nullptr"); } } diff --git a/solid/frame/mprpc/test/test_keepalive_success.cpp b/solid/frame/mprpc/test/test_keepalive_success.cpp index d610dc06a..192d55d3f 100644 --- a/solid/frame/mprpc/test/test_keepalive_success.cpp +++ b/solid/frame/mprpc/test/test_keepalive_success.cpp @@ -61,7 +61,7 @@ InitStub initarray[] = { std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); +std::atomic crtwriteidx(0); // std::atomic crtreadidx(0); std::atomic crtbackidx(0); std::atomic crtackidx(0); diff --git a/solid/frame/mprpc/test/test_pool_basic.cpp b/solid/frame/mprpc/test/test_pool_basic.cpp index 1034b0eb4..10736a4b9 100644 --- a/solid/frame/mprpc/test/test_pool_basic.cpp +++ b/solid/frame/mprpc/test/test_pool_basic.cpp @@ -60,11 +60,11 @@ InitStub initarray[] = { std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); -std::atomic crtreadidx(0); -std::atomic crtbackidx(0); -std::atomic crtackidx(0); -std::atomic writecount(0); +std::atomic crtwriteidx(0); +std::atomic crtreadidx(0); +std::atomic crtbackidx(0); +std::atomic crtackidx(0); +std::atomic writecount(0); size_t connection_count(0); bool running = true; @@ -246,11 +246,13 @@ void server_complete_message( ++crtreadidx; solid_dbg(generic_logger, Info, crtreadidx); - if (crtwriteidx < writecount) { + if (crtwriteidx < writecount and pmprpcclient) { err = pmprpcclient->sendMessage( client_id, frame::mprpc::make_message(crtwriteidx++), initarray[crtwriteidx % initarraysize].flags | frame::mprpc::MessageFlagsE::AwaitResponse); solid_check(!err, "Connection id should not be invalid! " << err.message()); + } else { + solid_check(pmprpcclient, "pmprpcclient should not be nullptr"); } } if (_rsent_msg_ptr) { diff --git a/solid/frame/mprpc/test/test_pool_delay_close.cpp b/solid/frame/mprpc/test/test_pool_delay_close.cpp index 638eed8a7..978d9cae4 100644 --- a/solid/frame/mprpc/test/test_pool_delay_close.cpp +++ b/solid/frame/mprpc/test/test_pool_delay_close.cpp @@ -358,7 +358,7 @@ int test_pool_delay_close(int argc, char* argv[]) { std::vector msg_vec; - for (size_t i = 0; i < start_count; ++i) { + for (uint32_t i = 0; i < start_count; ++i) { msg_vec.push_back(MessagePointerT(frame::mprpc::make_message(i))); } diff --git a/solid/frame/mprpc/test/test_pool_force_close.cpp b/solid/frame/mprpc/test/test_pool_force_close.cpp index 733b02d10..620e163ae 100644 --- a/solid/frame/mprpc/test/test_pool_force_close.cpp +++ b/solid/frame/mprpc/test/test_pool_force_close.cpp @@ -116,7 +116,7 @@ struct Message : frame::mprpc::Message { if (_rthis.isOnPeer()) { ++crtreadidx; solid_dbg(generic_logger, Info, crtreadidx); - if (crtreadidx == 1) { + if (crtreadidx == 1 and pmprpcclient) { pmprpcclient->forceCloseConnectionPool( recipinet_id, @@ -126,6 +126,8 @@ struct Message : frame::mprpc::Message { running = false; cnd.notify_one(); }); + } else { + solid_check(pmprpcclient, "pmprpcclient should not be nullptr"); } } } @@ -328,7 +330,7 @@ int test_pool_force_close(int argc, char* argv[]) std::vector msg_vec; ErrorConditionT err; - for (size_t i = 0; i < start_count; ++i) { + for (uint32_t i = 0; i < start_count; ++i) { msg_vec.push_back(MessagePointerT(frame::mprpc::make_message(i))); } { diff --git a/solid/frame/mprpc/test/test_protocol_basic.cpp b/solid/frame/mprpc/test/test_protocol_basic.cpp index 7cc0070f8..6cfbba2f9 100644 --- a/solid/frame/mprpc/test/test_protocol_basic.cpp +++ b/solid/frame/mprpc/test/test_protocol_basic.cpp @@ -48,7 +48,7 @@ InitStub initarray[] = { std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -size_t crtwriteidx = 0; +uint32_t crtwriteidx = 0; uint32_t crtreadidx = 0; size_t writecount = 0; @@ -199,9 +199,9 @@ struct Receiver : frame::mprpc::MessageReaderReceiver { { } - void fillRequestVector(size_t _m = 10) + void fillRequestVector(uint32_t const _m = 10) { - for (size_t i = 0; i < _m; ++i) { + for (uint32_t i = 0; i < _m; ++i) { reqvec.push_back(frame::mprpc::RequestId(i, i)); } } diff --git a/solid/frame/mprpc/test/test_protocol_synchronous.cpp b/solid/frame/mprpc/test/test_protocol_synchronous.cpp index 5ca9192ee..4b0471ab8 100644 --- a/solid/frame/mprpc/test/test_protocol_synchronous.cpp +++ b/solid/frame/mprpc/test/test_protocol_synchronous.cpp @@ -32,9 +32,9 @@ InitStub initarray[] = { std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -size_t crtwriteidx = 0; -size_t crtreadidx = 0; -size_t writecount = 0; +uint32_t crtwriteidx = 0; +uint32_t crtreadidx = 0; +size_t writecount = 0; size_t real_size(size_t _sz) { @@ -187,7 +187,7 @@ struct Receiver : frame::mprpc::MessageReaderReceiver { void fillRequestVector(size_t _m = 10) { - for (size_t i = 0; i < _m; ++i) { + for (uint32_t i = 0; i < _m; ++i) { reqvec.push_back(frame::mprpc::RequestId(i, i)); } } diff --git a/solid/frame/mprpc/test/test_raw_basic.cpp b/solid/frame/mprpc/test/test_raw_basic.cpp index 150fde3a0..7193c3f23 100644 --- a/solid/frame/mprpc/test/test_raw_basic.cpp +++ b/solid/frame/mprpc/test/test_raw_basic.cpp @@ -57,11 +57,11 @@ InitStub initarray[] = { std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); -std::atomic crtreadidx(0); -std::atomic crtbackidx(0); -std::atomic crtackidx(0); -std::atomic writecount(0); +std::atomic crtwriteidx(0); +std::atomic crtreadidx(0); +std::atomic crtbackidx(0); +std::atomic crtackidx(0); +std::atomic writecount(0); size_t connection_count(0); diff --git a/solid/frame/mprpc/test/test_raw_proxy.cpp b/solid/frame/mprpc/test/test_raw_proxy.cpp index 956a85948..21b239d7b 100644 --- a/solid/frame/mprpc/test/test_raw_proxy.cpp +++ b/solid/frame/mprpc/test/test_raw_proxy.cpp @@ -56,11 +56,11 @@ InitStub initarray[] = { std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); -std::atomic crtreadidx(0); -std::atomic crtbackidx(0); -std::atomic crtackidx(0); -std::atomic writecount(0); +std::atomic crtwriteidx(0); +std::atomic crtreadidx(0); +std::atomic crtbackidx(0); +std::atomic crtackidx(0); +std::atomic writecount(0); size_t connection_count(0); diff --git a/solid/frame/mprpc/test/test_relay_basic.cpp b/solid/frame/mprpc/test/test_relay_basic.cpp index eee641662..b843a3d4e 100644 --- a/solid/frame/mprpc/test/test_relay_basic.cpp +++ b/solid/frame/mprpc/test/test_relay_basic.cpp @@ -66,12 +66,12 @@ InitStub initarray[] = { std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); -std::atomic crtreadidx(0); -std::atomic crtbackidx(0); -std::atomic crtackidx(0); -std::atomic writecount(0); -std::atomic connection_count(0); +std::atomic crtwriteidx(0); +std::atomic crtreadidx(0); +std::atomic crtbackidx(0); +std::atomic crtackidx(0); +std::atomic writecount(0); +std::atomic connection_count(0); std::atomic running = true; mutex mtx; diff --git a/solid/frame/mprpc/test/test_relay_cancel_request.cpp b/solid/frame/mprpc/test/test_relay_cancel_request.cpp index 8121b0e3f..33317c899 100644 --- a/solid/frame/mprpc/test/test_relay_cancel_request.cpp +++ b/solid/frame/mprpc/test/test_relay_cancel_request.cpp @@ -69,7 +69,7 @@ using MessageIdVectorT = std::deque; std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); +std::atomic crtwriteidx(0); std::atomic writecount(0); std::atomic created_count(0); std::atomic cancelable_created_count(0); diff --git a/solid/frame/mprpc/test/test_relay_cancel_response.cpp b/solid/frame/mprpc/test/test_relay_cancel_response.cpp index ac11fc2aa..228b7a362 100644 --- a/solid/frame/mprpc/test/test_relay_cancel_response.cpp +++ b/solid/frame/mprpc/test/test_relay_cancel_response.cpp @@ -69,7 +69,7 @@ using MessageIdVectorT = std::deque; std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); +std::atomic crtwriteidx(0); std::atomic writecount(0); std::atomic created_count(0); std::atomic cancelable_created_count(0); diff --git a/solid/frame/mprpc/test/test_relay_close_request.cpp b/solid/frame/mprpc/test/test_relay_close_request.cpp index 39a7d7b53..86a4965b7 100644 --- a/solid/frame/mprpc/test/test_relay_close_request.cpp +++ b/solid/frame/mprpc/test/test_relay_close_request.cpp @@ -55,7 +55,7 @@ using MessageIdVectorT = std::deque; std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); +std::atomic crtwriteidx(0); std::atomic writecount(0); std::atomic created_count(0); std::atomic canceled_count(0); diff --git a/solid/frame/mprpc/test/test_relay_close_response.cpp b/solid/frame/mprpc/test/test_relay_close_response.cpp index 3fb4b160e..cf83ea3d5 100644 --- a/solid/frame/mprpc/test/test_relay_close_response.cpp +++ b/solid/frame/mprpc/test/test_relay_close_response.cpp @@ -55,7 +55,7 @@ using MessageIdVectorT = std::deque; std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); +std::atomic crtwriteidx(0); std::atomic writecount(0); std::atomic created_count(0); std::atomic canceled_count(0); diff --git a/solid/frame/mprpc/test/test_relay_detect_close.cpp b/solid/frame/mprpc/test/test_relay_detect_close.cpp index 66f14b1f7..b9ae205fe 100644 --- a/solid/frame/mprpc/test/test_relay_detect_close.cpp +++ b/solid/frame/mprpc/test/test_relay_detect_close.cpp @@ -140,8 +140,6 @@ void peera_complete_detect_close( solid::frame::mprpc::MessagePointerT& _rsent_msg_ptr, solid::frame::mprpc::MessagePointerT& _rrecv_msg_ptr, ErrorConditionT const& _rerror) { - static size_t call_count = 0; - ++call_count; solid_dbg(generic_logger, Info, _rctx.recipientId() << " error: " << _rerror.message()); if (_rrecv_msg_ptr) { solid_dbg(generic_logger, Info, _rctx.recipientId() << " peera received DetectCloseMessage " << _rrecv_msg_ptr->idx); diff --git a/solid/frame/mprpc/test/test_relay_detect_close_while_response.cpp b/solid/frame/mprpc/test/test_relay_detect_close_while_response.cpp index c80982cd0..3835797e9 100644 --- a/solid/frame/mprpc/test/test_relay_detect_close_while_response.cpp +++ b/solid/frame/mprpc/test/test_relay_detect_close_while_response.cpp @@ -182,8 +182,6 @@ void peera_complete_detect_close( solid::frame::mprpc::MessagePointerT& _rsent_msg_ptr, solid::frame::mprpc::MessagePointerT& _rrecv_msg_ptr, ErrorConditionT const& _rerror) { - static size_t call_count = 0; - ++call_count; solid_dbg(generic_logger, Info, _rctx.recipientId() << " error: " << _rerror.message()); if (_rrecv_msg_ptr) { solid_dbg(generic_logger, Info, _rctx.recipientId() << " peera received DetectCloseMessage " << _rrecv_msg_ptr->idx); diff --git a/solid/frame/mprpc/test/test_relay_disabled.cpp b/solid/frame/mprpc/test/test_relay_disabled.cpp index 31710c16f..ede0d8eda 100644 --- a/solid/frame/mprpc/test/test_relay_disabled.cpp +++ b/solid/frame/mprpc/test/test_relay_disabled.cpp @@ -64,11 +64,11 @@ InitStub initarray[] = { std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); -std::atomic crtreadidx(0); -std::atomic crtbackidx(0); -std::atomic crtackidx(0); -std::atomic writecount(0); +std::atomic crtwriteidx(0); +std::atomic crtreadidx(0); +std::atomic crtbackidx(0); +std::atomic crtackidx(0); +std::atomic writecount(0); size_t connection_count(0); diff --git a/solid/frame/mprpc/test/test_relay_split.cpp b/solid/frame/mprpc/test/test_relay_split.cpp index d159c37c5..55fc0f6f9 100644 --- a/solid/frame/mprpc/test/test_relay_split.cpp +++ b/solid/frame/mprpc/test/test_relay_split.cpp @@ -65,12 +65,12 @@ InitStub initarray[] = { std::string pattern; const size_t initarraysize = sizeof(initarray) / sizeof(InitStub); -std::atomic crtwriteidx(0); -std::atomic crtreadidx(0); -std::atomic crtbackidx(0); -std::atomic crtackidx(0); -std::atomic writecount(0); -std::atomic connection_count(0); +std::atomic crtwriteidx(0); +std::atomic crtreadidx(0); +std::atomic crtbackidx(0); +std::atomic crtackidx(0); +std::atomic writecount(0); +std::atomic connection_count(0); std::atomic running = true; mutex mtx; diff --git a/solid/frame/src/reactor.cpp b/solid/frame/src/reactor.cpp index 10b25ac3b..e747dffe6 100644 --- a/solid/frame/src/reactor.cpp +++ b/solid/frame/src/reactor.cpp @@ -95,7 +95,6 @@ struct ActorStub { } }; -constexpr size_t min_event_capacity = 32; constexpr size_t max_event_capacity = 1024 * 64; using UniqueIdVectorT = std::vector; diff --git a/solid/serialization/v3/binarydeserializer.hpp b/solid/serialization/v3/binarydeserializer.hpp index 91d3a7fb3..e006cde99 100644 --- a/solid/serialization/v3/binarydeserializer.hpp +++ b/solid/serialization/v3/binarydeserializer.hpp @@ -116,7 +116,7 @@ class DeserializerBase : public Base { public: std::istream& run(std::istream& _ris, void* _pctx = nullptr); - ptrdiff_t run(const char* _pbeg, unsigned _sz, void* _pctx = nullptr); + ptrdiff_t run(const char* _pbeg, size_t _sz, void* _pctx = nullptr); void clear(); @@ -1028,14 +1028,14 @@ class Deserializer : public DeserializerBase { } template - ptrdiff_t run(const char* _pbeg, unsigned _sz, F _f, ContextT& _rctx) + ptrdiff_t run(const char* _pbeg, size_t _sz, F _f, ContextT& _rctx) { doPrepareRun(_pbeg, _sz); _f(*this, _rctx); return doRun(&_rctx); } - ptrdiff_t run(const char* _pbeg, unsigned _sz, ContextT& _rctx) + ptrdiff_t run(const char* _pbeg, size_t _sz, ContextT& _rctx) { return DeserializerBase::run(_pbeg, _sz, &_rctx); } diff --git a/solid/serialization/v3/binaryserializer.hpp b/solid/serialization/v3/binaryserializer.hpp index d9dbbfacf..17e9502ec 100644 --- a/solid/serialization/v3/binaryserializer.hpp +++ b/solid/serialization/v3/binaryserializer.hpp @@ -101,7 +101,7 @@ class SerializerBase : public Base { static constexpr bool is_const_reflector = true; std::ostream& run(std::ostream& _ros, void* _pctx = nullptr); - ptrdiff_t run(char* _pbeg, unsigned _sz, void* _pctx = nullptr); + ptrdiff_t run(char* _pbeg, size_t _sz, void* _pctx = nullptr); void clear(); @@ -545,7 +545,7 @@ class SerializerBase : public Base { } protected: - void doPrepareRun(char* _pbeg, unsigned _sz) + void doPrepareRun(char* _pbeg, size_t const _sz) { pbeg_ = _pbeg; pend_ = _pbeg + _sz; diff --git a/solid/serialization/v3/src/binarydeserializer.cpp b/solid/serialization/v3/src/binarydeserializer.cpp index 91269a2c1..89932aa4d 100644 --- a/solid/serialization/v3/src/binarydeserializer.cpp +++ b/solid/serialization/v3/src/binarydeserializer.cpp @@ -43,7 +43,7 @@ std::istream& DeserializerBase::run(std::istream& _ris, void* /*_pctx*/) return _ris; } -ptrdiff_t DeserializerBase::run(const char* _pbeg, unsigned _sz, void* _pctx) +ptrdiff_t DeserializerBase::run(const char* _pbeg, size_t const _sz, void* _pctx) { doPrepareRun(_pbeg, _sz); return doRun(_pctx); diff --git a/solid/serialization/v3/src/binaryserializer.cpp b/solid/serialization/v3/src/binaryserializer.cpp index 02697e2ae..47c4131d2 100644 --- a/solid/serialization/v3/src/binaryserializer.cpp +++ b/solid/serialization/v3/src/binaryserializer.cpp @@ -41,7 +41,7 @@ std::ostream& SerializerBase::run(std::ostream& _ros, void* _pctx) return _ros; } -ptrdiff_t SerializerBase::run(char* _pbeg, unsigned _sz, void* _pctx) +ptrdiff_t SerializerBase::run(char* _pbeg, size_t const _sz, void* _pctx) { doPrepareRun(_pbeg, _sz); return doRun(_pctx); diff --git a/solid/serialization/v3/test/test_binary.cpp b/solid/serialization/v3/test/test_binary.cpp index d8221b66e..4dbcbb644 100644 --- a/solid/serialization/v3/test/test_binary.cpp +++ b/solid/serialization/v3/test/test_binary.cpp @@ -75,9 +75,9 @@ class Test { uint32_t blob64_sz = 0; char blob64[sizeof(uint64_t)]; - std::ostringstream oss; - std::istringstream iss; - string* pstr = nullptr; + std::ostringstream oss; + std::istringstream iss; + [[maybe_unused]] string* pstr = nullptr; void populate(bool _b) { diff --git a/solid/serialization/v3/test/test_container.cpp b/solid/serialization/v3/test/test_container.cpp index e2f67a8cb..265f88f8c 100644 --- a/solid/serialization/v3/test/test_container.cpp +++ b/solid/serialization/v3/test/test_container.cpp @@ -232,7 +232,7 @@ void Test::init() } } - v32 = str.size(); + v32 = static_cast(str.size()); for (size_t i = 0; i < 100; ++i) { sa[i] = kv_array[i % kv_array_size].second; diff --git a/solid/system/pimpl.hpp b/solid/system/pimpl.hpp index bdd7b5b6e..3b80f0b1b 100644 --- a/solid/system/pimpl.hpp +++ b/solid/system/pimpl.hpp @@ -29,7 +29,7 @@ class Pimpl { Pimpl(Args&&... args) { static_assert(sizeof(T) <= Cp && alignof(T) <= Align); -#if __cpp_static_assert >= 202306L +#if __cpp_static_assert > 202306L // Not real C++ yet (std::format should be constexpr to work): static_assert(sizeof(T) <= Cp, std::format("Increase the capacity! Expected {}, got {}", sizeof(T), Cp)); #else diff --git a/solid/utility/event.hpp b/solid/utility/event.hpp index 2a456e925..3b9c4fbaf 100644 --- a/solid/utility/event.hpp +++ b/solid/utility/event.hpp @@ -484,12 +484,12 @@ class Event : public EventBase { Event(const Evs _ev, T&& _rvalue) : EventBase(category, to_underlying(_ev)) { - - if constexpr (is_small_type()) { - auto& rval = reinterpret_cast(data_); - doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), std::forward(_rvalue)); + using ValueT = std::decay_t; + if constexpr (is_small_type()) { + auto& rval = reinterpret_cast(data_); + doEmplaceSmall(std::addressof(rval), std::forward(_rvalue)); } else { - doEmplaceBig>(std::forward(_rvalue)); + doEmplaceBig(std::forward<>(_rvalue)); } } @@ -497,12 +497,12 @@ class Event : public EventBase { Event(const EventCategoryBase& _category, const Evs _ev, T&& _rvalue) : EventBase(_category, to_underlying(_ev)) { - - if constexpr (is_small_type()) { - auto& rval = reinterpret_cast(data_); - doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), std::forward(_rvalue)); + using ValueT = std::decay_t; + if constexpr (is_small_type()) { + auto& rval = reinterpret_cast(data_); + doEmplaceSmall(std::addressof(rval), std::forward(_rvalue)); } else { - doEmplaceBig>(std::forward(_rvalue)); + doEmplaceBig(std::forward(_rvalue)); } } @@ -514,11 +514,12 @@ class Event : public EventBase { explicit Event(const Evs _ev, std::in_place_type_t, Args&&... _args) : EventBase(category, to_underlying(_ev)) { - if constexpr (is_small_type()) { - auto& rval = reinterpret_cast(data_); - doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), std::forward(_args)...); + using ValueT = std::decay_t; + if constexpr (is_small_type()) { + auto& rval = reinterpret_cast(data_); + doEmplaceSmall(std::addressof(rval), std::forward(_args)...); } else { - doEmplaceBig>(std::forward(_args)...); + doEmplaceBig(std::forward(_args)...); } } @@ -530,11 +531,12 @@ class Event : public EventBase { explicit Event(const EventCategoryBase& _category, const Evs _ev, std::in_place_type_t, Args&&... _args) : EventBase(_category, to_underlying(_ev)) { - if constexpr (is_small_type()) { - auto& rval = reinterpret_cast(data_); - doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), std::forward(_args)...); + using ValueT = std::decay_t; + if constexpr (is_small_type()) { + auto& rval = reinterpret_cast(data_); + doEmplaceSmall(std::addressof(rval), std::forward(_args)...); } else { - doEmplaceBig>(std::forward(_args)...); + doEmplaceBig(std::forward(_args)...); } } @@ -546,11 +548,12 @@ class Event : public EventBase { explicit Event(const Evs _ev, std::in_place_type_t, std::initializer_list _ilist, Args&&... _args) : EventBase(category, to_underlying(_ev)) { - if constexpr (is_small_type()) { - auto& rval = reinterpret_cast(data_); - doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), _ilist, std::forward(_args)...); + using ValueT = std::decay_t; + if constexpr (is_small_type()) { + auto& rval = reinterpret_cast(data_); + doEmplaceSmall(std::addressof(rval), _ilist, std::forward(_args)...); } else { - doEmplaceBig>(_ilist, std::forward(_args)...); + doEmplaceBig(_ilist, std::forward(_args)...); } } @@ -562,11 +565,12 @@ class Event : public EventBase { explicit Event(const EventCategoryBase& _category, const Evs _ev, std::in_place_type_t, std::initializer_list _ilist, Args&&... _args) : EventBase(_category, to_underlying(_ev)) { - if constexpr (is_small_type()) { - auto& rval = reinterpret_cast(data_); - doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), _ilist, std::forward(_args)...); + using ValueT = std::decay_t; + if constexpr (is_small_type()) { + auto& rval = reinterpret_cast(data_); + doEmplaceSmall(std::addressof(rval), _ilist, std::forward(_args)...); } else { - doEmplaceBig>(_ilist, std::forward(_args)...); + doEmplaceBig(_ilist, std::forward(_args)...); } } @@ -617,7 +621,7 @@ class Event : public EventBase { if constexpr (is_small_type()) { auto& rval = reinterpret_cast(data_); - doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), std::forward(_rvalue)); + doEmplaceSmall>(std::addressof(rval), std::forward(_rvalue)); } else { doEmplaceBig>(std::forward(_rvalue)); } @@ -632,11 +636,12 @@ class Event : public EventBase { std::decay_t& emplace(Args&&... _args) { resetData(); - if constexpr (is_small_type()) { - auto& rval = reinterpret_cast(data_); - return doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), std::forward(_args)...); + using ValueT = std::decay_t; + if constexpr (is_small_type()) { + auto& rval = reinterpret_cast(data_); + return doEmplaceSmall(std::addressof(rval), std::forward(_args)...); } else { - return doEmplaceBig>(std::forward(_args)...); + return doEmplaceBig(std::forward(_args)...); } } template & emplace(std::initializer_list _ilist, Args&&... _args) { resetData(); - if constexpr (is_small_type()) { - auto& rval = reinterpret_cast(data_); - return doEmplaceSmall>(const_cast(static_cast(std::addressof(rval))), _ilist, std::forward(_args)...); + using ValueT = std::decay_t; + if constexpr (is_small_type()) { + auto& rval = reinterpret_cast(data_); + return doEmplaceSmall(std::addressof(rval), _ilist, std::forward(_args)...); } else { - return doEmplaceBig>(_ilist, std::forward(_args)...); + return doEmplaceBig(_ilist, std::forward(_args)...); } } diff --git a/solid/utility/memoryfile.hpp b/solid/utility/memoryfile.hpp index 2bcde722f..b26ef1c1d 100644 --- a/solid/utility/memoryfile.hpp +++ b/solid/utility/memoryfile.hpp @@ -68,7 +68,7 @@ class MemoryFile { //! Read data from file ssize_t read(char* _pb, size_t _bl); //! Write data to file - ssize_t write(const char* _pb, uint32_t _bl); + ssize_t write(const char* _pb, size_t _bl); //! Move the file cursor at position int64_t seek(int64_t _pos, SeekRef _ref = SeekBeg); //! Truncate the file diff --git a/solid/utility/src/memoryfile.cpp b/solid/utility/src/memoryfile.cpp index e6dd12191..43b318295 100644 --- a/solid/utility/src/memoryfile.cpp +++ b/solid/utility/src/memoryfile.cpp @@ -85,7 +85,7 @@ ssize_t MemoryFile::read(char* _pb, size_t _bl) return rv; } -ssize_t MemoryFile::write(const char* _pb, uint32_t _bl) +ssize_t MemoryFile::write(const char* _pb, size_t _bl) { ssize_t rv(write(_pb, _bl, off)); if (rv > 0) { diff --git a/solid/utility/src/sharedbuffer.cpp b/solid/utility/src/sharedbuffer.cpp index eb4d80318..7373bc561 100644 --- a/solid/utility/src/sharedbuffer.cpp +++ b/solid/utility/src/sharedbuffer.cpp @@ -310,7 +310,7 @@ struct Stub { uint64_t pack(uint64_t const _index, uint64_t const _unique) { - return _index << 32U + (_unique & 0xffffffffU); + return _index << (32U + (_unique & 0xffffffffU)); } pair unpack(uint64_t const _id) diff --git a/solid/utility/test/test_callpool_multicast_basic.cpp b/solid/utility/test/test_callpool_multicast_basic.cpp index 42750f268..35c5fd60c 100644 --- a/solid/utility/test/test_callpool_multicast_basic.cpp +++ b/solid/utility/test/test_callpool_multicast_basic.cpp @@ -68,7 +68,7 @@ int test_callpool_multicast_basic(int argc, char* argv[]) std::future barrier_future = barrier.get_future(); std::thread all_thr{ - [&cp, cnt](std::promise barrier) { + [&cp](std::promise barrier) { barrier.set_value(); for (uint32_t i = 0; i < cnt; ++i) { if ((i % 10) == 0) { diff --git a/solid/utility/test/test_intrusiveptr.cpp b/solid/utility/test/test_intrusiveptr.cpp index af1f11508..1c91e56cb 100644 --- a/solid/utility/test/test_intrusiveptr.cpp +++ b/solid/utility/test/test_intrusiveptr.cpp @@ -8,8 +8,8 @@ using namespace std; namespace { class Test : public IntrusiveThreadSafeBase { - string s_; - int i_ = 0; + string s_; + [[maybe_unused]] int i_ = 0; public: Test(const string_view _s, const int _i) @@ -42,7 +42,7 @@ struct TestWithCounter { virtual ~TestWithCounter() {} private: - friend class TestIntrusivePolicy; + friend struct TestIntrusivePolicy; mutable atomic use_count_{1}; }; diff --git a/solid/utility/test/test_threadpool_batch.cpp b/solid/utility/test/test_threadpool_batch.cpp index febf1faf8..2b5dab9ee 100644 --- a/solid/utility/test/test_threadpool_batch.cpp +++ b/solid/utility/test/test_threadpool_batch.cpp @@ -152,7 +152,7 @@ int test_threadpool_batch(int argc, char* argv[]) for (size_t j = 0; j < entries.size(); ++j) { auto& entry{entries[j]}; - auto lambda = [&entry, start, j](Context& _rctx) mutable { + auto lambda = [start](Context& _rctx) mutable { const auto now = chrono::steady_clock::now(); const uint64_t duration = chrono::duration_cast(now - start).count(); store_min(_rctx.min_, duration); diff --git a/solid/utility/test/test_threadpool_multicast_basic.cpp b/solid/utility/test/test_threadpool_multicast_basic.cpp index e33555f6d..3cfaa7d15 100644 --- a/solid/utility/test/test_threadpool_multicast_basic.cpp +++ b/solid/utility/test/test_threadpool_multicast_basic.cpp @@ -67,7 +67,7 @@ int test_threadpool_multicast_basic(int argc, char* argv[]) std::future barrier_future = barrier.get_future(); std::thread all_thr{ - [&wp, cnt](std::promise barrier) { + [&wp](std::promise barrier) { barrier.set_value(); for (uint32_t i = 0; i < cnt; ++i) { if ((i % 10) == 0) { diff --git a/solid/utility/test/test_threadpool_multicast_sleep.cpp b/solid/utility/test/test_threadpool_multicast_sleep.cpp index d0164d617..00a8d9536 100644 --- a/solid/utility/test/test_threadpool_multicast_sleep.cpp +++ b/solid/utility/test/test_threadpool_multicast_sleep.cpp @@ -66,7 +66,7 @@ int test_threadpool_multicast_sleep(int argc, char* argv[]) std::future barrier_future = barrier.get_future(); std::thread all_thr{ - [&wp, cnt](std::promise barrier) { + [&wp](std::promise barrier) { barrier.set_value(); for (uint32_t i = 0; i < cnt; ++i) { if ((i % 10) == 0) { diff --git a/solid/utility/test/test_threadpool_thread_context.cpp b/solid/utility/test/test_threadpool_thread_context.cpp index 2fab3be1c..d88536e6a 100644 --- a/solid/utility/test/test_threadpool_thread_context.cpp +++ b/solid/utility/test/test_threadpool_thread_context.cpp @@ -18,7 +18,6 @@ using unique_lock_t = std::unique_lock; namespace { -mutex_t mtx; const LoggerT logger("test"); struct Context { diff --git a/tutorials/aio_echo/aio_echo_server.cpp b/tutorials/aio_echo/aio_echo_server.cpp index 8c85bc81b..dbfd736c8 100644 --- a/tutorials/aio_echo/aio_echo_server.cpp +++ b/tutorials/aio_echo/aio_echo_server.cpp @@ -215,7 +215,7 @@ bool parseArguments(Params& _par, int argc, char* argv[]) void Listener::onAccept(frame::aio::ReactorContext& _rctx, SocketDevice& _rsd) { - unsigned repeatcnt = backlog_size(); + size_t repeatcnt = backlog_size(); do { if (!_rctx.error()) { diff --git a/tutorials/mprpc_echo_relay/mprpc_echo_relay_client.cpp b/tutorials/mprpc_echo_relay/mprpc_echo_relay_client.cpp index e30a8c04c..6e31fc972 100644 --- a/tutorials/mprpc_echo_relay/mprpc_echo_relay_client.cpp +++ b/tutorials/mprpc_echo_relay/mprpc_echo_relay_client.cpp @@ -166,13 +166,13 @@ int main(int argc, char* argv[]) bool parseArguments(Parameters& _par, int argc, char* argv[]) { if (argc == 2) { - _par.group_id = stoul(argv[1]); + _par.group_id = static_cast(stoul(argv[1])); return true; } if (argc == 3) { size_t pos; - _par.group_id = stoul(argv[1]); + _par.group_id = static_cast(stoul(argv[1])); _par.server_addr = argv[2]; From 533c72f81c6304c163f643a9464fabee136396e0 Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Sun, 16 Nov 2025 11:34:52 +0200 Subject: [PATCH 19/56] utility: remove cacheable.hpp --- solid/frame/aio/aioreactor.hpp | 4 +- solid/frame/aio/src/aioreactor.cpp | 1 + solid/frame/common.hpp | 6 +- solid/frame/mprpc/mprpcmessage.hpp | 13 +- .../mprpc/test/test_clientserver_topic.cpp | 50 +--- solid/utility/CMakeLists.txt | 1 - solid/utility/cacheable.hpp | 275 ------------------ 7 files changed, 24 insertions(+), 326 deletions(-) delete mode 100644 solid/utility/cacheable.hpp diff --git a/solid/frame/aio/aioreactor.hpp b/solid/frame/aio/aioreactor.hpp index 51320b599..38411124d 100644 --- a/solid/frame/aio/aioreactor.hpp +++ b/solid/frame/aio/aioreactor.hpp @@ -52,6 +52,7 @@ struct ReactorStatistic : ReactorStatisticBase { std::atomic_uint64_t post_count_; std::atomic_uint64_t post_stop_count_; std::atomic_size_t max_exec_size_; + std::atomic_size_t exec_count_; std::atomic_size_t actor_count_; std::atomic_size_t max_actor_count_; std::atomic_size_t complete_events_total_ns_{0}; @@ -93,6 +94,7 @@ struct ReactorStatistic : ReactorStatisticBase { void execSize(const size_t _sz) { solid_statistic_max(max_exec_size_, _sz); + exec_count_ += _sz; } std::ostream& print(std::ostream& _ros) const override; @@ -233,7 +235,7 @@ class Reactor : public frame::ReactorBase { return ReactorContext(*this, _rcrttime); } - void update(ReactorContext& _rctx, const size_t _completion_handler_index, const size_t _actor_index) const + static void update(ReactorContext& _rctx, const size_t _completion_handler_index, const size_t _actor_index) { _rctx.completion_heandler_index_ = _completion_handler_index; _rctx.actor_index_ = _actor_index; diff --git a/solid/frame/aio/src/aioreactor.cpp b/solid/frame/aio/src/aioreactor.cpp index ba5a870e1..3baafc94c 100644 --- a/solid/frame/aio/src/aioreactor.cpp +++ b/solid/frame/aio/src/aioreactor.cpp @@ -1437,6 +1437,7 @@ std::ostream& ReactorStatistic::print(std::ostream& _ros) const _ros << " post_count = " << post_count_; _ros << " post_stop_count = " << post_stop_count_; _ros << " max_exec_size = " << max_exec_size_; + _ros << " exec_count = " << exec_count_; _ros << " actor_count = " << actor_count_; _ros << " max_actor_count = " << max_actor_count_; _ros << " complete_events_total_ms = " << (complete_events_total_ns_ / 1000000u); diff --git a/solid/frame/common.hpp b/solid/frame/common.hpp index b4822642a..6e0103119 100644 --- a/solid/frame/common.hpp +++ b/solid/frame/common.hpp @@ -18,8 +18,7 @@ #include "solid/utility/common.hpp" #include "solid/utility/function.hpp" -namespace solid { -namespace frame { +namespace solid::frame { using IndexT = uint64_t; using UniqueT = uint32_t; @@ -173,5 +172,4 @@ enum struct ReactorWaitRequestE { Error }; -} // namespace frame -} // namespace solid +} // namespace solid::frame diff --git a/solid/frame/mprpc/mprpcmessage.hpp b/solid/frame/mprpc/mprpcmessage.hpp index ef46b29e8..8a18188ae 100644 --- a/solid/frame/mprpc/mprpcmessage.hpp +++ b/solid/frame/mprpc/mprpcmessage.hpp @@ -16,7 +16,6 @@ #include "solid/system/common.hpp" #include "solid/system/exception.hpp" -#include "solid/utility/cacheable.hpp" #include "solid/utility/function.hpp" #include "solid/utility/typetraits.hpp" @@ -28,9 +27,7 @@ #include "solid/utility/intrusiveptr.hpp" #endif -namespace solid { -namespace frame { -namespace mprpc { +namespace solid::frame::mprpc { class Service; class Connection; @@ -152,9 +149,9 @@ struct MessageHeader { } }; #if defined(SOLID_MPRPC_USE_SHARED_PTR_MESSAGE) -struct Message : SharedCacheable { +struct Message { #else -struct Message : IntrusiveCacheable { +struct Message : IntrusiveThreadSafeBase { #endif using FlagsT = MessageFlagsValueT; @@ -404,6 +401,4 @@ MessagePointerT make_message(Args&&... _args) using MessageCompleteFunctionT = solid_function_t(void( ConnectionContext&, MessagePointerT<>&, MessagePointerT<>&, ErrorConditionT const&)); -} // namespace mprpc -} // namespace frame -} // namespace solid +} // namespace solid::frame::mprpc diff --git a/solid/frame/mprpc/test/test_clientserver_topic.cpp b/solid/frame/mprpc/test/test_clientserver_topic.cpp index 2ef47bf0e..fac1f8fd5 100644 --- a/solid/frame/mprpc/test/test_clientserver_topic.cpp +++ b/solid/frame/mprpc/test/test_clientserver_topic.cpp @@ -180,12 +180,8 @@ struct Response : frame::mprpc::Message { } }; -using CacheableRequestT = EnableCacheable; -using CacheableResponseT = EnableCacheable; -using RequestPointerT = solid::frame::mprpc::MessagePointerT; -using CesponsePointerT = solid::frame::mprpc::MessagePointerT; -using CacheableRequestPointerT = solid::frame::mprpc::MessagePointerT; -using CacheableResponsePointerT = solid::frame::mprpc::MessagePointerT; +using RequestPointerT = solid::frame::mprpc::MessagePointerT; +using ResponsePointerT = solid::frame::mprpc::MessagePointerT; template auto lin_value(T _from, T _to, const size_t _index, const size_t _n) @@ -234,22 +230,22 @@ void server_connection_start(frame::mprpc::ConnectionContext& _rctx) void client_complete_request( frame::mprpc::ConnectionContext& _rctx, - RequestPointerT& _rsent_msg_ptr, CacheableResponsePointerT& _rrecv_msg_ptr, + RequestPointerT& _rsent_msg_ptr, ResponsePointerT& _rrecv_msg_ptr, ErrorConditionT const& _rerror); void client_complete_response( frame::mprpc::ConnectionContext& _rctx, - CacheableResponsePointerT& _rsent_msg_ptr, CacheableResponsePointerT& _rrecv_msg_ptr, + ResponsePointerT& _rsent_msg_ptr, ResponsePointerT& _rrecv_msg_ptr, ErrorConditionT const& _rerror); void server_complete_response( frame::mprpc::ConnectionContext& _rctx, - CacheableResponsePointerT& _rsent_msg_ptr, CacheableResponsePointerT& _rrecv_msg_ptr, + ResponsePointerT& _rsent_msg_ptr, ResponsePointerT& _rrecv_msg_ptr, ErrorConditionT const& /*_rerror*/); void server_complete_request( frame::mprpc::ConnectionContext& _rctx, - CacheableRequestPointerT& _rsent_msg_ptr, CacheableRequestPointerT& _rrecv_msg_ptr, + RequestPointerT& _rsent_msg_ptr, RequestPointerT& _rrecv_msg_ptr, ErrorConditionT const& /*_rerror*/); void multicast_run(CallPoolT& _work_pool); @@ -300,13 +296,6 @@ chrono::microseconds test_duration{chrono::seconds(1) DurationDqT duration_dq; #endif -auto create_message_ptr = [](auto& _rctx, auto& _rmsgptr) { - using PtrT = std::decay_t; - using ElemT = typename PtrT::element_type; - - _rmsgptr = ElemT::create(); -}; - //----------------------------------------------------------------------------- } // namespace @@ -345,10 +334,6 @@ int test_clientserver_topic(int argc, char* argv[]) sch_client.start([]() {set_current_thread_affinity();return true; }, []() {}, 1); sch_server.start([]() { set_current_thread_affinity(); - for(size_t i = 0; i < 2000; ++i){ - auto reply_ptr = frame::mprpc::make_message(); - reply_ptr->cache(); - } return true; }, []() {}, 2); { @@ -376,8 +361,8 @@ int test_clientserver_topic(int argc, char* argv[]) auto proto = frame::mprpc::serialization_v3::create_protocol( reflection::v1::metadata::factory, [&](auto& _rmap) { - _rmap.template registerMessage(1, "Request", server_complete_request, create_message_ptr); - _rmap.template registerMessage(2, "Response", server_complete_response, create_message_ptr); + _rmap.template registerMessage(1, "Request", server_complete_request); + _rmap.template registerMessage(2, "Response", server_complete_response); }); frame::mprpc::Configuration cfg(sch_server, proto); @@ -421,7 +406,7 @@ int test_clientserver_topic(int argc, char* argv[]) reflection::v1::metadata::factory, [&](auto& _rmap) { _rmap.template registerMessage(1, "Request", client_complete_request); - _rmap.template registerMessage(2, "Response", client_complete_response, create_message_ptr); + _rmap.template registerMessage(2, "Response", client_complete_response); }); frame::mprpc::Configuration cfg(sch_client, proto); @@ -589,7 +574,7 @@ void multicast_run(CallPoolT& _work_pool) } void client_complete_response( frame::mprpc::ConnectionContext& _rctx, - CacheableResponsePointerT& _rsent_msg_ptr, CacheableResponsePointerT& _rrecv_msg_ptr, + ResponsePointerT& _rsent_msg_ptr, ResponsePointerT& _rrecv_msg_ptr, ErrorConditionT const& _rerror) { solid_check(false); // should not be called @@ -597,7 +582,7 @@ void client_complete_response( void client_complete_request( frame::mprpc::ConnectionContext& _rctx, - RequestPointerT& _rsent_msg_ptr, CacheableResponsePointerT& _rrecv_msg_ptr, + RequestPointerT& _rsent_msg_ptr, ResponsePointerT& _rrecv_msg_ptr, ErrorConditionT const& _rerror) { solid_dbg(logger, Info, _rctx.recipientId()); @@ -627,8 +612,6 @@ void client_complete_request( ); #endif - cacheable_cache(std::move(_rrecv_msg_ptr)); - _rsent_msg_ptr->time_point_ = now; ++_rsent_msg_ptr->iteration_; @@ -651,18 +634,17 @@ void client_complete_request( void server_complete_response( frame::mprpc::ConnectionContext& _rctx, - CacheableResponsePointerT& _rsent_msg_ptr, CacheableResponsePointerT& _rrecv_msg_ptr, + ResponsePointerT& _rsent_msg_ptr, ResponsePointerT& _rrecv_msg_ptr, ErrorConditionT const& /*_rerror*/) { solid_check(_rsent_msg_ptr); solid_check(!_rrecv_msg_ptr); solid_dbg(logger, Info, _rctx.recipientId() << " done sent message " << _rsent_msg_ptr.get()); - cacheable_cache(std::move(_rsent_msg_ptr)); } void server_complete_request( frame::mprpc::ConnectionContext& _rctx, - CacheableRequestPointerT& _rsent_msg_ptr, CacheableRequestPointerT& _rrecv_msg_ptr, + RequestPointerT& _rsent_msg_ptr, RequestPointerT& _rrecv_msg_ptr, ErrorConditionT const& /*_rerror*/) { solid_check(_rrecv_msg_ptr); @@ -671,12 +653,10 @@ void server_complete_request( solid_dbg(logger, Info, _rctx.recipientId()); auto& topic_ptr = local_worker_context_ptr->topic_vec_[_rrecv_msg_ptr->topic_id_ % local_worker_context_ptr->topic_vec_.size()]; - auto reply_ptr = CacheableResponseT::create(); + auto reply_ptr = frame::mprpc::make_message(); reply_ptr->receive_time_point_ = microseconds_since_epoch(); reply_ptr->header(_rrecv_msg_ptr->header()); - // cacheable_cache(std::move(_rrecv_msg_ptr)); - auto lambda = [topic_ptr, _rrecv_msg_ptr = std::move(_rrecv_msg_ptr), &service = _rctx.service(), recipient_id = _rctx.recipientId(), reply_ptr = std::move(reply_ptr)]() { ++topic_ptr->value_; @@ -685,8 +665,6 @@ void server_complete_request( reply_ptr->topic_context_ = local_thread_pool_context_ptr->value_; reply_ptr->time_point_ = microseconds_since_epoch(); - reply_ptr->cacheableAttach(std::move(_rrecv_msg_ptr)); - service.sendResponse(recipient_id, reply_ptr); }; diff --git a/solid/utility/CMakeLists.txt b/solid/utility/CMakeLists.txt index b09dc9209..ec09977cb 100644 --- a/solid/utility/CMakeLists.txt +++ b/solid/utility/CMakeLists.txt @@ -27,7 +27,6 @@ set(Headers super.hpp sharedbuffer.hpp threadpool.hpp - cacheable.hpp cast.hpp intrusiveptr.hpp collapse.hpp diff --git a/solid/utility/cacheable.hpp b/solid/utility/cacheable.hpp deleted file mode 100644 index e3a9e97f0..000000000 --- a/solid/utility/cacheable.hpp +++ /dev/null @@ -1,275 +0,0 @@ -// solid/utility/cacheable.hpp -// -// Copyright (c) 2023 Valentin Palade (vipalade @ gmail . com) -// -// This file is part of SolidFrame framework. -// -// Distributed under the Boost Software License, Version 1.0. -// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt. -// - -#include "solid/system/exception.hpp" -#include "solid/utility/cast.hpp" -#include "solid/utility/intrusiveptr.hpp" -#include "solid/utility/stack.hpp" - -namespace solid { - -class Cacheable { -protected: - virtual void doCache() {} - virtual void cacheableClear() {} - -public: - virtual ~Cacheable() = default; -}; - -class SharedCacheable : public Cacheable, public std::enable_shared_from_this { - - template - friend class EnableCacheable; - - std::shared_ptr next_; - - void doAttach(std::shared_ptr&& _other) - { - if (_other) { - _other->next_ = std::move(next_); - next_ = std::move(_other); - } - } - -public: - void cache() - { - auto next = std::move(next_); - cacheableClear(); - doCache(); - while (next) { - auto tmp = std::move(next->next_); - next->cacheableClear(); - next->doCache(); - std::swap(next, tmp); - } - } - - template - void cacheableAttach(const std::shared_ptr& _other) - { - doAttach(std::static_pointer_cast(_other)); - } - - template - void cacheableAttach(std::shared_ptr&& _other) - { - doAttach(std::static_pointer_cast(std::move(_other))); - } -}; - -class IntrusiveCacheable : public Cacheable, public IntrusiveThreadSafeBase { - - template - friend class EnableCacheable; - - IntrusivePtr next_; - - void doAttach(IntrusivePtr&& _other) - { - if (_other) { - _other->next_ = std::move(next_); - next_ = std::move(_other); - } - } - - IntrusivePtr doDetach() - { - IntrusivePtr ptr = std::move(next_); - if (ptr) { - next_ = std::move(ptr->next_); - } - return ptr; - } - -public: - void cache() - { - auto next = std::move(next_); - cacheableClear(); - doCache(); - while (next) { - auto tmp = std::move(next->next_); - next->cacheableClear(); - next->doCache(); - std::swap(next, tmp); - } - } - - template - void cacheableAttach(const IntrusivePtr& _other) - { - doAttach(static_pointer_cast(_other)); - } - - template - void cacheableAttach(IntrusivePtr&& _other) - { - doAttach(static_pointer_cast(std::move(_other))); - } - - template - IntrusivePtr cacheableDetachAs() - { - return static_pointer_cast(doDetach()); - } - - template - IntrusivePtr cacheableDetachAllAs() - { - return static_pointer_cast(std::move(next_)); - } - - ~IntrusiveCacheable() override - { - auto next = std::move(next_); - while (next) { - auto tmp = std::move(next->next_); - assert(not next->next_); - assert(next.useCount() == 1U); - next.reset(); - next = std::move(tmp); - } - } -}; - -#ifdef __cpp_concepts -template -concept SharedCacheableDerived = std::is_base_of_v; - -template -#else -template -#endif -void cacheable_cache(std::shared_ptr&& _what_ptr) -{ - if (_what_ptr) [[likely]] { - _what_ptr->cache(); - _what_ptr.reset(); - } -} - -#ifdef __cpp_concepts -template -concept IntrusiveCacheableDerived = std::is_base_of_v; - -template -#else -template -#endif -void cacheable_cache(IntrusivePtr&& _what_ptr) -{ - if (_what_ptr) [[likely]] { - _what_ptr->cache(); - _what_ptr.reset(); - } -} - -class ThreadLocalCache; - -template -class EnableCacheable : public What { - using ThisT = EnableCacheable; - -public: - static auto create() - { - if constexpr (std::is_base_of_v) { - auto ret = static_pointer_cast(Cache::template load_ip()); - if (!ret) [[unlikely]] { - ret = make_intrusive(); - } - return ret; - } else { - static_assert(std::is_base_of_v, "Type must be derived from SharedCacheable"); - auto p{Cache::template load_sp()}; - auto ret = std::static_pointer_cast(std::move(p)); - if (!ret) [[unlikely]] { - ret = std::make_shared(); - } - return ret; - } - } - - template - EnableCacheable(Args&&... _args) - : What(std::forward(_args)...) - { - } - -private: - void doCache() override - { - if constexpr (std::is_base_of_v) { - Cache::store(IntrusivePtr(static_cast(this), true)); - } else { - static_assert(std::is_base_of_v, "Type must be derived from SharedCacheable"); - Cache::store(std::static_pointer_cast(this->shared_from_this())); - } - } -}; - -class ThreadLocalCache { - template - static auto& local_stack_sp() - { - static thread_local Stack> stack; - return stack; - } - - template - static auto& local_stack_ip() - { - static thread_local Stack> stack; - return stack; - } - -public: - template - static void store(std::shared_ptr&& _what) - { - local_stack_sp().push(std::move(_what)); - } - - template - static void store(IntrusivePtr&& _what) - { - local_stack_ip().push(std::move(_what)); - } - - template - static auto load_sp() - { - auto& ls = local_stack_sp(); - if (!ls.empty()) { - auto ret = std::move(ls.top()); - ls.pop(); - return ret; - } else { - return std::shared_ptr{}; - } - } - - template - static auto load_ip() - { - auto& ls = local_stack_ip(); - if (!ls.empty()) { - auto ret = std::move(ls.top()); - ls.pop(); - return ret; - } else { - return IntrusivePtr{}; - } - } -}; - -} // namespace solid From 402bfaa651a640fd3b010b51ff18484a175ff544 Mon Sep 17 00:00:00 2001 From: Valentin Palade Date: Tue, 18 Nov 2025 22:12:50 +0200 Subject: [PATCH 20/56] modernize function&event&any + function static_assert on big objects --- CMakeLists.txt | 1 - configure | 2 - .../aio_echo/example_echo_auto_client.cpp | 2 +- .../frame/mprpc_echo/example_mprpc_echo.cpp | 2 +- solid/frame/aio/aioreactor.hpp | 2 +- solid/frame/aio/aiostream.hpp | 4 +- solid/frame/aio/aiotimer.hpp | 3 +- solid/frame/aio/test/test_echo_tcp_stress.cpp | 2 +- solid/frame/mprpc/mprpcconfiguration.hpp | 2 +- solid/frame/mprpc/mprpcmessage.hpp | 20 +---- .../mprpc/mprpcprotocol_serialization_v3.hpp | 10 +-- solid/frame/mprpc/mprpcservice.hpp | 3 +- solid/frame/mprpc/mprpcsocketstub_openssl.hpp | 16 ++-- solid/frame/mprpc/src/mprpcservice.cpp | 3 +- .../alpha/client/alphaclient.cpp | 2 +- .../beta/client/betaclient.cpp | 2 +- .../gamma/client/gammaclient.cpp | 2 +- .../test/test_clientfrontback_download.cpp | 6 +- .../test/test_clientfrontback_upload.cpp | 6 +- .../mprpc/test/test_clientserver_basic.cpp | 4 +- .../test/test_clientserver_cancel_client.cpp | 4 +- .../test/test_clientserver_cancel_server.cpp | 4 +- .../mprpc/test/test_clientserver_delayed.cpp | 4 +- .../mprpc/test/test_clientserver_download.cpp | 4 +- .../test/test_clientserver_idempotent.cpp | 4 +- .../mprpc/test/test_clientserver_noserver.cpp | 4 +- .../mprpc/test/test_clientserver_oneshot.cpp | 4 +- .../test/test_clientserver_pause_read.cpp | 4 +- .../test/test_clientserver_sendrequest.cpp | 4 +- .../mprpc/test/test_clientserver_split.cpp | 4 +- .../mprpc/test/test_clientserver_stop.cpp | 4 +- .../test/test_clientserver_timeout_secure.cpp | 2 +- .../mprpc/test/test_clientserver_topic.cpp | 2 +- .../mprpc/test/test_clientserver_upload.cpp | 4 +- .../test/test_clientserver_upload_single.cpp | 4 +- .../test/test_clientserver_versioning.cpp | 10 +-- .../mprpc/test/test_connection_close.cpp | 4 +- .../frame/mprpc/test/test_keepalive_fail.cpp | 4 +- .../mprpc/test/test_keepalive_success.cpp | 4 +- .../mprpc/test/test_multiprotocol_basic.cpp | 2 +- solid/frame/mprpc/test/test_pool_basic.cpp | 4 +- .../mprpc/test/test_pool_delay_close.cpp | 4 +- .../mprpc/test/test_pool_force_close.cpp | 4 +- solid/frame/mprpc/test/test_raw_basic.cpp | 4 +- solid/frame/mprpc/test/test_raw_proxy.cpp | 4 +- solid/frame/mprpc/test/test_relay_basic.cpp | 6 +- .../mprpc/test/test_relay_cancel_request.cpp | 6 +- .../mprpc/test/test_relay_cancel_response.cpp | 6 +- .../mprpc/test/test_relay_close_request.cpp | 6 +- .../mprpc/test/test_relay_close_response.cpp | 6 +- .../mprpc/test/test_relay_detect_close.cpp | 6 +- ...test_relay_detect_close_while_response.cpp | 6 +- .../frame/mprpc/test/test_relay_disabled.cpp | 6 +- solid/frame/mprpc/test/test_relay_split.cpp | 6 +- solid/frame/sharedstore.hpp | 4 +- solid/serialization/v3/binarydeserializer.hpp | 2 +- solid/system/configuration_impl.hpp.in | 4 +- solid/utility/any.hpp | 38 ++++----- solid/utility/event.hpp | 75 +++++++++-------- solid/utility/function.hpp | 83 +++++++++++-------- solid/utility/intrusiveptr.hpp | 9 +- solid/utility/test/test_collapse.cpp | 2 +- solid/utility/test/test_function.cpp | 27 ++++-- solid/utility/test/test_function_perf.cpp | 7 +- solid/utility/typetraits.hpp | 7 +- tutorials/mprpc_echo/mprpc_echo_client.cpp | 4 +- .../mprpc_echo/mprpc_echo_client_pool.cpp | 4 +- .../mprpc_echo_relay_client.cpp | 4 +- tutorials/mprpc_file/mprpc_file_client.cpp | 4 +- .../mprpc_request/mprpc_request_client.cpp | 4 +- .../mprpc_request_client.cpp | 4 +- 71 files changed, 263 insertions(+), 267 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 63e232185..e2ac9ec9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,7 +156,6 @@ set(SYSTEM_BASIC_LIBRARIES "") option(SOLID_FRAME_AIO_REACTOR_USE_SPINLOCK "Use SpinLock on AIO Reactor" ON) -option(SOLID_MPRPC_USE_SHARED_PTR_MESSAGE "Use std::shared_ptr with mprpc::Message" OFF) #----------------------------------------------------------------- # Per OS configuration diff --git a/configure b/configure index c3b0c9207..827d3566e 100755 --- a/configure +++ b/configure @@ -76,8 +76,6 @@ print_usage(){ echo "7) create a debug Ninja build for C++17" echo "./configure -b debug -e ../external -f debug -g Ninja -P \"-DCMAKE_CXX_STANDARD=17\"" echo - echo "8) create release build with using std::shared_ptr for solid::frame::mprpc::Message" - echo "./configure -f release_sp -e ../external/ -g Ninja -P \"-DSOLID_MPRPC_USE_SHARED_PTR_MESSAGE=on\"" echo exit } diff --git a/examples/frame/aio_echo/example_echo_auto_client.cpp b/examples/frame/aio_echo/example_echo_auto_client.cpp index 062ea9fd5..b818381d3 100644 --- a/examples/frame/aio_echo/example_echo_auto_client.cpp +++ b/examples/frame/aio_echo/example_echo_auto_client.cpp @@ -110,7 +110,7 @@ frame::aio::Resolver& async_resolver(frame::aio::Resolver* _pres = nullptr) return r; } -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; } // namespace diff --git a/examples/frame/mprpc_echo/example_mprpc_echo.cpp b/examples/frame/mprpc_echo/example_mprpc_echo.cpp index cc1994abe..f712fc934 100644 --- a/examples/frame/mprpc_echo/example_mprpc_echo.cpp +++ b/examples/frame/mprpc_echo/example_mprpc_echo.cpp @@ -243,7 +243,7 @@ bool restart( } if (params.connectstringvec.size()) { - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(_resolver, params.baseport.c_str()); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(_resolver, params.baseport.c_str())); } cfg.connection_stop_fnc = &connection_stop; cfg.server.connection_start_fnc = &incoming_connection_start; diff --git a/solid/frame/aio/aioreactor.hpp b/solid/frame/aio/aioreactor.hpp index 38411124d..e693562c3 100644 --- a/solid/frame/aio/aioreactor.hpp +++ b/solid/frame/aio/aioreactor.hpp @@ -137,7 +137,7 @@ class Reactor : public frame::ReactorBase { public: using StatisticT = ReactorStatistic; - using EventFunctionT = solid::Function; + using EventFunctionT = solid::Function128T; bool start(); void stop() override; diff --git a/solid/frame/aio/aiostream.hpp b/solid/frame/aio/aiostream.hpp index e333cbe4a..7ddf3d8ea 100644 --- a/solid/frame/aio/aiostream.hpp +++ b/solid/frame/aio/aiostream.hpp @@ -26,8 +26,8 @@ class ReactorContext; template class Stream : public CompletionHandler { using ThisT = Stream; - using RecvFunctionT = solid_function_t(void(ThisT&, ReactorContext&)); - using SendFunctionT = solid_function_t(void(ThisT&, ReactorContext&)); + using RecvFunctionT = solid::Function128T; + using SendFunctionT = solid::Function128T; static void on_init_completion(CompletionHandler& _rch, ReactorContext& _rctx) { diff --git a/solid/frame/aio/aiotimer.hpp b/solid/frame/aio/aiotimer.hpp index e815b726d..dd9d9dafd 100644 --- a/solid/frame/aio/aiotimer.hpp +++ b/solid/frame/aio/aiotimer.hpp @@ -16,6 +16,7 @@ #include "aiocompletion.hpp" #include "aioerror.hpp" #include "aioreactorcontext.hpp" +#include "solid/utility/function.hpp" namespace solid { namespace frame { @@ -54,7 +55,7 @@ class SteadyTimer : public CompletionHandler { { } - typedef solid_function_t(void(ReactorContext&)) FunctionT; + using FunctionT = solid::Function96T; FunctionT function_; size_t storeidx_; diff --git a/solid/frame/aio/test/test_echo_tcp_stress.cpp b/solid/frame/aio/test/test_echo_tcp_stress.cpp index 4a01e71c9..91de9aca1 100644 --- a/solid/frame/aio/test/test_echo_tcp_stress.cpp +++ b/solid/frame/aio/test/test_echo_tcp_stress.cpp @@ -37,7 +37,7 @@ namespace { using AioSchedulerT = frame::Scheduler; using AtomicSizeT = atomic; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; bool running = true; mutex mtx; diff --git a/solid/frame/mprpc/mprpcconfiguration.hpp b/solid/frame/mprpc/mprpcconfiguration.hpp index 71d1eee6d..244366f6b 100644 --- a/solid/frame/mprpc/mprpcconfiguration.hpp +++ b/solid/frame/mprpc/mprpcconfiguration.hpp @@ -267,7 +267,7 @@ class RelayEngine { using AddressVectorT = std::vector; using ServerSetupSocketDeviceFunctionT = solid_function_t(bool(SocketDevice&)); using ClientSetupSocketDeviceFunctionT = solid_function_t(bool(SocketDevice&)); -using ResolveCompleteFunctionT = solid_function_t(void(AddressVectorT&&)); +using ResolveCompleteFunctionT = solid::Function; using ConnectionStopFunctionT = solid_function_t(void(ConnectionContext&)); using ConnectionStartFunctionT = solid_function_t(void(ConnectionContext&)); using SendAllocateBufferFunctionT = solid_function_t(MutableSharedBuffer(const uint32_t)); diff --git a/solid/frame/mprpc/mprpcmessage.hpp b/solid/frame/mprpc/mprpcmessage.hpp index 8a18188ae..2cb274873 100644 --- a/solid/frame/mprpc/mprpcmessage.hpp +++ b/solid/frame/mprpc/mprpcmessage.hpp @@ -23,9 +23,7 @@ #include "solid/frame/mprpc/mprpcmessageflags.hpp" #include "solid/reflection/v1/reflection.hpp" -#if !defined(SOLID_MPRPC_USE_SHARED_PTR_MESSAGE) #include "solid/utility/intrusiveptr.hpp" -#endif namespace solid::frame::mprpc { @@ -148,11 +146,8 @@ struct MessageHeader { } } }; -#if defined(SOLID_MPRPC_USE_SHARED_PTR_MESSAGE) -struct Message { -#else + struct Message : IntrusiveThreadSafeBase { -#endif using FlagsT = MessageFlagsValueT; @@ -376,17 +371,6 @@ struct Message : IntrusiveThreadSafeBase { MessageHeader header_; }; -#if defined(SOLID_MPRPC_USE_SHARED_PTR_MESSAGE) -template -using MessagePointerT = std::shared_ptr; - -template -MessagePointerT make_message(Args&&... _args) -{ - return std::make_shared(std::forward(_args)...); -} - -#else template using MessagePointerT = IntrusivePtr; @@ -396,8 +380,6 @@ MessagePointerT make_message(Args&&... _args) return make_intrusive(std::forward(_args)...); } -#endif - using MessageCompleteFunctionT = solid_function_t(void( ConnectionContext&, MessagePointerT<>&, MessagePointerT<>&, ErrorConditionT const&)); diff --git a/solid/frame/mprpc/mprpcprotocol_serialization_v3.hpp b/solid/frame/mprpc/mprpcprotocol_serialization_v3.hpp index ea8fad5ea..f43c602bb 100644 --- a/solid/frame/mprpc/mprpcprotocol_serialization_v3.hpp +++ b/solid/frame/mprpc/mprpcprotocol_serialization_v3.hpp @@ -219,11 +219,8 @@ class Protocol : public mprpc::Protocol { auto create_lambda = [](auto& _rctx, auto& _rptr) { using PtrType = std::decay_t; using CtxType = std::decay_t; -#if defined(SOLID_MPRPC_USE_SHARED_PTR_MESSAGE) - if constexpr (solid::is_shared_ptr_v) { -#else + if constexpr (solid::is_intrusive_ptr_v) { -#endif _rptr = make_message(); if constexpr (std::is_same_v) { _rptr->header(_rctx); @@ -251,11 +248,8 @@ class Protocol : public mprpc::Protocol { auto create_lambda = [_create_fnc](auto& _rctx, auto& _rptr) { using PtrType = std::decay_t; using CtxType = std::decay_t; -#if defined(SOLID_MPRPC_USE_SHARED_PTR_MESSAGE) - if constexpr (solid::is_shared_ptr_v) { -#else + if constexpr (solid::is_intrusive_ptr_v) { -#endif _create_fnc(_rctx, _rptr); if constexpr (std::is_same_v) { diff --git a/solid/frame/mprpc/mprpcservice.hpp b/solid/frame/mprpc/mprpcservice.hpp index f1f997da2..88ba7bd62 100644 --- a/solid/frame/mprpc/mprpcservice.hpp +++ b/solid/frame/mprpc/mprpcservice.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "solid/system/exception.hpp" #include "solid/system/statistic.hpp" @@ -967,7 +968,7 @@ ErrorConditionT Service::connectionNotifyRecvSomeRawData( RecipientId const& _rrecipient_id, CompleteFnc _complete_fnc) { - ConnectionRecvRawDataCompleteFunctionT complete_fnc(std::move(_complete_fnc)); + ConnectionRecvRawDataCompleteFunctionT complete_fnc(std::move(_complete_fnc), std::false_type{}); return doConnectionNotifyRecvRawData(_rrecipient_id, std::move(complete_fnc)); } //------------------------------------------------------------------------- diff --git a/solid/frame/mprpc/mprpcsocketstub_openssl.hpp b/solid/frame/mprpc/mprpcsocketstub_openssl.hpp index 2114b8cc0..da2e1bfb0 100644 --- a/solid/frame/mprpc/mprpcsocketstub_openssl.hpp +++ b/solid/frame/mprpc/mprpcsocketstub_openssl.hpp @@ -33,10 +33,10 @@ namespace solid::frame::mprpc::openssl { using ContextT = frame::aio::openssl::Context; using StreamSocketT = frame::aio::Stream; -using ConnectionPrepareServerFunctionT = solid_function_t(unsigned long(frame::aio::ReactorContext&, ConnectionContext&, StreamSocketT&, ErrorConditionT&)); -using ConnectionPrepareClientFunctionT = solid_function_t(unsigned long(frame::aio::ReactorContext&, ConnectionContext&, StreamSocketT&, ErrorConditionT&)); -using ConnectionServerVerifyFunctionT = solid_function_t(bool(frame::aio::ReactorContext&, ConnectionContext&, StreamSocketT&, bool, frame::aio::openssl::VerifyContext&)); -using ConnectionClientVerifyFunctionT = solid_function_t(bool(frame::aio::ReactorContext&, ConnectionContext&, StreamSocketT&, bool, frame::aio::openssl::VerifyContext&)); +using ConnectionPrepareServerFunctionT = solid_function_t(unsigned long(frame::aio::ReactorContext&, ConnectionContext&, StreamSocketT&, ErrorConditionT&), 64); +using ConnectionPrepareClientFunctionT = solid_function_t(unsigned long(frame::aio::ReactorContext&, ConnectionContext&, StreamSocketT&, ErrorConditionT&), 64); +using ConnectionServerVerifyFunctionT = solid_function_t(bool(frame::aio::ReactorContext&, ConnectionContext&, StreamSocketT&, bool, frame::aio::openssl::VerifyContext&), 64); +using ConnectionClientVerifyFunctionT = solid_function_t(bool(frame::aio::ReactorContext&, ConnectionContext&, StreamSocketT&, bool, frame::aio::openssl::VerifyContext&), 64); struct ClientConfiguration { ClientConfiguration() @@ -332,8 +332,8 @@ inline void setup_client( _ctx_fnc(rsecure_cfg.context); - rsecure_cfg.connection_prepare_secure_fnc = std::move(_start_fnc); - rsecure_cfg.connection_verify_fnc = std::move(_verify_fnc); + rsecure_cfg.connection_prepare_secure_fnc.emplace(std::move(_start_fnc)); + rsecure_cfg.connection_verify_fnc.emplace(std::move(_verify_fnc)); } template #include #include +#include #include #include #include @@ -2425,7 +2426,7 @@ bool Service::Data::doTryCreateNewConnectionForPool(Service& _rsvc, const size_t if (rpool.connect_addr_vec_.empty()) { - ResolveCompleteFunctionT cbk(OnRelsolveF(_rsvc.manager(), conuid, Connection::eventResolve())); + ResolveCompleteFunctionT cbk(OnRelsolveF(_rsvc.manager(), conuid, Connection::eventResolve()), std::false_type{}); config_.client.name_resolve_fnc(rpool.name_, cbk); diff --git a/solid/frame/mprpc/test/multiprotocol_basic/alpha/client/alphaclient.cpp b/solid/frame/mprpc/test/multiprotocol_basic/alpha/client/alphaclient.cpp index 2707a2179..2af5da392 100644 --- a/solid/frame/mprpc/test/multiprotocol_basic/alpha/client/alphaclient.cpp +++ b/solid/frame/mprpc/test/multiprotocol_basic/alpha/client/alphaclient.cpp @@ -131,7 +131,7 @@ ErrorConditionT start( cfg.pool_max_active_connection_count = _rctx.max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(_rctx.rresolver, _rctx.rserver_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(_rctx.rresolver, _rctx.rserver_port.c_str() /*, SocketInfo::Inet4*/)); mprpcclient_ptr = make_shared(_rctx.rm); mprpcclient_ptr->start(std::move(cfg)); diff --git a/solid/frame/mprpc/test/multiprotocol_basic/beta/client/betaclient.cpp b/solid/frame/mprpc/test/multiprotocol_basic/beta/client/betaclient.cpp index 81c38a4b4..df44ced41 100644 --- a/solid/frame/mprpc/test/multiprotocol_basic/beta/client/betaclient.cpp +++ b/solid/frame/mprpc/test/multiprotocol_basic/beta/client/betaclient.cpp @@ -126,7 +126,7 @@ ErrorConditionT start( cfg.pool_max_active_connection_count = _rctx.max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(_rctx.rresolver, _rctx.rserver_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(_rctx.rresolver, _rctx.rserver_port.c_str() /*, SocketInfo::Inet4*/)); mprpcclient_ptr = make_shared(_rctx.rm); mprpcclient_ptr->start(std::move(cfg)); diff --git a/solid/frame/mprpc/test/multiprotocol_basic/gamma/client/gammaclient.cpp b/solid/frame/mprpc/test/multiprotocol_basic/gamma/client/gammaclient.cpp index 00817e33e..d8e16832c 100644 --- a/solid/frame/mprpc/test/multiprotocol_basic/gamma/client/gammaclient.cpp +++ b/solid/frame/mprpc/test/multiprotocol_basic/gamma/client/gammaclient.cpp @@ -80,7 +80,7 @@ ErrorConditionT start( cfg.pool_max_active_connection_count = _rctx.max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(_rctx.rresolver, _rctx.rserver_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(_rctx.rresolver, _rctx.rserver_port.c_str() /*, SocketInfo::Inet4*/)); mprpcclient_ptr = std::make_shared(_rctx.rm); mprpcclient_ptr->start(std::move(cfg)); diff --git a/solid/frame/mprpc/test/test_clientfrontback_download.cpp b/solid/frame/mprpc/test/test_clientfrontback_download.cpp index 1bc1bd7b4..28bbcc119 100644 --- a/solid/frame/mprpc/test/test_clientfrontback_download.cpp +++ b/solid/frame/mprpc/test/test_clientfrontback_download.cpp @@ -35,7 +35,7 @@ using namespace solid; namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; LoggerT logger("test"); @@ -419,7 +419,7 @@ int test_clientfrontback_download(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, back_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, back_port.c_str() /*, SocketInfo::Inet4*/)); cfg.client.connection_start_state = frame::mprpc::ConnectionState::Active; if (secure) { @@ -499,7 +499,7 @@ int test_clientfrontback_download(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, front_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, front_port.c_str() /*, SocketInfo::Inet4*/)); cfg.client.connection_start_state = frame::mprpc::ConnectionState::Active; if (secure) { diff --git a/solid/frame/mprpc/test/test_clientfrontback_upload.cpp b/solid/frame/mprpc/test/test_clientfrontback_upload.cpp index c5ca7c38d..ee882ca3c 100644 --- a/solid/frame/mprpc/test/test_clientfrontback_upload.cpp +++ b/solid/frame/mprpc/test/test_clientfrontback_upload.cpp @@ -43,7 +43,7 @@ frame::mprpc::ServiceT* pmprpc_front_server = nullptr; atomic expect_count(0); promise prom; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; namespace back { struct Request; @@ -411,7 +411,7 @@ int test_clientfrontback_upload(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, back_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, back_port.c_str() /*, SocketInfo::Inet4*/)); cfg.client.connection_start_state = frame::mprpc::ConnectionState::Active; if (secure) { @@ -490,7 +490,7 @@ int test_clientfrontback_upload(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, front_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, front_port.c_str() /*, SocketInfo::Inet4*/)); cfg.client.connection_start_state = frame::mprpc::ConnectionState::Active; if (secure) { diff --git a/solid/frame/mprpc/test/test_clientserver_basic.cpp b/solid/frame/mprpc/test/test_clientserver_basic.cpp index 3841c9b21..19590f069 100644 --- a/solid/frame/mprpc/test/test_clientserver_basic.cpp +++ b/solid/frame/mprpc/test/test_clientserver_basic.cpp @@ -39,7 +39,7 @@ struct InitStub { frame::mprpc::MessageFlagsT flags; }; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; InitStub initarray[] = { {100000, 0}, @@ -396,7 +396,7 @@ int test_clientserver_basic(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF{resolver, server_port}; + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF{resolver, server_port}); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_clientserver_cancel_client.cpp b/solid/frame/mprpc/test/test_clientserver_cancel_client.cpp index a0827eba8..64d21cad2 100644 --- a/solid/frame/mprpc/test/test_clientserver_cancel_client.cpp +++ b/solid/frame/mprpc/test/test_clientserver_cancel_client.cpp @@ -44,7 +44,7 @@ struct InitStub { frame::mprpc::MessageFlagsT flags; }; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; // NOTE: if making more messages non-cancelable, please consider to change the value of expected_transfered_count @@ -381,7 +381,7 @@ int test_clientserver_cancel_client(int argc, char* argv[]) cfg.writer.max_message_count_multiplex = 6; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_clientserver_cancel_server.cpp b/solid/frame/mprpc/test/test_clientserver_cancel_server.cpp index aee316848..eff7b6dc3 100644 --- a/solid/frame/mprpc/test/test_clientserver_cancel_server.cpp +++ b/solid/frame/mprpc/test/test_clientserver_cancel_server.cpp @@ -38,7 +38,7 @@ using SecureContextT = frame::aio::openssl::Context; namespace { -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -393,7 +393,7 @@ int test_clientserver_cancel_server(int argc, char* argv[]) cfg.writer.max_message_count_multiplex = 6; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_clientserver_delayed.cpp b/solid/frame/mprpc/test/test_clientserver_delayed.cpp index 736c2c33c..5d49fb6df 100644 --- a/solid/frame/mprpc/test/test_clientserver_delayed.cpp +++ b/solid/frame/mprpc/test/test_clientserver_delayed.cpp @@ -32,7 +32,7 @@ using AioSchedulerT = frame::Scheduler, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -333,7 +333,7 @@ int test_clientserver_delayed(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_clientserver_download.cpp b/solid/frame/mprpc/test/test_clientserver_download.cpp index 90a8dd2e9..ef02edde8 100644 --- a/solid/frame/mprpc/test/test_clientserver_download.cpp +++ b/solid/frame/mprpc/test/test_clientserver_download.cpp @@ -41,7 +41,7 @@ using SecureContextT = frame::aio::openssl::Context; namespace { LoggerT logger("test"); -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; atomic expect_count(0); promise prom; @@ -296,7 +296,7 @@ int test_clientserver_download(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/)); cfg.client.connection_start_state = frame::mprpc::ConnectionState::Active; if (secure) { diff --git a/solid/frame/mprpc/test/test_clientserver_idempotent.cpp b/solid/frame/mprpc/test/test_clientserver_idempotent.cpp index b8762b17e..452c6213f 100644 --- a/solid/frame/mprpc/test/test_clientserver_idempotent.cpp +++ b/solid/frame/mprpc/test/test_clientserver_idempotent.cpp @@ -33,7 +33,7 @@ using AioSchedulerT = frame::Scheduler, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -389,7 +389,7 @@ int test_clientserver_idempotent(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port.c_str(), "localhost", SocketInfo::Inet4); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port.c_str(), "localhost", SocketInfo::Inet4)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_clientserver_noserver.cpp b/solid/frame/mprpc/test/test_clientserver_noserver.cpp index 7d9a6d8ca..0b22b1785 100644 --- a/solid/frame/mprpc/test/test_clientserver_noserver.cpp +++ b/solid/frame/mprpc/test/test_clientserver_noserver.cpp @@ -33,7 +33,7 @@ using SecureContextT = frame::aio::openssl::Context; namespace { -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -245,7 +245,7 @@ int test_clientserver_noserver(int argc, char* argv[]) cfg.client.connection_start_state = frame::mprpc::ConnectionState::Active; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_clientserver_oneshot.cpp b/solid/frame/mprpc/test/test_clientserver_oneshot.cpp index cc4e32910..311c87b99 100644 --- a/solid/frame/mprpc/test/test_clientserver_oneshot.cpp +++ b/solid/frame/mprpc/test/test_clientserver_oneshot.cpp @@ -32,7 +32,7 @@ namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -247,7 +247,7 @@ int test_clientserver_oneshot(int argc, char* argv[]) cfg.client.connection_start_state = frame::mprpc::ConnectionState::Active; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_clientserver_pause_read.cpp b/solid/frame/mprpc/test/test_clientserver_pause_read.cpp index 993e42b19..665819159 100644 --- a/solid/frame/mprpc/test/test_clientserver_pause_read.cpp +++ b/solid/frame/mprpc/test/test_clientserver_pause_read.cpp @@ -39,7 +39,7 @@ struct InitStub { frame::mprpc::MessageFlagsT flags; }; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; InitStub initarray[] = { {100000, 0}, @@ -397,7 +397,7 @@ int test_clientserver_pause_read(int argc, char* argv[]) cfg.pool_max_active_connection_count = 1; // NOTE: currently the test only works with one connection per pool - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF{resolver, server_port}; + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF{resolver, server_port}); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_clientserver_sendrequest.cpp b/solid/frame/mprpc/test/test_clientserver_sendrequest.cpp index 34bcfcc6a..f1509143a 100644 --- a/solid/frame/mprpc/test/test_clientserver_sendrequest.cpp +++ b/solid/frame/mprpc/test/test_clientserver_sendrequest.cpp @@ -32,7 +32,7 @@ namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -456,7 +456,7 @@ int test_clientserver_sendrequest(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_clientserver_split.cpp b/solid/frame/mprpc/test/test_clientserver_split.cpp index 9db5616c9..3cd701526 100644 --- a/solid/frame/mprpc/test/test_clientserver_split.cpp +++ b/solid/frame/mprpc/test/test_clientserver_split.cpp @@ -33,7 +33,7 @@ namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -426,7 +426,7 @@ int test_clientserver_split(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_clientserver_stop.cpp b/solid/frame/mprpc/test/test_clientserver_stop.cpp index 98f0497df..fba6d2749 100644 --- a/solid/frame/mprpc/test/test_clientserver_stop.cpp +++ b/solid/frame/mprpc/test/test_clientserver_stop.cpp @@ -78,7 +78,7 @@ struct InitStub { frame::mprpc::MessageFlagsT flags; }; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; InitStub initarray[] = { {100000, 0}, @@ -440,7 +440,7 @@ int test_clientserver_stop(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF{resolver, server_port}; + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF{resolver, server_port}); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_clientserver_timeout_secure.cpp b/solid/frame/mprpc/test/test_clientserver_timeout_secure.cpp index 10307fbb7..fe68c41c2 100644 --- a/solid/frame/mprpc/test/test_clientserver_timeout_secure.cpp +++ b/solid/frame/mprpc/test/test_clientserver_timeout_secure.cpp @@ -35,7 +35,7 @@ using namespace std::chrono_literals; namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; atomic wait_count{0}; bool running = true; diff --git a/solid/frame/mprpc/test/test_clientserver_topic.cpp b/solid/frame/mprpc/test/test_clientserver_topic.cpp index fac1f8fd5..4d12532d0 100644 --- a/solid/frame/mprpc/test/test_clientserver_topic.cpp +++ b/solid/frame/mprpc/test/test_clientserver_topic.cpp @@ -417,7 +417,7 @@ int test_clientserver_topic(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; cfg.pool_max_message_queue_size = message_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF{resolver, server_port}; + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF{resolver, server_port}); if (secure) { solid_dbg(logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_clientserver_upload.cpp b/solid/frame/mprpc/test/test_clientserver_upload.cpp index d9f2c6940..71bcc9753 100644 --- a/solid/frame/mprpc/test/test_clientserver_upload.cpp +++ b/solid/frame/mprpc/test/test_clientserver_upload.cpp @@ -32,7 +32,7 @@ using namespace std; using namespace solid; namespace { -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; @@ -286,7 +286,7 @@ int test_clientserver_upload(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/)); cfg.client.connection_start_state = frame::mprpc::ConnectionState::Active; if (secure) { diff --git a/solid/frame/mprpc/test/test_clientserver_upload_single.cpp b/solid/frame/mprpc/test/test_clientserver_upload_single.cpp index f7feed292..698424715 100644 --- a/solid/frame/mprpc/test/test_clientserver_upload_single.cpp +++ b/solid/frame/mprpc/test/test_clientserver_upload_single.cpp @@ -38,7 +38,7 @@ using namespace solid; namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; LoggerT logger("test"); @@ -290,7 +290,7 @@ int test_clientserver_upload_single(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/)); cfg.client.connection_start_state = frame::mprpc::ConnectionState::Active; if (secure) { diff --git a/solid/frame/mprpc/test/test_clientserver_versioning.cpp b/solid/frame/mprpc/test/test_clientserver_versioning.cpp index 1e2e4b208..4d121eb2c 100644 --- a/solid/frame/mprpc/test/test_clientserver_versioning.cpp +++ b/solid/frame/mprpc/test/test_clientserver_versioning.cpp @@ -39,7 +39,7 @@ namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; const solid::LoggerT logger("test"); @@ -140,7 +140,7 @@ void configure_service(frame::mprpc::ServiceT& _rsvc, AioSchedulerT& _rsch, fram }); frame::mprpc::Configuration cfg(_rsch, proto); - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(_rrsv, _server_port.c_str()); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(_rrsv, _server_port.c_str())); auto connection_start_lambda = [](frame::mprpc::ConnectionContext& _rctx) { solid_log(logger, Info, "Connection start"); @@ -210,7 +210,7 @@ void configure_service(frame::mprpc::ServiceT& _rsvc, AioSchedulerT& _rsch, fram }); frame::mprpc::Configuration cfg(_rsch, proto); - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(_rrsv, _server_port.c_str()); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(_rrsv, _server_port.c_str())); auto connection_start_lambda = [](frame::mprpc::ConnectionContext& _rctx) { solid_log(logger, Info, "Connection start"); @@ -283,7 +283,7 @@ void configure_service(frame::mprpc::ServiceT& _rsvc, AioSchedulerT& _rsch, fram configure_protocol(lambda); }); frame::mprpc::Configuration cfg(_rsch, proto); - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(_rrsv, _server_port.c_str()); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(_rrsv, _server_port.c_str())); auto connection_start_lambda = [](frame::mprpc::ConnectionContext& _rctx) { solid_log(logger, Info, "Connection start"); @@ -357,7 +357,7 @@ void configure_service(frame::mprpc::ServiceT& _rsvc, AioSchedulerT& _rsch, fram }); frame::mprpc::Configuration cfg(_rsch, proto); - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(_rrsv, _server_port.c_str()); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(_rrsv, _server_port.c_str())); auto connection_start_lambda = [](frame::mprpc::ConnectionContext& _rctx) { solid_log(logger, Info, "Connection start"); diff --git a/solid/frame/mprpc/test/test_connection_close.cpp b/solid/frame/mprpc/test/test_connection_close.cpp index acfe0917e..9f2e73c5f 100644 --- a/solid/frame/mprpc/test/test_connection_close.cpp +++ b/solid/frame/mprpc/test/test_connection_close.cpp @@ -32,7 +32,7 @@ using namespace solid; namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -377,7 +377,7 @@ int test_connection_close(int argc, char* argv[]) cfg.pool_max_active_connection_count = 1; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/)); mprpcclient.start(std::move(cfg)); } diff --git a/solid/frame/mprpc/test/test_keepalive_fail.cpp b/solid/frame/mprpc/test/test_keepalive_fail.cpp index 1259078fc..e9e11c8b2 100644 --- a/solid/frame/mprpc/test/test_keepalive_fail.cpp +++ b/solid/frame/mprpc/test/test_keepalive_fail.cpp @@ -35,7 +35,7 @@ namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -380,7 +380,7 @@ int test_keepalive_fail(int argc, char* argv[]) cfg.writer.max_message_count_multiplex = 6; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/)); mprpcclient.start(std::move(cfg)); } diff --git a/solid/frame/mprpc/test/test_keepalive_success.cpp b/solid/frame/mprpc/test/test_keepalive_success.cpp index 192d55d3f..e10bb2d67 100644 --- a/solid/frame/mprpc/test/test_keepalive_success.cpp +++ b/solid/frame/mprpc/test/test_keepalive_success.cpp @@ -34,7 +34,7 @@ namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -354,7 +354,7 @@ int test_keepalive_success(int argc, char* argv[]) cfg.writer.max_message_count_multiplex = 6; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/)); mprpcclient.start(std::move(cfg)); } diff --git a/solid/frame/mprpc/test/test_multiprotocol_basic.cpp b/solid/frame/mprpc/test/test_multiprotocol_basic.cpp index 3209c490a..f31eb1017 100644 --- a/solid/frame/mprpc/test/test_multiprotocol_basic.cpp +++ b/solid/frame/mprpc/test/test_multiprotocol_basic.cpp @@ -41,7 +41,7 @@ using namespace solid; typedef frame::aio::openssl::Context SecureContextT; namespace { -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; std::atomic wait_count(0); mutex mtx; diff --git a/solid/frame/mprpc/test/test_pool_basic.cpp b/solid/frame/mprpc/test/test_pool_basic.cpp index 10736a4b9..9e83a1cb8 100644 --- a/solid/frame/mprpc/test/test_pool_basic.cpp +++ b/solid/frame/mprpc/test/test_pool_basic.cpp @@ -33,7 +33,7 @@ namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -387,7 +387,7 @@ int test_pool_basic(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_pool_delay_close.cpp b/solid/frame/mprpc/test/test_pool_delay_close.cpp index 978d9cae4..070635c06 100644 --- a/solid/frame/mprpc/test/test_pool_delay_close.cpp +++ b/solid/frame/mprpc/test/test_pool_delay_close.cpp @@ -31,7 +31,7 @@ using namespace solid; namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -343,7 +343,7 @@ int test_pool_delay_close(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/)); cfg.writer.max_message_count_multiplex = 2; diff --git a/solid/frame/mprpc/test/test_pool_force_close.cpp b/solid/frame/mprpc/test/test_pool_force_close.cpp index 620e163ae..2d390428c 100644 --- a/solid/frame/mprpc/test/test_pool_force_close.cpp +++ b/solid/frame/mprpc/test/test_pool_force_close.cpp @@ -32,7 +32,7 @@ namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -314,7 +314,7 @@ int test_pool_force_close(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/)); cfg.writer.max_message_count_multiplex = 2; diff --git a/solid/frame/mprpc/test/test_raw_basic.cpp b/solid/frame/mprpc/test/test_raw_basic.cpp index 7193c3f23..67d136770 100644 --- a/solid/frame/mprpc/test/test_raw_basic.cpp +++ b/solid/frame/mprpc/test/test_raw_basic.cpp @@ -30,7 +30,7 @@ using namespace solid; namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -413,7 +413,7 @@ int test_raw_basic(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/)); mprpcclient.start(std::move(cfg)); } diff --git a/solid/frame/mprpc/test/test_raw_proxy.cpp b/solid/frame/mprpc/test/test_raw_proxy.cpp index 21b239d7b..2348add7b 100644 --- a/solid/frame/mprpc/test/test_raw_proxy.cpp +++ b/solid/frame/mprpc/test/test_raw_proxy.cpp @@ -29,7 +29,7 @@ using namespace solid; namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -413,7 +413,7 @@ int test_raw_proxy(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, server_port.c_str() /*, SocketInfo::Inet4*/)); mprpcclient.start(std::move(cfg)); } diff --git a/solid/frame/mprpc/test/test_relay_basic.cpp b/solid/frame/mprpc/test/test_relay_basic.cpp index b843a3d4e..cb7c09e9c 100644 --- a/solid/frame/mprpc/test/test_relay_basic.cpp +++ b/solid/frame/mprpc/test/test_relay_basic.cpp @@ -34,7 +34,7 @@ using namespace solid; namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -491,7 +491,7 @@ int test_relay_basic(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); @@ -527,7 +527,7 @@ int test_relay_basic(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_relay_cancel_request.cpp b/solid/frame/mprpc/test/test_relay_cancel_request.cpp index 33317c899..33415d086 100644 --- a/solid/frame/mprpc/test/test_relay_cancel_request.cpp +++ b/solid/frame/mprpc/test/test_relay_cancel_request.cpp @@ -34,7 +34,7 @@ using namespace solid; namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -541,7 +541,7 @@ int test_relay_cancel_request(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); @@ -577,7 +577,7 @@ int test_relay_cancel_request(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_relay_cancel_response.cpp b/solid/frame/mprpc/test/test_relay_cancel_response.cpp index 228b7a362..28618a5a7 100644 --- a/solid/frame/mprpc/test/test_relay_cancel_response.cpp +++ b/solid/frame/mprpc/test/test_relay_cancel_response.cpp @@ -34,7 +34,7 @@ using namespace solid; namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -533,7 +533,7 @@ int test_relay_cancel_response(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); @@ -569,7 +569,7 @@ int test_relay_cancel_response(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_relay_close_request.cpp b/solid/frame/mprpc/test/test_relay_close_request.cpp index 86a4965b7..2dd7fc0b1 100644 --- a/solid/frame/mprpc/test/test_relay_close_request.cpp +++ b/solid/frame/mprpc/test/test_relay_close_request.cpp @@ -36,7 +36,7 @@ using namespace solid; namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -493,7 +493,7 @@ int test_relay_close_request(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); @@ -529,7 +529,7 @@ int test_relay_close_request(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_relay_close_response.cpp b/solid/frame/mprpc/test/test_relay_close_response.cpp index cf83ea3d5..e009f443c 100644 --- a/solid/frame/mprpc/test/test_relay_close_response.cpp +++ b/solid/frame/mprpc/test/test_relay_close_response.cpp @@ -36,7 +36,7 @@ using namespace solid; namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -493,7 +493,7 @@ int test_relay_close_response(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); @@ -535,7 +535,7 @@ int test_relay_close_response(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_relay_detect_close.cpp b/solid/frame/mprpc/test/test_relay_detect_close.cpp index b9ae205fe..09d75e7ad 100644 --- a/solid/frame/mprpc/test/test_relay_detect_close.cpp +++ b/solid/frame/mprpc/test/test_relay_detect_close.cpp @@ -36,7 +36,7 @@ using namespace solid; namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; bool running = true; mutex mtx; @@ -358,7 +358,7 @@ int test_relay_detect_close(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); @@ -401,7 +401,7 @@ int test_relay_detect_close(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_relay_detect_close_while_response.cpp b/solid/frame/mprpc/test/test_relay_detect_close_while_response.cpp index 3835797e9..fb9183a28 100644 --- a/solid/frame/mprpc/test/test_relay_detect_close_while_response.cpp +++ b/solid/frame/mprpc/test/test_relay_detect_close_while_response.cpp @@ -36,7 +36,7 @@ using namespace solid; namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; bool running = true; mutex mtx; @@ -397,7 +397,7 @@ int test_relay_detect_close_while_response(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); @@ -440,7 +440,7 @@ int test_relay_detect_close_while_response(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_relay_disabled.cpp b/solid/frame/mprpc/test/test_relay_disabled.cpp index ede0d8eda..87671ccae 100644 --- a/solid/frame/mprpc/test/test_relay_disabled.cpp +++ b/solid/frame/mprpc/test/test_relay_disabled.cpp @@ -32,7 +32,7 @@ using namespace solid; namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -439,7 +439,7 @@ int test_relay_disabled(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); @@ -475,7 +475,7 @@ int test_relay_disabled(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/mprpc/test/test_relay_split.cpp b/solid/frame/mprpc/test/test_relay_split.cpp index 55fc0f6f9..05bbbfa27 100644 --- a/solid/frame/mprpc/test/test_relay_split.cpp +++ b/solid/frame/mprpc/test/test_relay_split.cpp @@ -33,7 +33,7 @@ using namespace solid; namespace { using AioSchedulerT = frame::Scheduler>; using SecureContextT = frame::aio::openssl::Context; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; struct InitStub { size_t size; @@ -520,7 +520,7 @@ int test_relay_split(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); @@ -556,7 +556,7 @@ int test_relay_split(int argc, char* argv[]) cfg.pool_max_active_connection_count = max_per_pool_connection_count; - cfg.client.name_resolve_fnc = frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/); + cfg.client.name_resolve_fnc.emplace(frame::mprpc::InternetResolverF(resolver, relay_port.c_str() /*, SocketInfo::Inet4*/)); if (secure) { solid_dbg(generic_logger, Info, "Configure SSL client ------------------------------------"); diff --git a/solid/frame/sharedstore.hpp b/solid/frame/sharedstore.hpp index 33e955ef0..d4ed236b4 100644 --- a/solid/frame/sharedstore.hpp +++ b/solid/frame/sharedstore.hpp @@ -654,8 +654,8 @@ class Store : public StoreBase { waitdq.push_back(WaitStub()); pwait = &waitdq.back(); } - pwait->kind = _k; - pwait->fnc = std::move(_f); + pwait->kind = _k; + pwait->fnc.emplace(std::move(_f)); pwait->pnext = nullptr; if (rs.pwaitlast == nullptr) { diff --git a/solid/serialization/v3/binarydeserializer.hpp b/solid/serialization/v3/binarydeserializer.hpp index e006cde99..b732ada6a 100644 --- a/solid/serialization/v3/binarydeserializer.hpp +++ b/solid/serialization/v3/binarydeserializer.hpp @@ -73,7 +73,7 @@ class DeserializerBase : public Base { , size_(0) , data_(0) , name_(_name) - , fnc_ptr_(std::make_unique(std::move(_f))) + , fnc_ptr_(std::make_unique(std::move(_f), std::false_type{})) , limit_(0) { } diff --git a/solid/system/configuration_impl.hpp.in b/solid/system/configuration_impl.hpp.in index 9ec992ff9..04eb9fba9 100644 --- a/solid/system/configuration_impl.hpp.in +++ b/solid/system/configuration_impl.hpp.in @@ -26,6 +26,4 @@ #cmakedefine SOLID_USE_GCC_BSWAP -#cmakedefine SOLID_FRAME_AIO_REACTOR_USE_SPINLOCK - -#cmakedefine SOLID_MPRPC_USE_SHARED_PTR_MESSAGE +#cmakedefine SOLID_FRAME_AIO_REACTOR_USE_SPINLOCK \ No newline at end of file diff --git a/solid/utility/any.hpp b/solid/utility/any.hpp index 460e7936b..88f60c52a 100644 --- a/solid/utility/any.hpp +++ b/solid/utility/any.hpp @@ -41,6 +41,9 @@ template struct is_any : std::false_type { }; +template +inline constexpr bool is_any_v = is_any::value; + namespace any_impl { struct SmallRTTI; @@ -323,28 +326,23 @@ class Any { } template < - class T, std::enable_if_t>>, std::negation, std::in_place_type_t>>>, int> = 0> + class T> Any(T&& _rvalue) + requires(not is_any_v> and not is_specialization_v, std::in_place_type_t>) { doEmplace>(std::forward(_rvalue)); } - template , Args...> /*, std::is_copy_constructible>*/>, - int> - = 0> + template explicit Any(std::in_place_type_t, Args&&... _args) + requires(std::is_constructible_v, Args...>) { doEmplace>(std::forward(_args)...); } - template , std::initializer_list&, Args...>, - std::is_copy_constructible>>, - int> - = 0> + template explicit Any(std::in_place_type_t, std::initializer_list _ilist, Args&&... _args) + requires(std::is_constructible_v, std::initializer_list&, Args...> and std::is_copy_constructible_v>) { doEmplace>(_ilist, std::forward(_args)...); } @@ -382,30 +380,24 @@ class Any { return *this; } - template >>, std::is_copy_constructible>>, int> = 0> + template ThisT& operator=(T&& _rvalue) + requires(not is_any_v> and std::is_copy_constructible_v>) { *this = ThisT{std::forward(_rvalue)}; return *this; } - template , Args...>>, - int> - = 0> + template std::decay_t& emplace(Args&&... _args) + requires(std::is_constructible_v, Args...>) { reset(); return doEmplace>(std::forward(_args)...); } - template , std::initializer_list&, Args...> /*, - is_copy_constructible>*/ - >, - int> - = 0> + template std::decay_t& emplace(std::initializer_list _ilist, Args&&... _args) + requires(std::is_constructible_v, std::initializer_list&, Args...>) { reset(); return doEmplace>(_ilist, std::forward(_args)...); diff --git a/solid/utility/event.hpp b/solid/utility/event.hpp index 3b9c4fbaf..85074a43d 100644 --- a/solid/utility/event.hpp +++ b/solid/utility/event.hpp @@ -386,6 +386,9 @@ template struct is_event : std::false_type { }; +template +inline constexpr bool is_event_v = is_event::value; + template <> class Event<0, 0> : public EventBase { public: @@ -480,8 +483,9 @@ class Event : public EventBase { doMoveFrom(data_, smallCapacity(), smallAlign(), _other); } - template >>, std::negation, std::in_place_type_t>>>, int> = 0> + template Event(const Evs _ev, T&& _rvalue) + requires(not is_event_v> and not is_specialization_v, std::in_place_type_t>) : EventBase(category, to_underlying(_ev)) { using ValueT = std::decay_t; @@ -493,8 +497,9 @@ class Event : public EventBase { } } - template >>, std::negation, std::in_place_type_t>>>, int> = 0> + template Event(const EventCategoryBase& _category, const Evs _ev, T&& _rvalue) + requires(not is_event_v> and not is_specialization_v, std::in_place_type_t>) : EventBase(_category, to_underlying(_ev)) { using ValueT = std::decay_t; @@ -506,12 +511,9 @@ class Event : public EventBase { } } - template , Args...>>, - int> - = 0> + template explicit Event(const Evs _ev, std::in_place_type_t, Args&&... _args) + requires(std::is_constructible_v, Args...>) : EventBase(category, to_underlying(_ev)) { using ValueT = std::decay_t; @@ -523,12 +525,9 @@ class Event : public EventBase { } } - template , Args...>>, - int> - = 0> + template explicit Event(const EventCategoryBase& _category, const Evs _ev, std::in_place_type_t, Args&&... _args) + requires(std::is_constructible_v, Args...>) : EventBase(_category, to_underlying(_ev)) { using ValueT = std::decay_t; @@ -540,12 +539,9 @@ class Event : public EventBase { } } - template , std::initializer_list&, Args...>, - std::is_copy_constructible>>, - int> - = 0> + template explicit Event(const Evs _ev, std::in_place_type_t, std::initializer_list _ilist, Args&&... _args) + requires(std::is_constructible_v, std::initializer_list&, Args...> and std::is_copy_constructible_v>) : EventBase(category, to_underlying(_ev)) { using ValueT = std::decay_t; @@ -557,12 +553,9 @@ class Event : public EventBase { } } - template , std::initializer_list&, Args...>, - std::is_copy_constructible>>, - int> - = 0> + template explicit Event(const EventCategoryBase& _category, const Evs _ev, std::in_place_type_t, std::initializer_list _ilist, Args&&... _args) + requires(std::is_constructible_v, std::initializer_list&, Args...> and std::is_copy_constructible_v>) : EventBase(_category, to_underlying(_ev)) { using ValueT = std::decay_t; @@ -614,8 +607,9 @@ class Event : public EventBase { return *this; } - template >>, std::is_copy_constructible>>, int> = 0> + template ThisT& operator=(T&& _rvalue) + requires(not is_event_v> and std::is_copy_constructible_v>) { resetData(); @@ -628,12 +622,9 @@ class Event : public EventBase { return *this; } - template , Args...>>, - int> - = 0> + template std::decay_t& emplace(Args&&... _args) + requires(std::is_constructible_v, Args...>) { resetData(); using ValueT = std::decay_t; @@ -644,9 +635,9 @@ class Event : public EventBase { return doEmplaceBig(std::forward(_args)...); } } - template , std::initializer_list&, Args...>>, int> = 0> + template std::decay_t& emplace(std::initializer_list _ilist, Args&&... _args) + requires(std::is_constructible_v, std::initializer_list&, Args...>) { resetData(); using ValueT = std::decay_t; @@ -676,48 +667,56 @@ class Event : public EventBase { //----------------------------------------------------------------------------- // make_event //----------------------------------------------------------------------------- -template , int> = 0> +template inline auto make_event(const Events _id) + requires(std::is_enum_v) { return Event<>(_id); } -template , int> = 0> +template inline auto make_event(const EventCategoryBase& _category, const Events _id) + requires(std::is_enum_v) { return Event<>(_category, _id); } -template , int> = 0> +template inline auto make_event(const Events _id, T&& _data) + requires(std::is_enum_v) { return Event), alignof(std::decay_t)>(_id, std::forward(_data)); } -template , int> = 0> +template auto make_event(const Events _id, Args&&... _args) + requires(std::is_enum_v) { return Event), alignof(std::decay_t)>{_id, std::in_place_type, std::forward(_args)...}; } -template , int> = 0> +template auto make_event(const Events _id, std::initializer_list _ilist, Args&&... _args) + requires(std::is_enum_v) { return Event), alignof(std::decay_t)>{_id, std::in_place_type, _ilist, std::forward(_args)...}; } -template , int> = 0> +template inline auto make_event(const EventCategoryBase& _category, const Events _id, T&& _data) + requires(std::is_enum_v) { return Event), alignof(std::decay_t)>(_category, _id, std::forward(_data)); } -template , int> = 0> +template auto make_event(const EventCategoryBase& _category, const Events _id, Args&&... _args) + requires(std::is_enum_v) { return Event), alignof(std::decay_t)>{_category, _id, std::in_place_type, std::forward(_args)...}; } -template , int> = 0> +template auto make_event(const EventCategoryBase& _category, const Events _id, std::initializer_list _ilist, Args&&... _args) + requires(std::is_enum_v) { return Event), alignof(std::decay_t)>{_category, _id, std::in_place_type, _ilist, std::forward(_args)...}; } diff --git a/solid/utility/function.hpp b/solid/utility/function.hpp index b7a41b636..e0ac0e322 100644 --- a/solid/utility/function.hpp +++ b/solid/utility/function.hpp @@ -8,14 +8,16 @@ // See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt. // #pragma once + +// #define SOLID_THROW_ON_BIG_FUNCTION + +#include +#include #include +#include #include #include #include -#define SOLID_THROW_ON_BIG_FUNCTION -#include -#include -#include #include #include @@ -27,10 +29,21 @@ namespace solid { -constexpr size_t function_default_size = 32 - sizeof(std::uintptr_t); +template + requires(std::popcount(Align) == 1) +constexpr size_t function_size_to_small_size() +{ + constexpr size_t max = std::max(sizeof(std::uintptr_t), Align); + static_assert(Size >= max, "size must be greater than sizeof(std::uintptr_t)"); + return Size - max; +} + +constexpr size_t function_default_size = function_size_to_small_size<32>(); constexpr size_t function_default_align = alignof(std::uintptr_t); template + requires(SmallSize > 0 and SmallSize >= SmallAlign + and (SmallSize % SmallAlign == 0) and std::popcount(SmallAlign) == 1) class Function; // undefined template @@ -44,6 +57,9 @@ template struct is_function : std::false_type { }; +template +inline constexpr bool is_function_v = is_function::value; + namespace fnc_impl { using any_impl::representation; @@ -223,6 +239,8 @@ uintptr_t do_move_big( } // namespace fnc_impl template + requires(SmallSize > 0 and SmallSize >= SmallAlign + and (SmallSize % SmallAlign == 0) and std::popcount(SmallAlign) == 1) class Function { using BaseRTTI_T = fnc_impl::BaseRTTI; @@ -247,6 +265,8 @@ class Function { Storage storage_{}; template + requires(S > 0 and S >= A + and (S % A == 0) and std::popcount(A) == 1) friend class Function; public: @@ -294,44 +314,21 @@ class Function { doMoveFrom(_other); } - template >>, std::negation, std::in_place_type_t>> /*, - std::is_copy_constructible>*/ - >, - int> - = 0> - Function(const T& _fun) + template + Function(T&& _fun, std::integral_constant = std::true_type{}) + requires(not is_function_v> and not is_specialization_v, std::in_place_type_t>) { using FncT = std::remove_cvref_t>; + static_assert(not CheckSmall or is_small_type(), "Function not small. Construct with std::false_type."); if constexpr (is_small_type()) { storage_.rtti_ = fnc_impl::representation(&fnc_impl::small_rtti, fnc_impl::RepresentationE::Small); auto& rval = reinterpret_cast(storage_.small_.data_); - std::construct_at(std::addressof(rval), _fun); - } else { -#if defined(SOLID_THROW_ON_BIG_FUNCTION) - solid_throw("Big Function"); -#endif - FncT* const ptr = ::new FncT(_fun); - storage_.big_.ptr_ = ptr; - storage_.rtti_ = fnc_impl::representation(&fnc_impl::big_rtti, fnc_impl::RepresentationE::Big); - } - } - template >>, std::negation, std::in_place_type_t>> /*, - std::is_copy_constructible>*/ - >, - int> - = 0> - Function(T&& _fun) - { - using FncT = std::remove_cvref_t; - if constexpr (is_small_type()) { - storage_.rtti_ = fnc_impl::representation(&fnc_impl::small_rtti, fnc_impl::RepresentationE::Small); - auto& rval = reinterpret_cast(storage_.small_.data_); - std::construct_at(std::addressof(rval), std::move(_fun)); + std::construct_at(std::addressof(rval), std::forward(_fun)); } else { #if defined(SOLID_THROW_ON_BIG_FUNCTION) solid_throw("Big Function"); #endif - FncT* const ptr = ::new FncT(std::move(_fun)); + FncT* const ptr = ::new FncT(std::forward(_fun)); storage_.big_.ptr_ = ptr; storage_.rtti_ = fnc_impl::representation(&fnc_impl::big_rtti, fnc_impl::RepresentationE::Big); } @@ -384,13 +381,20 @@ class Function { return *this; } - template >>, std::is_copy_constructible>>, int> = 0> + template ThisT& operator=(T&& _rvalue) { *this = ThisT{std::forward(_rvalue)}; return *this; } + template + ThisT& emplace(T&& _rvalue) + { + *this = ThisT{std::forward(_rvalue), std::false_type{}}; + return *this; + } + void reset() noexcept { auto const rtti = storage_.rtti_; @@ -529,7 +533,14 @@ class Function { }; //----------------------------------------------------------------------------- - +template +using Function64T = Function()>; +template +using Function96T = Function()>; +template +using Function128T = Function()>; +template +using Function256T = Function()>; //----------------------------------------------------------------------------- } // namespace solid diff --git a/solid/utility/intrusiveptr.hpp b/solid/utility/intrusiveptr.hpp index 7c9280e80..a6905beb9 100644 --- a/solid/utility/intrusiveptr.hpp +++ b/solid/utility/intrusiveptr.hpp @@ -117,7 +117,6 @@ class IntrusivePtrBase { protected: T* ptr_ = nullptr; -protected: IntrusivePtrBase() = default; IntrusivePtrBase(T* _ptr) @@ -150,7 +149,7 @@ class IntrusivePtrBase { } } - IntrusivePtrBase(IntrusivePtrBase&& _other) + IntrusivePtrBase(IntrusivePtrBase&& _other) noexcept : ptr_(_other.detach()) { } @@ -261,7 +260,7 @@ class IntrusivePtr : public impl::IntrusivePtrBase { { } - IntrusivePtr(IntrusivePtr&& _other) + IntrusivePtr(IntrusivePtr&& _other) noexcept : BaseT(std::move(_other)) { } @@ -377,7 +376,7 @@ class MutableIntrusivePtr : public impl::IntrusivePtrBase { template MutableIntrusivePtr(const MutableIntrusivePtr& _other) = delete; - MutableIntrusivePtr(MutableIntrusivePtr&& _other) + MutableIntrusivePtr(MutableIntrusivePtr&& _other) noexcept : BaseT(std::move(_other)) { } @@ -481,7 +480,7 @@ class ConstIntrusivePtr : public impl::IntrusivePtrBase { { } - ConstIntrusivePtr(ConstIntrusivePtr&& _other) + ConstIntrusivePtr(ConstIntrusivePtr&& _other) noexcept : BaseT(std::move(_other)) { } diff --git a/solid/utility/test/test_collapse.cpp b/solid/utility/test/test_collapse.cpp index 1d1427d0f..2c8a030df 100644 --- a/solid/utility/test/test_collapse.cpp +++ b/solid/utility/test/test_collapse.cpp @@ -49,7 +49,7 @@ struct Message : IntrusiveThreadSafeBase { } }; -using CallPoolT = ThreadPool, Function>; +using CallPoolT = ThreadPool, Function64T>; using SharedMessageT = ConstIntrusivePtr; } // namespace diff --git a/solid/utility/test/test_function.cpp b/solid/utility/test/test_function.cpp index 8f834894d..ec751c72c 100644 --- a/solid/utility/test/test_function.cpp +++ b/solid/utility/test/test_function.cpp @@ -2,6 +2,7 @@ #include #include #include +#include using namespace solid; using namespace std; @@ -11,7 +12,7 @@ void test_fnc(void* _ptr, const char* _txt) } class Test2 { - Function fnc_; + Function64T fnc_; public: template @@ -51,30 +52,40 @@ class Test3 { int test_function(int /*argc*/, char* /*argv*/[]) { { - Function fnc(&test_fnc); + Function64T fnc(&test_fnc); fnc(&fnc, "something"); } { - ifstream ifs; - Function fnc( + ifstream ifs; + Function fnc( [ifs = std::move(ifs)](void* _ptr, const char* _txt) mutable { ifs.open("test.txt"); cout << "test_fnc: " << _ptr << " " << _txt << endl; - }); + }, + std::false_type{}); fnc(&fnc, "something"); } #if 0 { ifstream ifs; - auto lambda = [ifs = std::move(ifs)](void *_ptr, const char*_txt)mutable{ + auto lambda = [ifs = std::move(ifs)](void* _ptr, const char* _txt) mutable { ifs.open("test.txt"); - cout<<"test_fnc: "<<_ptr<<" "<<_txt< fnc(std::move(lambda)); - + fnc(&fnc, "something"); } #endif + { + Function()> fnc(&test_fnc); + static_assert(sizeof(fnc) == 64); + static_assert(sizeof(Function64T) == 64); + static_assert(sizeof(Function96T) == 96); + static_assert(sizeof(Function128T) == 128); + static_assert(sizeof(Function256T) == 256); + static_assert(sizeof(Function(), 16>) == 64); + } #if 1 { diff --git a/solid/utility/test/test_function_perf.cpp b/solid/utility/test/test_function_perf.cpp index 25dd574ba..f668aa6f4 100644 --- a/solid/utility/test/test_function_perf.cpp +++ b/solid/utility/test/test_function_perf.cpp @@ -3,6 +3,7 @@ #include #include #include +#include using namespace solid; using namespace std; @@ -46,7 +47,11 @@ class FunctionTest : public TestBase { void push(Fnc _f) { static const PrintSize ps(sizeof(_f)); - fnc_dq.emplace_back(std::move(_f)); + if constexpr (solid::is_function_v) { + fnc_dq.emplace_back(std::move(_f), std::false_type{}); + } else { + fnc_dq.emplace_back(std::move(_f)); + } } void create(const size_t _create_count) override diff --git a/solid/utility/typetraits.hpp b/solid/utility/typetraits.hpp index 4d7010192..108dbea65 100644 --- a/solid/utility/typetraits.hpp +++ b/solid/utility/typetraits.hpp @@ -77,15 +77,20 @@ struct is_container< template inline constexpr bool is_container_v = is_container::value; +namespace impl { template class _Template> inline constexpr bool is_specialization_v = false; template