diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index 316ca5d3..423779fa 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -36,24 +36,12 @@ class DXFeedSubscription : public std::enable_shared_from_thisisEmpty()) { - return; - } - - std::size_t i = 0; - - for (auto it = begin; it != end; it++, i++) { - list->set(i, it->getId()); - } - handler_ = createSubscriptionHandlerFromEventClassList(list); } diff --git a/include/dxfeed_graal_cpp_api/internal/Common.hpp b/include/dxfeed_graal_cpp_api/internal/Common.hpp index bdf7d05b..af1ac906 100644 --- a/include/dxfeed_graal_cpp_api/internal/Common.hpp +++ b/include/dxfeed_graal_cpp_api/internal/Common.hpp @@ -3,7 +3,13 @@ #pragma once -#define DXFCPP_DEBUG_ISOLATES +#ifndef DXFCPP_TRACE_ISOLATES +# define DXFCPP_TRACE_ISOLATES 0 +#endif + +#ifndef DXFCPP_TRACE_LISTS +# define DXFCPP_TRACE_LISTS 1 +#endif #ifdef __cpp_lib_bit_cast # include @@ -32,14 +38,21 @@ struct DXEndpointStateChangeListener {}; #if defined(NDEBUG) && !defined(DXFCPP_DEBUG) constexpr bool isDebug = false; -constexpr bool isDebugIsolates = false; +constexpr bool traceIsolates = false; +constexpr bool traceLists = false; #else constexpr bool isDebug = true; -# ifdef DXFCPP_DEBUG_ISOLATES -constexpr bool isDebugIsolates = true; +# if DXFCPP_TRACE_ISOLATES == 1 +constexpr bool traceIsolates = true; # else -constexpr bool isDebugIsolates = false; +constexpr bool traceIsolates = false; +# endif + +# if DXFCPP_TRACE_LISTS == 1 +constexpr bool traceLists = true; +# else +constexpr bool traceLists = false; # endif #endif @@ -154,10 +167,22 @@ inline std::string debugPrefixStr() { return fmt::format("D {} [{}]", nowStr(), tid.str()); } +inline std::string tracePrefixStr() { + std::ostringstream tid{}; + + tid << std::this_thread::get_id(); + + return fmt::format("T {} [{}]", nowStr(), tid.str()); +} + template inline void debug(std::string_view format, Args &&...args) { vprint(std::cerr, "{} {}\n", debugPrefixStr(), vformat(format, std::forward(args)...)); } +template inline void trace(std::string_view format, Args &&...args) { + vprint(std::cerr, "{} ~~ {}\n", tracePrefixStr(), vformat(format, std::forward(args)...)); +} + namespace handler_utils { template struct JavaObjectHandler { @@ -185,7 +210,28 @@ template struct JavaObjectHandler { }; struct EventClassList { - static std::unique_ptr create(std::size_t size) noexcept; + template + static std::unique_ptr create(EventTypeIt begin, EventTypeIt end) noexcept { + auto size = std::distance(begin, end); + + if (size <= 0) { + return {}; + } + + auto list = handler_utils::EventClassList::create(size); + + if (list->isEmpty()) { + return {}; + } + + std::size_t i = 0; + + for (auto it = begin; it != end; it++, i++) { + list->set(i, it->getId()); + } + + return list; + } void set(std::size_t index, std::uint32_t id) noexcept; @@ -198,6 +244,8 @@ struct EventClassList { ~EventClassList() noexcept; private: + static std::unique_ptr create(std::size_t size) noexcept; + EventClassList() noexcept; struct Impl; diff --git a/include/dxfeed_graal_cpp_api/internal/Isolate.hpp b/include/dxfeed_graal_cpp_api/internal/Isolate.hpp index 9671d777..2d21b303 100644 --- a/include/dxfeed_graal_cpp_api/internal/Isolate.hpp +++ b/include/dxfeed_graal_cpp_api/internal/Isolate.hpp @@ -36,21 +36,21 @@ class Isolate final { this->idx = idx++; - if constexpr (isDebugIsolates) { - debug("IsolateThread{{{}, isMain = {}, tid = {}, idx = {}}}()", bit_cast(handle), isMain, + if constexpr (traceIsolates) { + trace("IsolateThread{{{}, isMain = {}, tid = {}, idx = {}}}()", bit_cast(handle), isMain, tid, idx); } } CEntryPointErrors detach() noexcept { - if constexpr (isDebugIsolates) { - debug("{}::detach()", toString()); + if constexpr (traceIsolates) { + trace("{}::detach()", toString()); } // OK if nothing is attached. if (!handle) { - if constexpr (isDebugIsolates) { - debug("\tNot attached"); + if constexpr (traceIsolates) { + trace("\tNot attached"); } return CEntryPointErrors::NO_ERROR; @@ -59,8 +59,8 @@ class Isolate final { auto result = CEntryPointErrors::valueOf(graal_detach_thread(handle)); if (result == CEntryPointErrors::NO_ERROR) { - if constexpr (isDebugIsolates) { - debug("\tDetached"); + if constexpr (traceIsolates) { + trace("\tDetached"); } handle = nullptr; @@ -70,13 +70,13 @@ class Isolate final { } CEntryPointErrors detachAllThreadsAndTearDownIsolate() noexcept { - if constexpr (isDebugIsolates) { - debug("{}::detachAllThreadsAndTearDownIsolate()", toString()); + if constexpr (traceIsolates) { + trace("{}::detachAllThreadsAndTearDownIsolate()", toString()); } if (!handle) { - if constexpr (isDebugIsolates) { - debug("\tNot attached"); + if constexpr (traceIsolates) { + trace("\tNot attached"); } return CEntryPointErrors::NO_ERROR; @@ -85,8 +85,8 @@ class Isolate final { auto result = CEntryPointErrors::valueOf(graal_detach_all_threads_and_tear_down_isolate(handle)); if (result == CEntryPointErrors::NO_ERROR) { - if constexpr (isDebugIsolates) { - debug("\tAll threads have been detached. The isolate has been teared down."); + if constexpr (traceIsolates) { + trace("\tAll threads have been detached. The isolate has been teared down."); } handle = nullptr; @@ -96,13 +96,13 @@ class Isolate final { } ~IsolateThread() noexcept { - if constexpr (isDebugIsolates) { - debug("~{}()", toString()); + if constexpr (traceIsolates) { + trace("~{}()", toString()); } if (isMain) { - if constexpr (isDebugIsolates) { - debug("\tThis is the main thread"); + if constexpr (traceIsolates) { + trace("\tThis is the main thread"); } return; @@ -128,15 +128,15 @@ class Isolate final { currentIsolateThread_.handle = mainIsolateThreadHandle; currentIsolateThread_.isMain = true; - if constexpr (isDebugIsolates) { - debug("Isolate{{{}, main = {}, current = {}}}()", bit_cast(handle), + if constexpr (traceIsolates) { + trace("Isolate{{{}, main = {}, current = {}}}()", bit_cast(handle), mainIsolateThread_.toString(), currentIsolateThread_.toString()); } } static std::shared_ptr create() noexcept { - if constexpr (isDebugIsolates) { - debug("Isolate::create()"); + if constexpr (traceIsolates) { + trace("Isolate::create()"); } GraalIsolateHandle graalIsolateHandle{}; @@ -147,29 +147,29 @@ class Isolate final { auto result = std::shared_ptr{new Isolate{graalIsolateHandle, graalIsolateThreadHandle}}; - if constexpr (isDebugIsolates) { - debug("Isolate::create() -> *{}", result->toString()); + if constexpr (traceIsolates) { + trace("Isolate::create() -> *{}", result->toString()); } return result; } - if constexpr (isDebugIsolates) { - debug("\t-> nullptr"); + if constexpr (traceIsolates) { + trace("\t-> nullptr"); } return nullptr; } CEntryPointErrors attach() noexcept { - if constexpr (isDebugIsolates) { - debug("{}::attach()", toString()); + if constexpr (traceIsolates) { + trace("{}::attach()", toString()); } // We will not re-attach. if (!currentIsolateThread_.handle) { - if constexpr (isDebugIsolates) { - debug("\tNeeds to be attached."); + if constexpr (traceIsolates) { + trace("\tNeeds to be attached."); } GraalIsolateThreadHandle newIsolateThreadHandle{}; @@ -177,8 +177,8 @@ class Isolate final { if (auto result = CEntryPointErrors::valueOf(graal_attach_thread(handle_, &newIsolateThreadHandle)); result != CEntryPointErrors::NO_ERROR) { - if constexpr (isDebugIsolates) { - debug("\t-> {}", result.getDescription()); + if constexpr (traceIsolates) { + trace("\t-> {}", result.getDescription()); } return result; @@ -187,12 +187,12 @@ class Isolate final { currentIsolateThread_.handle = newIsolateThreadHandle; currentIsolateThread_.isMain = mainIsolateThread_.handle == newIsolateThreadHandle; - if constexpr (isDebugIsolates) { - debug("\tAttached: {}", currentIsolateThread_.toString()); + if constexpr (traceIsolates) { + trace("\tAttached: {}", currentIsolateThread_.toString()); } } else { - if constexpr (isDebugIsolates) { - debug("\tCached: {}", currentIsolateThread_.toString()); + if constexpr (traceIsolates) { + trace("\tCached: {}", currentIsolateThread_.toString()); } } @@ -200,8 +200,8 @@ class Isolate final { } GraalIsolateThreadHandle get() noexcept { - if constexpr (isDebugIsolates) { - debug("{}::get()", toString()); + if constexpr (traceIsolates) { + trace("{}::get()", toString()); } return graal_get_current_thread(handle_); @@ -213,14 +213,14 @@ class Isolate final { Isolate &operator=(const Isolate &) = delete; static std::shared_ptr getInstance() noexcept { - if constexpr (isDebugIsolates) { - debug("Isolate::getInstance()"); + if constexpr (traceIsolates) { + trace("Isolate::getInstance()"); } static std::shared_ptr instance = create(); - if constexpr (isDebugIsolates) { - debug("Isolate::getInstance() -> *{}", instance->toString()); + if constexpr (traceIsolates) { + trace("Isolate::getInstance() -> *{}", instance->toString()); } return instance; @@ -228,8 +228,8 @@ class Isolate final { template auto runIsolated(F &&f) -> std::variant> { - if constexpr (isDebugIsolates) { - debug("{}::runIsolated({})", toString(), bit_cast(&f)); + if constexpr (traceIsolates) { + trace("{}::runIsolated({})", toString(), bit_cast(&f)); } // Perhaps the code is already running within the GraalVM thread (for example, we are in a listener) @@ -238,8 +238,8 @@ class Isolate final { } if (auto result = attach(); result != CEntryPointErrors::NO_ERROR) { - if constexpr (isDebugIsolates) { - debug("\t-> {}", result.getDescription()); + if constexpr (traceIsolates) { + trace("\t-> {}", result.getDescription()); } return result; @@ -266,8 +266,8 @@ class Isolate final { } ~Isolate() { - if constexpr (isDebugIsolates) { - debug("~Isolate()"); + if constexpr (traceIsolates) { + trace("~Isolate()"); } } diff --git a/src/internal/Common.cpp b/src/internal/Common.cpp index 1e267fb2..44d430ad 100644 --- a/src/internal/Common.cpp +++ b/src/internal/Common.cpp @@ -27,36 +27,99 @@ template void JavaObjectHandler::deleter(void *handler) noexcept false); } -struct EventClassList::Impl { - dxfg_event_clazz_list_t list_; +//TODO: RawListSizeType +template +struct RawListWrapper { + mutable RawListType list_; + + RawListWrapper() noexcept : list_{0, nullptr} { + if constexpr (traceLists) { + trace("RawListWrapper<{}, {}, {}, {}>::()", typeid(RawListType).name(), typeid(RawListElementType).name(), + typeid(IndexType).name(), typeid(ValueType).name()); + } + } - Impl() noexcept : list_{0, nullptr} {} + void set(IndexType index, ValueType value) const noexcept { + if constexpr (traceLists) { + trace("RawListWrapper<{}, {}, {}, {}>::set({}, {})", typeid(RawListType).name(), + typeid(RawListElementType).name(), typeid(IndexType).name(), typeid(ValueType).name(), index, value); + } - void set(std::size_t index, std::uint32_t id) const noexcept { if (list_.size == 0) { + if constexpr (traceLists) { + trace("RawListWrapper<{}, {}, {}, {}>::set({}, {}): list_.size == 0 ", typeid(RawListType).name(), + typeid(RawListElementType).name(), typeid(IndexType).name(), typeid(ValueType).name(), index, + value); + } + return; } if (index < list_.size) { - *list_.elements[index] = static_cast(id); + if constexpr (traceLists) { + trace("RawListWrapper<{}, {}, {}, {}>::set({}, {}): index < list_.size ", typeid(RawListType).name(), + typeid(RawListElementType).name(), typeid(IndexType).name(), typeid(ValueType).name(), index, + value); + } + + ElementSetter(list_, index, value); } } - [[nodiscard]] bool isEmpty() const noexcept { return list_.size == 0; } + [[nodiscard]] bool isEmpty() const noexcept { + if constexpr (traceLists) { + trace("RawListWrapper<{}, {}, {}, {}>::isEmpty() -> ", typeid(RawListType).name(), + typeid(RawListElementType).name(), typeid(IndexType).name(), typeid(ValueType).name(), + (list_.size == 0)); + } - [[nodiscard]] std::size_t size() const noexcept { return static_cast(list_.size); } + return list_.size == 0; + } - void *getHandler() noexcept { return bit_cast(&list_); } + [[nodiscard]] IndexType size() const noexcept { + if constexpr (traceLists) { + trace("RawListWrapper<{}, {}, {}, {}>::size() -> ", typeid(RawListType).name(), + typeid(RawListElementType).name(), typeid(IndexType).name(), typeid(ValueType).name(), + (static_cast(list_.size))); + } + + return static_cast(list_.size); + } + + void *getHandler() noexcept { + if constexpr (traceLists) { + trace("RawListWrapper<{}, {}, {}, {}>::getHandler() -> ", typeid(RawListType).name(), + typeid(RawListElementType).name(), typeid(IndexType).name(), typeid(ValueType).name(), + (bit_cast(&list_))); + } + + return bit_cast(&list_); + } + + void init(IndexType size) noexcept { + if constexpr (traceLists) { + trace("RawListWrapper<{}, {}, {}, {}>::init({})", typeid(RawListType).name(), + typeid(RawListElementType).name(), typeid(IndexType).name(), typeid(ValueType).name(), size); + } - void init(std::uint32_t size) noexcept { if (size <= 0) { + if constexpr (traceLists) { + trace("RawListWrapper<{}, {}, {}, {}>::init({}): size <= 0", typeid(RawListType).name(), + typeid(RawListElementType).name(), typeid(IndexType).name(), typeid(ValueType).name()); + } + return; } list_.size = static_cast(size); - list_.elements = new (std::nothrow) dxfg_event_clazz_t *[list_.size]; + list_.elements = new (std::nothrow) RawListElementType *[list_.size]; if (!list_.elements) { + if constexpr (traceLists) { + trace("RawListWrapper<{}, {}, {}, {}>::init({}): !list_.elements", typeid(RawListType).name(), + typeid(RawListElementType).name(), typeid(IndexType).name(), typeid(ValueType).name()); + } + release(); return; @@ -65,7 +128,7 @@ struct EventClassList::Impl { bool needToRelease = false; for (std::int32_t i = 0; i < list_.size; i++) { - list_.elements[i] = new (std::nothrow) dxfg_event_clazz_t{}; + list_.elements[i] = new (std::nothrow) RawListElementType{}; if (!list_.elements[i]) { needToRelease = true; @@ -73,12 +136,28 @@ struct EventClassList::Impl { } if (needToRelease) { + if constexpr (traceLists) { + trace("RawListWrapper<{}, {}, {}, {}>::init({}): needToRelease", typeid(RawListType).name(), + typeid(RawListElementType).name(), typeid(IndexType).name(), typeid(ValueType).name()); + } + release(); } } void release() { + if constexpr (traceLists) { + trace("RawListWrapper<{}, {}, {}, {}>::release()", typeid(RawListType).name(), + typeid(RawListElementType).name(), typeid(IndexType).name(), typeid(ValueType).name()); + } + if (list_.size == 0 || list_.elements == nullptr) { + if constexpr (traceLists) { + trace("RawListWrapper<{}, {}, {}, {}>::release(): list_.size == 0 || list_.elements == nullptr", + typeid(RawListType).name(), typeid(RawListElementType).name(), typeid(IndexType).name(), + typeid(ValueType).name()); + } + return; } @@ -91,9 +170,152 @@ struct EventClassList::Impl { list_.elements = nullptr; } - ~Impl() noexcept { release(); } + ~RawListWrapper() noexcept { + if constexpr (traceLists) { + trace("RawListWrapper<{}, {}, {}, {}>::~()", typeid(RawListType).name(), typeid(RawListElementType).name(), + typeid(IndexType).name(), typeid(ValueType).name()); + } + + release(); + } }; +struct EventClassList::Impl : public RawListWrapper(id); + }> {}; + +//struct EventClassList::Impl { +// dxfg_event_clazz_list_t list_; +// +// Impl() noexcept : list_{0, nullptr} { +// if constexpr (traceLists) { +// trace("EventClassList::Impl()"); +// } +// } +// +// void set(std::size_t index, std::uint32_t id) const noexcept { +// if constexpr (traceLists) { +// trace("EventClassList::Impl::set({}, {})", index, id); +// } +// +// if (list_.size == 0) { +// if constexpr (traceLists) { +// trace("EventClassList::Impl::set({}, {}): list_.size == 0 ", index, id); +// } +// +// return; +// } +// +// if (index < list_.size) { +// if constexpr (traceLists) { +// trace("EventClassList::Impl::set({}, {}): index < list_.size ", index, id); +// } +// +// *list_.elements[index] = static_cast(id); +// } +// } +// +// [[nodiscard]] bool isEmpty() const noexcept { +// if constexpr (traceLists) { +// trace("EventClassList::Impl::isEmpty() -> ", (list_.size == 0)); +// } +// +// return list_.size == 0; +// } +// +// [[nodiscard]] std::size_t size() const noexcept { +// if constexpr (traceLists) { +// trace("EventClassList::Impl::size() -> ", (static_cast(list_.size))); +// } +// +// return static_cast(list_.size); +// } +// +// void *getHandler() noexcept { +// if constexpr (traceLists) { +// trace("EventClassList::Impl::getHandler() -> ", (bit_cast(&list_))); +// } +// +// return bit_cast(&list_); +// } +// +// void init(std::uint32_t size) noexcept { +// if constexpr (traceLists) { +// trace("EventClassList::Impl::init({})", size); +// } +// +// if (size <= 0) { +// if constexpr (traceLists) { +// trace("EventClassList::Impl::init({}): size <= 0"); +// } +// +// return; +// } +// +// list_.size = static_cast(size); +// list_.elements = new (std::nothrow) dxfg_event_clazz_t *[list_.size]; +// +// if (!list_.elements) { +// if constexpr (traceLists) { +// trace("EventClassList::Impl::init({}): !list_.elements"); +// } +// +// release(); +// +// return; +// } +// +// bool needToRelease = false; +// +// for (std::int32_t i = 0; i < list_.size; i++) { +// list_.elements[i] = new (std::nothrow) dxfg_event_clazz_t{}; +// +// if (!list_.elements[i]) { +// needToRelease = true; +// } +// } +// +// if (needToRelease) { +// if constexpr (traceLists) { +// trace("EventClassList::Impl::init({}): needToRelease"); +// } +// +// release(); +// } +// } +// +// void release() { +// if constexpr (traceLists) { +// trace("EventClassList::Impl::release()"); +// } +// +// if (list_.size == 0 || list_.elements == nullptr) { +// if constexpr (traceLists) { +// trace("EventClassList::Impl::release(): list_.size == 0 || list_.elements == nullptr"); +// } +// +// return; +// } +// +// for (auto i = list_.size - 1; i >= 0; i--) { +// delete list_.elements[i]; +// } +// +// delete[] list_.elements; +// list_.size = 0; +// list_.elements = nullptr; +// } +// +// ~Impl() noexcept { +// if constexpr (traceLists) { +// trace("EventClassList::Impl::~()"); +// } +// +// release(); +// } +//}; + template struct handler_utils::JavaObjectHandler; template struct handler_utils::JavaObjectHandler; template struct handler_utils::JavaObjectHandler; @@ -119,9 +341,9 @@ std::size_t EventClassList::size() const noexcept { return impl_->size(); } void *EventClassList::getHandler() noexcept { return impl_->getHandler(); } -EventClassList::~EventClassList() noexcept {} +EventClassList::~EventClassList() noexcept = default; -} +} // namespace handler_utils std::string toString(const char *chars) { if (chars == nullptr) { @@ -159,4 +381,4 @@ std::int16_t utf8to16(char in) { } } -} \ No newline at end of file +} // namespace dxfcpp \ No newline at end of file