diff --git a/src-test/server/ConfigTest.cpp b/src-test/server/ConfigTest.cpp index 7dac417c06..4cd38ada9f 100644 --- a/src-test/server/ConfigTest.cpp +++ b/src-test/server/ConfigTest.cpp @@ -34,6 +34,7 @@ #include "mc/world/actor/DataItem.h" #include "ll/api/base/Containers.h" +#include "ll/api/data/IndirectValue.h" // [0, 8, 16, 96, 97, 98, 104, 136, 144, 160, 176, 184, 196, 208, 232, 248, 304, 328, 360, 392, 408] diff --git a/src-test/server/ECSTest.cpp b/src-test/server/ECSTest.cpp index 863c49b4e7..3d6c65b7e6 100644 --- a/src-test/server/ECSTest.cpp +++ b/src-test/server/ECSTest.cpp @@ -37,7 +37,7 @@ namespace ll::test::ecstest { void registerTimingCommand() { - constexpr static size_t counttick = 100; + static constexpr size_t counttick = 100; auto& cmd = ::ll::command::CommandRegistrar::getInstance() .getOrCreateCommand("timing", "timing", CommandPermissionLevel::GameDirectors, CommandFlagValue::None); diff --git a/src/ll/api/Expected.cpp b/src/ll/api/Expected.cpp index 2d00d67cc5..fc1dd118a0 100644 --- a/src/ll/api/Expected.cpp +++ b/src/ll/api/Expected.cpp @@ -11,27 +11,32 @@ namespace ll { #if defined(LL_DEBUG) -struct ErrorInfoBase::Impl { +struct DebugContext { Stacktrace stacktrace; }; -ErrorInfoBase::ErrorInfoBase() noexcept : impl(std::make_unique(Stacktrace::current(1))) {} + +void* Error::createExtraData() noexcept { return new DebugContext{Stacktrace::current(1)}; } +void Error::destroyExtraData(void* ptr) noexcept { delete ((DebugContext*)ptr); } +void* Error::copyExtraData(void* ptr) noexcept { return new DebugContext(*(DebugContext const*)(ptr)); } + std::string Error::message() const noexcept { - if (!mInfo) { + if (!hasValue()) { return "success"; } - auto res = mInfo->message(); + auto res = dataPtr->message(); res += "\nexpected stacktrace:\n"; - res += stacktrace_utils::toString(mInfo->impl->stacktrace); + res += stacktrace_utils::toString(reinterpret_cast(extraData)->stacktrace); return res; } -struct ExceptionError : ErrorInfoBase { +struct ExceptionError { std::exception_ptr exc; Stacktrace stacktrace; ExceptionError(std::exception_ptr const& exc) noexcept : exc(exc), stacktrace(error_utils::stacktraceFromCurrentException()) {} - [[nodiscard]] std::string message() const noexcept override { + + [[nodiscard]] std::string message() const noexcept { auto res = error_utils::makeExceptionString(exc); if (!stacktrace.empty()) { res += "\nexception stacktrace:\n"; @@ -41,19 +46,20 @@ struct ExceptionError : ErrorInfoBase { } }; #else -struct ErrorInfoBase::Impl {}; -ErrorInfoBase::ErrorInfoBase() noexcept {} -std::string Error::message() const noexcept { return mInfo ? mInfo->message() : "success"; } -struct ExceptionError : ErrorInfoBase { +void* Error::createExtraData() noexcept { return nullptr; } +void Error::destroyExtraData(void* ptr) noexcept {} +void* Error::copyExtraData(void* ptr) noexcept { return nullptr; } + +std::string Error::message() const noexcept { return hasValue() ? dataPtr->message() : "success"; } + +struct ExceptionError { std::exception_ptr exc; ExceptionError(std::exception_ptr const& exc) noexcept : exc(exc) {} - std::string message() const noexcept override { return error_utils::makeExceptionString(exc); } + std::string message() const noexcept { return error_utils::makeExceptionString(exc); } }; #endif -ErrorInfoBase::~ErrorInfoBase() = default; - Unexpected makeExceptionError(std::exception_ptr const& exc) noexcept { auto err = error_utils::AnyExceptionRef(exc).tryGet>(); if (err) { @@ -62,14 +68,13 @@ Unexpected makeExceptionError(std::exception_ptr const& exc) noexcept { return makeError(exc); } -struct ErrorList : ErrorInfoBase { - std::vector> errors; +struct ErrorList { + std::vector errors; ErrorList() noexcept = default; - [[nodiscard]] std::string message() const noexcept override { + [[nodiscard]] std::string message() const noexcept { std::string result; - for (size_t i = 0; i < errors.size(); i++) { - result += errors[i]->message(); + result += errors[i].message(); if (i + 1 < errors.size()) { result += '\n'; } @@ -79,8 +84,9 @@ struct ErrorList : ErrorInfoBase { }; Error& Error::join(Error err) noexcept { - if (!*this) { - mInfo = std::move(err.mInfo); + if (!hasValue()) { + tidy(); + move(std::move(err)); return *this; } if (!err) { @@ -90,18 +96,19 @@ Error& Error::join(Error err) noexcept { if (err.isA()) { as().errors.append_range(std::move(err.as().errors)); } else { - as().errors.emplace_back(std::move(err.mInfo)); + as().errors.emplace_back(std::move(err)); } } else { if (err.isA()) { auto& list = err.as(); - list.errors.insert(list.errors.begin(), std::move(mInfo)); - mInfo = std::move(err.mInfo); + list.errors.insert(list.errors.begin(), std::move(*this)); + *this = std::move(err); } else { - auto list = std::make_unique(); - list->errors.emplace_back(std::move(mInfo)); - list->errors.emplace_back(std::move(err.mInfo)); - mInfo = std::move(list); + Error list(std::in_place_type); + auto& vec = list.as().errors; + vec.emplace_back(std::move(*this)); + vec.emplace_back(std::move(err)); + *this = std::move(list); } } return *this; diff --git a/src/ll/api/Expected.h b/src/ll/api/Expected.h index 067049568e..8b3e45a141 100644 --- a/src/ll/api/Expected.h +++ b/src/ll/api/Expected.h @@ -13,7 +13,9 @@ #include #include +#include "ll/api/base/Concepts.h" #include "ll/api/base/Macro.h" +#include "ll/api/data/AnyObjBase.h" #include "ll/api/io/LogLevel.h" #include "mc/server/commands/CommandOutputMessageType.h" @@ -28,48 +30,150 @@ using Expected = ::nonstd::expected; using Unexpected = ::nonstd::unexpected_type<::ll::Error>; -class ErrorInfoBase { - friend Error; - struct Impl; - std::unique_ptr impl; +template +concept IsErrorObj = requires(T t) { + requires requires { + { t.message() } -> concepts::IsString; + } || requires { + { t.what() } -> concepts::IsString; + }; +} || concepts::IsString; +class ErrorObjBase : public data::AnyObjBase { public: - LLAPI ErrorInfoBase() noexcept; - LLAPI virtual ~ErrorInfoBase(); + static constexpr inline size_t errorSizeNumPtrs = 7; + static constexpr inline size_t smallObjSize = ((errorSizeNumPtrs - 2) * sizeof(void*)); + + virtual ErrorObjBase* copy(void* to) const = 0; + virtual ErrorObjBase* move(void* to) noexcept = 0; + virtual void tidy() noexcept = 0; + virtual std::string message() noexcept = 0; + virtual std::type_info const& type() const noexcept = 0; + virtual const void* get() const noexcept = 0; +}; +template +class ErrorObj : public ErrorObjBase { + Err err; + +public: + static constexpr inline bool nothrowMove = std::is_nothrow_move_constructible_v; + + template + constexpr explicit ErrorObj(Args&&... args) : err(std::forward(args)...) {} + + template + static constexpr ErrorObjBase* construct(void* to, Args&&... args) { + return constructImpl(to, std::forward(args)...); + } - virtual std::string message() const noexcept = 0; + ErrorObjBase* copy(void* to) const override { return constructImpl(to, err); } + ErrorObjBase* move(void* to) noexcept override { return constructImpl(to, std::move(err)); } + void tidy() noexcept override { destroyImpl(this); } + std::type_info const& type() const noexcept override { return typeid(Err); } + void const* get() const noexcept override { return std::addressof(err); } + std::string message() noexcept override { + if constexpr (requires { + { err.message() } -> concepts::IsString; + }) { + return err.message(); + } else if constexpr (requires { + { err.what() } -> concepts::IsString; + }) { + return err.what(); + } else { + return err; + } + } }; + class Error { - mutable std::unique_ptr mInfo; + ErrorObjBase* dataPtr{}; + void* extraData{}; + union { + std::max_align_t dummy; + char soo[ErrorObjBase::smallObjSize]; + }; + + constexpr bool isLarge() const noexcept { return dataPtr != static_cast(&soo); } + + constexpr bool hasValue() const noexcept { return dataPtr; } + + LLAPI static void* createExtraData() noexcept; + LLAPI static void destroyExtraData(void*) noexcept; + LLAPI static void* copyExtraData(void*) noexcept; + + void tidy() noexcept { + destroyExtraData(extraData); + extraData = nullptr; + if (hasValue()) { + dataPtr->tidy(); + dataPtr = nullptr; + } + } + void copy(Error const& other) { + extraData = copyExtraData(other.extraData); + if (other.hasValue()) { + dataPtr = other.dataPtr->copy(&soo); + } + } + constexpr void move(Error&& other) noexcept { + extraData = other.extraData; + other.extraData = nullptr; + if (other.hasValue()) { + if (other.isLarge()) { + dataPtr = other.dataPtr; + other.dataPtr = nullptr; + } else { + dataPtr = other.dataPtr->move(&soo); + other.tidy(); + } + } + } public: - Error& operator=(Error&&) noexcept = default; - Error& operator=(Error const&) noexcept = delete; - [[nodiscard]] Error(Error&&) noexcept = default; - [[nodiscard]] Error(Error const&) noexcept = delete; + constexpr Error() noexcept {} + ~Error() { tidy(); } + + Error(Error const& other) { copy(other); } + Error& operator=(Error const& other) { + if (this != std::addressof(other)) { + tidy(); + copy(other); + } + return *this; + } - LL_CONSTEXPR23 Error() noexcept = default; - LL_CONSTEXPR23 ~Error() noexcept = default; + constexpr Error(Error&& other) noexcept { move(std::move(other)); } + constexpr Error& operator=(Error&& other) noexcept { + if (this != std::addressof(other)) { + tidy(); + move(std::move(other)); + } + return *this; + } - LL_CONSTEXPR23 Error(std::unique_ptr i) noexcept : mInfo(std::move(i)) {} + template + Error(std::in_place_type_t, Args&&... args) + : extraData(createExtraData()), + dataPtr(ErrorObj::construct(&soo, std::forward(args)...)) {} - LL_CONSTEXPR23 Error(::nonstd::unexpected_type<::ll::Error> i) noexcept : Error(std::move(i.value())) {} + Error(::nonstd::unexpected_type<::ll::Error> i) noexcept : Error(std::move(i.value())) {} - LL_CONSTEXPR23 operator bool() const noexcept { return mInfo != nullptr; } + constexpr operator bool() const noexcept { return hasValue(); } - LL_CONSTEXPR23 operator Unexpected() noexcept { - return ::nonstd::make_unexpected(std::in_place, std::move(mInfo)); - } + operator Unexpected() noexcept { return ::nonstd::make_unexpected(std::move(*this)); } LLNDAPI std::string message() const noexcept; + std::type_info const& type() const noexcept { return hasValue() ? dataPtr->type() : typeid(void); } + template - LL_CONSTEXPR23 bool isA() noexcept { - return mInfo ? typeid(T) == typeid(mInfo.get()) : false; + constexpr bool isA() noexcept { + return typeid(T) == type(); } template - LL_CONSTEXPR23 T& as() noexcept { - return *static_cast(mInfo.get()); + constexpr T& as() noexcept { + return *(T*)(dataPtr->get()); } LLAPI Error& join(Error) noexcept; @@ -78,57 +182,39 @@ class Error { LLAPI Error const& log(CommandOutput&, CommandOutputMessageType = CommandOutputMessageType::Error) const noexcept; }; -struct StringError : ErrorInfoBase { - std::string str; - StringError(std::string str) : str(std::move(str)) {} - std::string message() const noexcept override { return str; } -}; -struct ErrorCodeError : ErrorInfoBase { - std::error_code ec; - ErrorCodeError(std::error_code ec) : ec(ec) {} - std::string message() const noexcept override { return ec.message(); } -}; inline Unexpected forwardError(::ll::Error& err) noexcept { return ::nonstd::make_unexpected(std::move(err)); } inline Unexpected makeSuccessed() noexcept { return ::nonstd::make_unexpected(Error{}); } -template T, class... Args> +template inline Unexpected makeError(Args&&... args) noexcept { - return ::nonstd::make_unexpected(std::in_place, std::make_unique(std::forward(args)...)); + return ::nonstd::make_unexpected(std::in_place, std::in_place_type, std::forward(args)...); } -inline Unexpected makeStringError(std::string str) noexcept { return makeError(std::move(str)); } +inline Unexpected makeStringError(std::string str) noexcept { return makeError(std::move(str)); } -inline Unexpected makeErrorCodeError(std::error_code ec) noexcept { return makeError(ec); } +inline Unexpected makeErrorCodeError(std::error_code ec) noexcept { return makeError(ec); } -inline Unexpected makeErrorCodeError(std::errc ec) noexcept { return makeError(make_error_code(ec)); } +inline Unexpected makeErrorCodeError(std::errc ec) noexcept { return makeErrorCodeError(make_error_code(ec)); } LLNDAPI Unexpected makeExceptionError(std::exception_ptr const& exc = std::current_exception()) noexcept; } // namespace ll -namespace nonstd::expected_lite { template <> -class bad_expected_access<::ll::Error> : public bad_expected_access { - std::shared_ptr<::ll::Error> mError; - std::string mMessage; +class nonstd::expected_lite::bad_expected_access<::ll::Error> : public bad_expected_access { + ::ll::Error mError; + std::string mMessage; public: - explicit bad_expected_access(::ll::Error& e) noexcept - : mError(::std::make_shared<::ll::Error>(::std::move(e))), - mMessage(mError->message()) {} + explicit bad_expected_access(::ll::Error e) noexcept : mError(::std::move(e)), mMessage(mError.message()) {} char const* what() const noexcept override { return mMessage.c_str(); } - ::ll::Error& error() & { return *mError; } + ::ll::Error& error() & { return mError; } - ::ll::Error const& error() const& { return *mError; } + ::ll::Error const& error() const& { return mError; } - ::ll::Error&& error() && { return ::std::move(*mError); } + ::ll::Error&& error() && { return ::std::move(mError); } - ::ll::Error const&& error() const&& { return ::std::move(*mError); } -}; -template <> -struct error_traits<::ll::Error> { - static void rethrow(::ll::Error const& e) { throw bad_expected_access<::ll::Error>{const_cast<::ll::Error&>(e)}; } + ::ll::Error const&& error() const&& { return ::std::move(mError); } }; -} // namespace nonstd::expected_lite diff --git a/src/ll/api/base/CompilerPredefine.h b/src/ll/api/base/CompilerPredefine.h index 7781166089..119c0eb4d3 100644 --- a/src/ll/api/base/CompilerPredefine.h +++ b/src/ll/api/base/CompilerPredefine.h @@ -33,6 +33,10 @@ #define LL_FORCEINLINE __forceinline #endif +#ifndef LL_NOINLINE +#define LL_NOINLINE __declspec(noinline) +#endif + #ifndef LL_CONSTEXPR23 #define LL_CONSTEXPR23 _CONSTEXPR23 #endif @@ -252,6 +256,10 @@ using FileHandleT = void*; #define LL_FORCEINLINE inline __attribute__((always_inline)) #endif +#ifndef LL_NOINLINE +#define LL_NOINLINE __attribute__((noinline)) +#endif + #ifndef LL_CONSTEXPR23 #if defined(__cpp_constexpr) && __cpp_constexpr >= 202211L #define LL_CONSTEXPR23 constexpr diff --git a/src/ll/api/base/Containers.h b/src/ll/api/base/Containers.h index e286226c65..af917b5f37 100644 --- a/src/ll/api/base/Containers.h +++ b/src/ll/api/base/Containers.h @@ -8,7 +8,6 @@ #include #include "ll/api/data/ConcurrentQueue.h" -#include "ll/api/data/IndirectValue.h" #include "parallel_hashmap/btree.h" #include "parallel_hashmap/phmap.h" @@ -110,27 +109,7 @@ using StringNodeMap = DenseNodeMap<::std::string, Value>; template using SmallStringNodeMap = SmallDenseNodeMap<::std::string, Value>; - template > using ConcurrentQueue = data::concurrent_queue; - -template > -using Indirect = data::IndirectValue, D>; -template < - class T, - class C = - std::conditional_t, data::virtualCloneCopy, data::polymorphicCopy>, - class D = std::default_delete> -using Polymorphic = data::IndirectValue; - -template -Indirect makeIndirect(Args&&... args) { - return Indirect(new T(std::forward(args)...)); -} -template -Polymorphic makePolymorphic(Args&&... args) { - return Polymorphic(new T(std::forward(args)...)); -} - } // namespace ll diff --git a/src/ll/api/base/Meta.h b/src/ll/api/base/Meta.h index 4a928fffff..8b27b96bf9 100644 --- a/src/ll/api/base/Meta.h +++ b/src/ll/api/base/Meta.h @@ -55,6 +55,7 @@ struct VisitStrategy { } }; +#ifndef LL_VISIT_CASE #define LL_VISIT_CASE(n) \ case (n): \ if constexpr ((n) < N) { \ @@ -137,6 +138,7 @@ struct VisitStrategy { #undef LL_STAMP64 #undef LL_STAMP16 #undef LL_STAMP4 +#endif template using VisitIndexResultT = decltype((std::declval().template operator()<0>(std::declval()...))); @@ -198,50 +200,50 @@ constexpr Ret visitIndex(size_t index, Fn&& fn, Args&&... args) { return Strategy::template impl(index, std::forward(fn), std::forward(args)...); } -template +template class TypeList { public: template - static constexpr bool contains = (std::is_same_v || ...); + static constexpr bool contains = (std::is_same_v || ...); template