From 21bf8f67c4c9be2c62756a1b4300974d11bdf914 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Thu, 23 May 2024 23:52:56 +0300 Subject: [PATCH 01/28] [EN-7587] Implement FetchDailyCandles sample --- CMakeLists.txt | 1 + samples/cpp/FetchDailyCandles/CMakeLists.txt | 56 +++++++++++++++++++ .../cpp/FetchDailyCandles/dxfeed.properties | 5 ++ samples/cpp/FetchDailyCandles/src/main.cpp | 56 +++++++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 samples/cpp/FetchDailyCandles/CMakeLists.txt create mode 100644 samples/cpp/FetchDailyCandles/dxfeed.properties create mode 100644 samples/cpp/FetchDailyCandles/src/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 16422d2ae..8152c3339 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -468,6 +468,7 @@ if (DXFCXX_BUILD_SAMPLES) add_subdirectory(samples/cpp/PrintQuoteEvents) add_subdirectory(samples/cpp/PublishProfiles) add_subdirectory(samples/cpp/DxFeedSample) + add_subdirectory(samples/cpp/FetchDailyCandles) add_subdirectory(samples/cpp/WriteTapeFile) add_subdirectory(samples/cpp/ConvertTapeFile) add_subdirectory(samples/cpp/DxFeedFileParser) diff --git a/samples/cpp/FetchDailyCandles/CMakeLists.txt b/samples/cpp/FetchDailyCandles/CMakeLists.txt new file mode 100644 index 000000000..e934ceab0 --- /dev/null +++ b/samples/cpp/FetchDailyCandles/CMakeLists.txt @@ -0,0 +1,56 @@ +# Copyright (c) 2024 Devexperts LLC. +# SPDX-License-Identifier: MPL-2.0 + +cmake_minimum_required(VERSION 3.21) + +if (POLICY CMP0092) + cmake_policy(SET CMP0092 NEW) +endif () + +if (POLICY CMP0135) + cmake_policy(SET CMP0135 NEW) +endif () + +project(FetchDailyCandles LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_C_STANDARD 11) +set(CXX_EXTENSIONS OFF) +set(C_EXTENSIONS OFF) + +if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(CMAKE_MACOSX_RPATH ON) + set(CMAKE_SKIP_BUILD_RPATH ON) + set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH OFF) + set(CMAKE_BUILD_RPATH_USE_ORIGIN ON) + set(CMAKE_INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR};@loader_path;@executable_path;@executable_path/../Frameworks") +elseif (UNIX) + set(CMAKE_SKIP_BUILD_RPATH ON) + set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH OFF) + set(CMAKE_BUILD_RPATH_USE_ORIGIN ON) + set(CMAKE_INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:$ORIGIN/../lib64:$ORIGIN/../lib:$ORIGIN") +endif () + +add_executable(${PROJECT_NAME} src/main.cpp) + +target_link_libraries(${PROJECT_NAME} PRIVATE dxfcxx::static) + +if (DXFCXX_FEATURE_STACKTRACE) + LinkStacktrace(${PROJECT_NAME}) +endif () + +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different + $ + ${CMAKE_CURRENT_SOURCE_DIR}/dxfeed.properties + $) + +if (DXFCXX_INSTALL AND DXFCXX_INSTALL_SAMPLES) + install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}/${PROJECT_NAME}) + install(FILES "dxfeed.properties" DESTINATION ${CMAKE_INSTALL_BINDIR}/${PROJECT_NAME}) + + if (WIN32) + install(FILES $ DESTINATION ${CMAKE_INSTALL_BINDIR}/${PROJECT_NAME}) + endif () +endif () \ No newline at end of file diff --git a/samples/cpp/FetchDailyCandles/dxfeed.properties b/samples/cpp/FetchDailyCandles/dxfeed.properties new file mode 100644 index 000000000..6d1f9e30b --- /dev/null +++ b/samples/cpp/FetchDailyCandles/dxfeed.properties @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Devexperts LLC. +# SPDX-License-Identifier: MPL-2.0 + +# Connection address for an endpoint with role Feed and OnDemandFeed. +dxfeed.address=demo.dxfeed.com:7300 diff --git a/samples/cpp/FetchDailyCandles/src/main.cpp b/samples/cpp/FetchDailyCandles/src/main.cpp new file mode 100644 index 000000000..9ef1f6726 --- /dev/null +++ b/samples/cpp/FetchDailyCandles/src/main.cpp @@ -0,0 +1,56 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include + +void fetchAndPrint(const dxfcpp::CandleSymbol &candleSymbol, std::int64_t toTime, std::int64_t fromTime) { + // Use default DXFeed instance for that data feed address is defined by dxfeed.properties file + // auto result = dxfcpp::DXFeed::getInstance() + // ->getTimeSeriesPromise(candleSymbol, fromTime, toTime) + // ->await(std::chrono::seconds(5)); + // + // for (auto candle : result) { + // std::cout << candle->toString(); + // } +} + +// Fetches last 20 days of candles for a specified symbol, prints them, and exits. +int main(int argc, char *argv[]) { + static const auto DAYS = 20; + + using namespace dxfcpp; + using namespace std::string_literals; + + try { + if (argc < 2) { + std::cout << R"( +Usage: +FetchDailyCandles + +Where: + baseSymbol - Is security symbol (e.g. IBM, AAPL, SPX etc.) +)"; + return 0; + } + + // Specified instrument name, for example AAPL, IBM, MSFT, etc. + auto baseSymbol = argv[1]; + + auto candleSymbol = CandleSymbol::valueOf(baseSymbol, CandlePeriod::DAY); + auto toTime = dxfcpp::now(); + auto fromTime = toTime - std::chrono::duration_cast(std::chrono::days(DAYS)).count(); + + std::cout << "Fetching last " << DAYS << " days of candles for " << baseSymbol << "\n"; + + fetchAndPrint(candleSymbol, toTime, fromTime); + } catch (const JavaException &e) { + std::cerr << e.what() << '\n'; + std::cerr << e.getStackTrace() << '\n'; + } catch (const GraalException &e) { + std::cerr << e.what() << '\n'; + std::cerr << e.getStackTrace() << '\n'; + } +} From 28d66167e8094e8696c1dc32f015e2cd40408c57 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Mon, 27 May 2024 02:28:25 +0300 Subject: [PATCH 02/28] [EN-7587] Implement FetchDailyCandles sample --- include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index 79174fa86..d55754ae9 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -4,6 +4,7 @@ #pragma once #include "../internal/Conf.hpp" +#include "osub/ObservableSubscription.hpp" DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) @@ -34,7 +35,7 @@ struct LastingEvent; /** * Subscription for a set of symbols and event types. */ -class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity { +class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableSubscription { friend struct DXFeed; std::unordered_set eventTypes_; From 77fe5b149a2cf80fe690c11a5354ed05ef4c12db Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 27 May 2024 18:10:55 +0300 Subject: [PATCH 03/28] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeedSubscription --- CMakeLists.txt | 1 + .../api/DXFeedSubscription.hpp | 53 ++++++------ .../api/DXPublisherObservableSubscription.hpp | 2 +- .../ObservableSubscriptionChangeListener.hpp | 1 + .../api/IsolatedDXFeedSubscription.hpp | 81 +++++++++++++++++++ src/api/DXFeedSubscription.cpp | 38 ++++++++- src/api/DXPublisherObservableSubscription.cpp | 6 +- .../api/IsolatedDXFeedSubscription.cpp | 14 ++++ 8 files changed, 163 insertions(+), 33 deletions(-) create mode 100644 include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp create mode 100644 src/isolated/api/IsolatedDXFeedSubscription.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8152c3339..80efdc7fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,6 +191,7 @@ set(dxFeedGraalCxxApi_Exceptions_Sources set(dxFeedGraalCxxApi_Isolated_Sources src/isolated/api/IsolatedDXEndpoint.cpp + src/isolated/api/IsolatedDXFeedSubscription.cpp src/isolated/api/IsolatedDXPublisher.cpp src/isolated/api/IsolatedDXPublisherObservableSubscription.cpp src/isolated/api/osub/IsolatedObservableSubscriptionChangeListener.cpp diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index d55754ae9..9a3716154 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -35,17 +35,25 @@ struct LastingEvent; /** * Subscription for a set of symbols and event types. */ -class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableSubscription { +class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared, public ObservableSubscription { +public: + static constexpr std::size_t FAKE_CHANGE_LISTENER_ID{static_cast(-1)}; + +private: friend struct DXFeed; + inline static std::atomic lastChangeListenerId_{}; + std::unordered_set eventTypes_; JavaObjectHandle handle_; - std::mutex listenerMutex_{}; + std::mutex eventListenerMutex_{}; JavaObjectHandle eventListenerHandle_; SimpleHandler> &)> onEvent_{}; + std::unordered_map> changeListeners_; + std::recursive_mutex changeListenersMutex_{}; - explicit DXFeedSubscription(const EventTypeEnum &eventType); + DXFeedSubscription(LockExternalConstructionTag, const EventTypeEnum &eventType); static JavaObjectHandle createSubscriptionHandleFromEventClassList(const std::unique_ptr &list); @@ -60,7 +68,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS { *iter } -> dxfcpp::ConvertibleTo; } #endif - DXFeedSubscription(EventTypeIt begin, EventTypeIt end) + DXFeedSubscription(LockExternalConstructionTag, EventTypeIt begin, EventTypeIt end) : eventTypes_(begin, end), handle_{}, eventListenerHandle_{}, onEvent_{} { if constexpr (Debugger::isDebug) { Debugger::debug("DXFeedSubscription(eventTypes = " + namesToString(begin, end) + ")"); @@ -71,21 +79,21 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS handle_ = createSubscriptionHandleFromEventClassList(list); } - DXFeedSubscription(std::initializer_list eventTypes) - : DXFeedSubscription(eventTypes.begin(), eventTypes.end()) { + DXFeedSubscription(LockExternalConstructionTag tag, std::initializer_list eventTypes) + : DXFeedSubscription(tag, eventTypes.begin(), eventTypes.end()) { } template - explicit DXFeedSubscription(EventTypesCollection &&eventTypes) + explicit DXFeedSubscription(LockExternalConstructionTag tag, EventTypesCollection &&eventTypes) #if __cpp_concepts requires requires { { - DXFeedSubscription(std::begin(std::forward(eventTypes)), + DXFeedSubscription(tag, std::begin(std::forward(eventTypes)), std::end(std::forward(eventTypes))) }; } #endif - : DXFeedSubscription(std::begin(std::forward(eventTypes)), + : DXFeedSubscription(tag, std::begin(std::forward(eventTypes)), std::end(std::forward(eventTypes))) { } @@ -93,7 +101,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS void clearImpl() const noexcept; - bool isClosedImpl() const noexcept; + bool isClosedImpl() const; void addSymbolImpl(void *graalSymbol) const noexcept; @@ -142,7 +150,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS Debugger::debug("DXFeedSubscription::create(eventType = " + eventType.getName() + ")"); } - auto sub = std::shared_ptr(new DXFeedSubscription(eventType)); + auto sub = createShared(eventType); auto id = ApiContext::getInstance()->getManager()->registerEntity(sub); dxfcpp::ignore_unused(id); @@ -182,7 +190,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS Debugger::debug("DXFeedSubscription::create(eventTypes = " + namesToString(begin, end) + ")"); } - auto sub = std::shared_ptr(new DXFeedSubscription(begin, end)); + auto sub = createShared(begin, end); auto id = ApiContext::getInstance()->getManager()->registerEntity(sub); dxfcpp::ignore_unused(id); @@ -202,7 +210,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS * @return The new detached subscription for the given collection of event types. */ static std::shared_ptr create(std::initializer_list eventTypes) { - auto sub = std::shared_ptr(new DXFeedSubscription(eventTypes)); + auto sub = createShared(eventTypes); auto id = ApiContext::getInstance()->getManager()->registerEntity(sub); dxfcpp::ignore_unused(id); @@ -230,8 +238,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS */ template static std::shared_ptr create(EventTypesCollection &&eventTypes) { - auto sub = - std::shared_ptr(new DXFeedSubscription(std::forward(eventTypes))); + auto sub = createShared(std::forward(eventTypes)); auto id = ApiContext::getInstance()->getManager()->registerEntity(sub); dxfcpp::ignore_unused(id); @@ -672,7 +679,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS * * @see DXFeedSubscription::close() */ - bool isClosed() const noexcept { + bool isClosed() override { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::isClosed()"); } @@ -685,7 +692,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS * * @return A set of subscribed event types. */ - const std::unordered_set &getEventTypes() const noexcept { + std::unordered_set getEventTypes() override { return eventTypes_; } @@ -697,7 +704,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS * * @see DXFeedSubscription::getEventTypes() */ - bool containsEventType(const EventTypeEnum &eventType) const noexcept { + bool containsEventType(const EventTypeEnum &eventType) override { return eventTypes_.contains(eventType); } @@ -737,15 +744,9 @@ class DXFCPP_EXPORT DXFeedSubscription : public SharedEntity, public ObservableS template void setExecutor(Executor &&executor) noexcept; - template std::size_t addChangeListener(ChangeListener &&changeListener) noexcept; - - void removeChangeListener(std::size_t changeListenerId) noexcept; - - auto onSymbolsAdded() noexcept; - - auto onSymbolsRemoved() noexcept; + std::size_t addChangeListener(std::shared_ptr listener) override; - auto onSubscriptionClosed() noexcept; + void removeChangeListener(std::size_t changeListenerId) override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/api/DXPublisherObservableSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXPublisherObservableSubscription.hpp index 01f5b5d36..756d941f7 100644 --- a/include/dxfeed_graal_cpp_api/api/DXPublisherObservableSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXPublisherObservableSubscription.hpp @@ -40,7 +40,7 @@ struct DXFCPP_EXPORT DXPublisherObservableSubscription : RequireMakeShared getEventTypes() override; bool containsEventType(const EventTypeEnum &eventType) override; std::size_t addChangeListener(std::shared_ptr listener) override; - void removeChangeListener(std::size_t id) override; + void removeChangeListener(std::size_t changeListenerId) override; }; DXFCPP_END_NAMESPACE diff --git a/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscriptionChangeListener.hpp b/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscriptionChangeListener.hpp index d28974ebd..e04315a2e 100644 --- a/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscriptionChangeListener.hpp +++ b/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscriptionChangeListener.hpp @@ -8,6 +8,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include "../../symbols/SymbolWrapper.hpp" +#include "../entity/SharedEntity.hpp" #include #include diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp new file mode 100644 index 000000000..adf9e64e6 --- /dev/null +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp @@ -0,0 +1,81 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../../internal/Conf.hpp" + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +#include + +#include "../../api/DXFeedSubscription.hpp" + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::api::IsolatedDXFeedSubscription { + +/* +dxfg_subscription_t* dxfg_DXFeedSubscription_new(graal_isolatethread_t *thread, dxfg_event_clazz_t eventClazz); + +dxfg_subscription_t* dxfg_DXFeedSubscription_new2(graal_isolatethread_t *thread, dxfg_event_clazz_list_t *eventClazzes); + +int32_t dxfg_DXFeedSubscription_close(graal_isolatethread_t *thread, dxfg_subscription_t *sub); + +int32_t dxfg_DXFeedSubscription_addEventListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_event_listener_t *listener); + +int32_t dxfg_DXFeedSubscription_removeEventListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_event_listener_t *listener); + +int32_t dxfg_DXFeedSubscription_addSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); + +int32_t dxfg_DXFeedSubscription_addSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_list *symbols); + +int32_t dxfg_DXFeedSubscription_removeSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); + +int32_t dxfg_DXFeedSubscription_removeSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_list *symbols); + +int32_t dxfg_DXFeedSubscription_clear(graal_isolatethread_t *thread, dxfg_subscription_t *sub); + +int32_t dxfg_DXFeedSubscription_attach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_t *feed); + +int32_t dxfg_DXFeedSubscription_detach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_t *feed); + +int32_t dxfg_DXFeedSubscription_isClosed(graal_isolatethread_t *thread, dxfg_subscription_t *sub); + +dxfg_event_clazz_list_t* dxfg_DXFeedSubscription_getEventTypes(graal_isolatethread_t *thread, dxfg_subscription_t *sub); + +int32_t dxfg_DXFeedSubscription_containsEventType(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_event_clazz_t eventClazz); + +dxfg_symbol_list* dxfg_DXFeedSubscription_getSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub); + +int32_t dxfg_DXFeedSubscription_setSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); + +int32_t dxfg_DXFeedSubscription_setSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_list *symbols); + +dxfg_symbol_list* dxfg_DXFeedSubscription_getDecoratedSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub); + +dxfg_executor_t* dxfg_DXFeedSubscription_getExecutor(graal_isolatethread_t *thread, dxfg_subscription_t *sub); + +int32_t dxfg_DXFeedSubscription_setExecutor(graal_isolatethread_t *thread, dxfg_executor_t *executor); + +int32_t dxfg_DXFeedSubscription_addChangeListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_observable_subscription_change_listener_t *listener); + +int32_t dxfg_DXFeedSubscription_removeChangeListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_observable_subscription_change_listener_t *listener); + +*/ + +// dxfg_DXFeedSubscription_new +JavaObjectHandle /* dxfg_subscription_t* */ create(/* dxfg_event_clazz_t */ const EventTypeEnum &eventType); + +namespace DXFeedEventListener { + +// dxfg_feed_event_listener_t* dxfg_DXFeedEventListener_new(graal_isolatethread_t *thread, dxfg_feed_event_listener_function user_func, void *user_data); + +} + +} + +DXFCPP_END_NAMESPACE + + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index 98bda917c..e13df7751 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -31,6 +31,38 @@ void DXFeedSubscription::detach(std::shared_ptr feed) noexcept { feed->detachSubscription(sharedAs()); } +std::size_t DXFeedSubscription::addChangeListener(std::shared_ptr listener) { + isolated::api::IsolatedDXFeedSubscription::addChangeListener(handle_, listener->getHandle()); + + std::lock_guard guard{changeListenersMutex_}; + + if (lastChangeListenerId_ >= FAKE_CHANGE_LISTENER_ID - 1) { + return FAKE_CHANGE_LISTENER_ID; + } + + auto id = ++lastChangeListenerId_; + + changeListeners_.emplace(id, listener); + + return id; +} + +void DXFeedSubscription::removeChangeListener(std::size_t changeListenerId) { + std::lock_guard guard{changeListenersMutex_}; + + if (changeListenerId == FAKE_CHANGE_LISTENER_ID) { + return; + } + + if (auto found = changeListeners_.find(changeListenerId); found != changeListeners_.end()) { + auto listener = found->second; + + isolated::api::IsolatedDXFeedSubscription::removeChangeListener(handle_, listener->getHandle()); + + changeListeners_.erase(found); + } +} + void DXFeedSubscription::addSymbolImpl(void *graalSymbol) const noexcept { if (!handle_) { return; @@ -165,7 +197,7 @@ void DXFeedSubscription::clearImpl() const noexcept { false); } -bool DXFeedSubscription::isClosedImpl() const noexcept { +bool DXFeedSubscription::isClosedImpl() const { if (!handle_) { return false; } @@ -177,7 +209,7 @@ bool DXFeedSubscription::isClosedImpl() const noexcept { false); } -DXFeedSubscription::DXFeedSubscription(const EventTypeEnum &eventType) +DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag, const EventTypeEnum &eventType) : eventTypes_{eventType}, handle_{}, eventListenerHandle_{}, onEvent_{} { if constexpr (Debugger::isDebug) { Debugger::debug("DXFeedSubscription(eventType = " + eventType.getName() + ")"); @@ -236,7 +268,7 @@ void DXFeedSubscription::setEventListenerHandle(Id id) { } bool DXFeedSubscription::tryToSetEventListenerHandle() noexcept { - std::lock_guard lock{listenerMutex_}; + std::lock_guard lock{eventListenerMutex_}; if (!eventListenerHandle_) { auto idOpt = diff --git a/src/api/DXPublisherObservableSubscription.cpp b/src/api/DXPublisherObservableSubscription.cpp index 77b2b972c..b1abfd70a 100644 --- a/src/api/DXPublisherObservableSubscription.cpp +++ b/src/api/DXPublisherObservableSubscription.cpp @@ -52,14 +52,14 @@ DXPublisherObservableSubscription::addChangeListener(std::shared_ptrsecond; isolated::api::IsolatedDXPublisherObservableSubscription::removeChangeListener(handle_, listener->getHandle()); diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp new file mode 100644 index 000000000..e6fb61735 --- /dev/null +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -0,0 +1,14 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::api::IsolatedDXFeedSubscription { +} + +DXFCPP_END_NAMESPACE From 3089348e2dbfb273e3c1890e4b2080e49eee9179 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Thu, 30 May 2024 00:49:35 +0300 Subject: [PATCH 04/28] [EN-7587] Implement FetchDailyCandles sample Mute some false positive warnings and fix the typos. --- .../api/DXFeedSubscription.hpp | 18 ++++++++++++++++-- .../api/osub/ObservableSubscription.hpp | 2 +- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index 9a3716154..3e933def3 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -71,6 +71,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared create(const EventTypeEnum &eventType) { if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode Debugger::debug("DXFeedSubscription::create(eventType = " + eventType.getName() + ")"); } @@ -187,6 +190,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared create(EventTypeIt begin, EventTypeIt end) { if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode Debugger::debug("DXFeedSubscription::create(eventTypes = " + namesToString(begin, end) + ")"); } @@ -267,8 +271,9 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared void addSymbols(SymbolIt begin, SymbolIt end) const { if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode Debugger::debug(toString() + "::addSymbols(symbols = " + elementsToString(begin, end) + ")"); } @@ -559,6 +567,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared void removeSymbols(SymbolIt begin, SymbolIt end) const { if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode Debugger::debug(toString() + "::removeSymbols(symbols = " + elementsToString(begin, end) + ")"); } @@ -618,6 +627,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared void setSymbols(SymbolIt begin, SymbolIt end) const { if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode Debugger::debug(toString() + "::setSymbols(symbols = " + elementsToString(begin, end) + ")"); } @@ -666,6 +676,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared getSymbols() const noexcept { if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode Debugger::debug(toString() + "::getSymbols()"); } @@ -732,8 +745,9 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared getDecoratedSymbols() noexcept { + std::vector getDecoratedSymbols() const { if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode Debugger::debug(toString() + "::getDecoratedSymbols()"); } diff --git a/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscription.hpp b/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscription.hpp index 39e973473..b18018c2e 100644 --- a/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscription.hpp @@ -61,7 +61,7 @@ struct DXFCPP_EXPORT ObservableSubscription { /** * Removes subscription change listener by id. This method does nothing if the listener with the given id was not - * installed or was already removed as subscription change listener for this subscription. Otherwise it removes the + * installed or was already removed as subscription change listener for this subscription. Otherwise, it removes the * corresponding listener and immediately invokes ObservableSubscriptionChangeListener::subscriptionClosed() on the * given listener while holding the lock for this subscription. * From 2623e20aa20a7e53aa356d2604bc615d0eb3c5f6 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Sun, 2 Jun 2024 21:52:17 +0300 Subject: [PATCH 05/28] [EN-7587] Implement FetchDailyCandles sample DXFeedSubscription::addChangeListener DXFeedSubscription::removeChangeListener --- include/dxfeed_graal_cpp_api/api.hpp | 1 + .../api/DXFeedSubscription.hpp | 62 +++++++++---------- .../api/osub/ObservableSubscription.hpp | 1 + .../api/IsolatedDXFeedSubscription.hpp | 36 +++++++++-- .../api/IsolatedDXFeedSubscription.cpp | 39 ++++++++++++ 5 files changed, 104 insertions(+), 35 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index f38bc16a9..6db5ba345 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -53,6 +53,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "exceptions/GraalException.hpp" #include "isolated/api/IsolatedDXEndpoint.hpp" +#include "isolated/api/IsolatedDXFeedSubscription.hpp" #include "isolated/api/IsolatedDXPublisher.hpp" #include "isolated/api/IsolatedDXPublisherObservableSubscription.hpp" #include "isolated/api/osub/IsolatedObservableSubscriptionChangeListener.hpp" diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index 3e933def3..07072d460 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -36,10 +36,10 @@ struct LastingEvent; * Subscription for a set of symbols and event types. */ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared, public ObservableSubscription { -public: + public: static constexpr std::size_t FAKE_CHANGE_LISTENER_ID{static_cast(-1)}; -private: + private: friend struct DXFeed; inline static std::atomic lastChangeListenerId_{}; @@ -53,8 +53,6 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared> changeListeners_; std::recursive_mutex changeListenersMutex_{}; - DXFeedSubscription(LockExternalConstructionTag, const EventTypeEnum &eventType); - static JavaObjectHandle createSubscriptionHandleFromEventClassList(const std::unique_ptr &list); @@ -62,6 +60,35 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared getSymbolsImpl() const; + + std::vector getDecoratedSymbolsImpl() const; + + public: + /// The alias to a type of shared pointer to the DXFeedSubscription object + using Ptr = std::shared_ptr; + + /// The alias to a type of unique pointer to the DXFeedSubscription object + using Unique = std::unique_ptr; + + DXFeedSubscription(LockExternalConstructionTag, const EventTypeEnum &eventType); + template #if __cpp_concepts requires requires(EventTypeIt iter) { @@ -98,33 +125,6 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared(eventTypes))) { } - void closeImpl() const noexcept; - - void clearImpl() const noexcept; - - bool isClosedImpl() const; - - void addSymbolImpl(void *graalSymbol) const noexcept; - - void addSymbolsImpl(void *graalSymbolList) const noexcept; - - void removeSymbolImpl(void *graalSymbol) const noexcept; - - void removeSymbolsImpl(void *graalSymbolList) const noexcept; - - void setSymbolsImpl(void *graalSymbolList) const noexcept; - - std::vector getSymbolsImpl() const; - - std::vector getDecoratedSymbolsImpl() const; - - public: - /// The alias to a type of shared pointer to the DXFeedSubscription object - using Ptr = std::shared_ptr; - - /// The alias to a type of unique pointer to the DXFeedSubscription object - using Unique = std::unique_ptr; - /// std::string toString() const noexcept override; diff --git a/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscription.hpp b/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscription.hpp index b18018c2e..b3cb47758 100644 --- a/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscription.hpp @@ -9,6 +9,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include "../../event/IndexedEventSource.hpp" #include "../../symbols/SymbolWrapper.hpp" +#include "../../event/EventTypeEnum.hpp" #include "ObservableSubscriptionChangeListener.hpp" #include diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp index adf9e64e6..7f6d93dd5 100644 --- a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp @@ -58,15 +58,43 @@ dxfg_executor_t* dxfg_DXFeedSubscription_getExecutor(graal_isolatethrea int32_t dxfg_DXFeedSubscription_setExecutor(graal_isolatethread_t *thread, dxfg_executor_t *executor); -int32_t dxfg_DXFeedSubscription_addChangeListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_observable_subscription_change_listener_t *listener); - -int32_t dxfg_DXFeedSubscription_removeChangeListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_observable_subscription_change_listener_t *listener); - */ + // dxfg_DXFeedSubscription_new JavaObjectHandle /* dxfg_subscription_t* */ create(/* dxfg_event_clazz_t */ const EventTypeEnum &eventType); +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_addChangeListener` in isolation. + * + * @param sub The subscription's handle. + * @param listener The listener's handle. + * @throws std::invalid_argument if DXFeedSubscription's or ObservableSubscriptionChangeListener's handle + * is invalid. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ addChangeListener( + /* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle + &listener); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_removeChangeListener` in isolation. + * + * @param sub The subscription's handle. + * @param listener The listener's handle. + * @throws std::invalid_argument if DXFeedSubscription's or ObservableSubscriptionChangeListener's handle + * is invalid. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ removeChangeListener( + /* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle + &listener); + + namespace DXFeedEventListener { // dxfg_feed_event_listener_t* dxfg_DXFeedEventListener_new(graal_isolatethread_t *thread, dxfg_feed_event_listener_function user_func, void *user_data); diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp index e6fb61735..968e2214c 100644 --- a/src/isolated/api/IsolatedDXFeedSubscription.cpp +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -9,6 +9,45 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::api::IsolatedDXFeedSubscription { + +void /* int32_t */ addChangeListener( + /* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle + &listener) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_addChangeListener`. The `sub` handle is invalid"); + } + + if (!listener) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_addChangeListener`. The " + "`listener` handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero( + dxfg_DXFeedSubscription_addChangeListener, static_cast(sub.get()), + static_cast(listener.get())); +} + +void /* int32_t */ removeChangeListener( + /* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle + &listener) { + if (!sub) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_removeChangeListener`. " + "The `sub` handle is invalid"); + } + + if (!listener) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_removeChangeListener`. The " + "`listener` handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero( + dxfg_DXFeedSubscription_removeChangeListener, static_cast(sub.get()), + static_cast(listener.get())); } +} // namespace isolated::api::IsolatedDXFeedSubscription + DXFCPP_END_NAMESPACE From 0692dc1507daed7730644896d8086592932b3053 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Sun, 9 Jun 2024 17:08:33 +0300 Subject: [PATCH 06/28] [EN-7587] Implement FetchDailyCandles sample Fix ObservableSubscriptionChangeListener build --- .../api/osub/ObservableSubscriptionChangeListener.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscriptionChangeListener.hpp b/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscriptionChangeListener.hpp index e04315a2e..5599f4d1c 100644 --- a/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscriptionChangeListener.hpp +++ b/include/dxfeed_graal_cpp_api/api/osub/ObservableSubscriptionChangeListener.hpp @@ -8,7 +8,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include "../../symbols/SymbolWrapper.hpp" -#include "../entity/SharedEntity.hpp" +#include "../../entity/SharedEntity.hpp" #include #include From b590882fc8058e46addd9876db7f8d587c18528c Mon Sep 17 00:00:00 2001 From: ttldtor Date: Mon, 10 Jun 2024 00:21:58 +0300 Subject: [PATCH 07/28] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeedSubscription --- .../api/DXFeedSubscription.hpp | 73 ++++++------ .../api/IsolatedDXFeedSubscription.hpp | 108 ++++++++++++++---- src/api/DXEndpoint.cpp | 2 +- src/api/DXFeedSubscription.cpp | 108 ++++++++---------- .../api/IsolatedDXFeedSubscription.cpp | 58 ++++++++++ 5 files changed, 224 insertions(+), 125 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index 07072d460..c1c21d3d7 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -44,6 +44,10 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared lastChangeListenerId_{}; + struct Impl; + + std::unique_ptr impl_; + std::unordered_set eventTypes_; JavaObjectHandle handle_; @@ -58,23 +62,23 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared id); - bool tryToSetEventListenerHandle() noexcept; + bool tryToSetEventListenerHandle(); - void closeImpl() const noexcept; + void closeImpl() const; - void clearImpl() const noexcept; + void clearImpl() const; bool isClosedImpl() const; - void addSymbolImpl(void *graalSymbol) const noexcept; + void addSymbolImpl(void *graalSymbol) const; - void addSymbolsImpl(void *graalSymbolList) const noexcept; + void addSymbolsImpl(void *graalSymbolList) const; - void removeSymbolImpl(void *graalSymbol) const noexcept; + void removeSymbolImpl(void *graalSymbol) const; - void removeSymbolsImpl(void *graalSymbolList) const noexcept; + void removeSymbolsImpl(void *graalSymbolList) const; - void setSymbolsImpl(void *graalSymbolList) const noexcept; + void setSymbolsImpl(void *graalSymbolList) const; std::vector getSymbolsImpl() const; @@ -87,6 +91,8 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared; + DXFeedSubscription(LockExternalConstructionTag); + DXFeedSubscription(LockExternalConstructionTag, const EventTypeEnum &eventType); template @@ -95,13 +101,15 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared dxfcpp::ConvertibleTo; } #endif - DXFeedSubscription(LockExternalConstructionTag, EventTypeIt begin, EventTypeIt end) - : eventTypes_(begin, end), handle_{}, eventListenerHandle_{}, onEvent_{} { + DXFeedSubscription(LockExternalConstructionTag tag, EventTypeIt begin, EventTypeIt end) + : DXFeedSubscription{tag} { if constexpr (Debugger::isDebug) { // ReSharper disable once CppDFAUnreachableCode Debugger::debug("DXFeedSubscription(eventTypes = " + namesToString(begin, end) + ")"); } + eventTypes_ = {begin, end}; + auto list = EventClassList::create(eventTypes_.begin(), eventTypes_.end()); handle_ = createSubscriptionHandleFromEventClassList(list); @@ -128,14 +136,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShareddetached subscription for a single event type. @@ -255,14 +256,14 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared feed) noexcept; + void attach(std::shared_ptr feed); /** * Detaches subscription from the specified feed. * * @param feed The feed to detach from. */ - void detach(std::shared_ptr feed) noexcept; + void detach(std::shared_ptr feed); /** * Closes this subscription and makes it permanently detached. @@ -312,7 +313,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared - std::size_t addEventListener(EventListener &&listener) noexcept + std::size_t addEventListener(EventListener &&listener) #if __cpp_concepts requires requires { { listener(std::vector>{}) } -> std::same_as; @@ -367,7 +368,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared - std::size_t addEventListener(std::function> &)> &&listener) noexcept + std::size_t addEventListener(std::function> &)> &&listener) #if __cpp_concepts requires std::is_base_of_v && (requires { @@ -407,7 +408,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared - void addSymbols(const SymbolsCollection &collection) const noexcept { + void addSymbols(const SymbolsCollection &collection) const { addSymbols(std::begin(collection), std::end(collection)); } @@ -547,7 +548,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared collection) const noexcept { + void addSymbols(std::initializer_list collection) const { addSymbols(collection.begin(), collection.end()); } @@ -592,7 +593,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared - void removeSymbols(SymbolsCollection &&collection) const noexcept { + void removeSymbols(SymbolsCollection &&collection) const { removeSymbols(std::begin(collection), std::end(collection)); } @@ -606,7 +607,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared collection) const noexcept { + void removeSymbols(std::initializer_list collection) const { removeSymbols(collection.begin(), collection.end()); } @@ -652,7 +653,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared - void setSymbols(SymbolsCollection &&collection) const noexcept { + void setSymbols(SymbolsCollection &&collection) const { setSymbols(std::begin(collection), std::end(collection)); } @@ -667,14 +668,14 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared collection) const noexcept { + void setSymbols(std::initializer_list collection) const { setSymbols(collection.begin(), collection.end()); } /** * Clears the set of subscribed symbols. */ - void clear() const noexcept { + void clear() const { if constexpr (Debugger::isDebug) { // ReSharper disable once CppDFAUnreachableCode Debugger::debug(toString() + "::clear()"); @@ -728,7 +729,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared getSymbols() const noexcept { + std::vector getSymbols() const { if constexpr (Debugger::isDebug) { // ReSharper disable once CppDFAUnreachableCode Debugger::debug(toString() + "::getSymbols()"); @@ -754,9 +755,9 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared void setExecutor(Executor &&executor) noexcept; + template void setExecutor(Executor &&executor); std::size_t addChangeListener(std::shared_ptr listener) override; diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp index 7f6d93dd5..b55c76621 100644 --- a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp @@ -16,43 +16,51 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::api::IsolatedDXFeedSubscription { /* -dxfg_subscription_t* dxfg_DXFeedSubscription_new(graal_isolatethread_t *thread, dxfg_event_clazz_t eventClazz); -dxfg_subscription_t* dxfg_DXFeedSubscription_new2(graal_isolatethread_t *thread, dxfg_event_clazz_list_t *eventClazzes); +int32_t dxfg_DXFeedSubscription_addEventListener(graal_isolatethread_t *thread, dxfg_subscription_t +*sub, dxfg_feed_event_listener_t *listener); -int32_t dxfg_DXFeedSubscription_close(graal_isolatethread_t *thread, dxfg_subscription_t *sub); +int32_t dxfg_DXFeedSubscription_removeEventListener(graal_isolatethread_t *thread, dxfg_subscription_t +*sub, dxfg_feed_event_listener_t *listener); -int32_t dxfg_DXFeedSubscription_addEventListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_event_listener_t *listener); +int32_t dxfg_DXFeedSubscription_addSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +dxfg_symbol_t *symbol); -int32_t dxfg_DXFeedSubscription_removeEventListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_event_listener_t *listener); +int32_t dxfg_DXFeedSubscription_addSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +dxfg_symbol_list *symbols); -int32_t dxfg_DXFeedSubscription_addSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); +int32_t dxfg_DXFeedSubscription_removeSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +dxfg_symbol_t *symbol); -int32_t dxfg_DXFeedSubscription_addSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_list *symbols); - -int32_t dxfg_DXFeedSubscription_removeSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); - -int32_t dxfg_DXFeedSubscription_removeSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_list *symbols); +int32_t dxfg_DXFeedSubscription_removeSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +dxfg_symbol_list *symbols); int32_t dxfg_DXFeedSubscription_clear(graal_isolatethread_t *thread, dxfg_subscription_t *sub); -int32_t dxfg_DXFeedSubscription_attach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_t *feed); +int32_t dxfg_DXFeedSubscription_attach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +dxfg_feed_t *feed); -int32_t dxfg_DXFeedSubscription_detach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_t *feed); +int32_t dxfg_DXFeedSubscription_detach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +dxfg_feed_t *feed); int32_t dxfg_DXFeedSubscription_isClosed(graal_isolatethread_t *thread, dxfg_subscription_t *sub); -dxfg_event_clazz_list_t* dxfg_DXFeedSubscription_getEventTypes(graal_isolatethread_t *thread, dxfg_subscription_t *sub); +dxfg_event_clazz_list_t* dxfg_DXFeedSubscription_getEventTypes(graal_isolatethread_t *thread, dxfg_subscription_t +*sub); -int32_t dxfg_DXFeedSubscription_containsEventType(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_event_clazz_t eventClazz); +int32_t dxfg_DXFeedSubscription_containsEventType(graal_isolatethread_t *thread, dxfg_subscription_t +*sub, dxfg_event_clazz_t eventClazz); dxfg_symbol_list* dxfg_DXFeedSubscription_getSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub); -int32_t dxfg_DXFeedSubscription_setSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); +int32_t dxfg_DXFeedSubscription_setSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +dxfg_symbol_t *symbol); -int32_t dxfg_DXFeedSubscription_setSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_list *symbols); +int32_t dxfg_DXFeedSubscription_setSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +dxfg_symbol_list *symbols); -dxfg_symbol_list* dxfg_DXFeedSubscription_getDecoratedSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub); +dxfg_symbol_list* dxfg_DXFeedSubscription_getDecoratedSymbols(graal_isolatethread_t *thread, dxfg_subscription_t +*sub); dxfg_executor_t* dxfg_DXFeedSubscription_getExecutor(graal_isolatethread_t *thread, dxfg_subscription_t *sub); @@ -60,9 +68,50 @@ int32_t dxfg_DXFeedSubscription_setExecutor(graal_isolatethrea */ +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_new` in isolation. + * + * @param eventType The subscription's event type. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +JavaObjectHandle /* dxfg_subscription_t* */ +create(/* dxfg_event_clazz_t */ const EventTypeEnum &eventType); -// dxfg_DXFeedSubscription_new -JavaObjectHandle /* dxfg_subscription_t* */ create(/* dxfg_event_clazz_t */ const EventTypeEnum &eventType); +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_new2` in isolation. + * + * @param eventClassList The subscription's event types. + * + * @throws std::invalid_argument if eventClassList is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +JavaObjectHandle /* dxfg_subscription_t* */ +create(/* dxfg_event_clazz_list_t * */ const std::unique_ptr &eventClassList); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_close` in isolation. + * + * @param sub The subscription's handle. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ close(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_addEventListener` in isolation. + * + * @param sub The subscription's handle. + * @param listener The listener's handle. + * @throws std::invalid_argument if DXFeedSubscription's or DXFeedEventListener's handle is invalid. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ +addEventListener(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_feed_event_listener_t * */ const JavaObjectHandle &listener); /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addChangeListener` in isolation. @@ -94,16 +143,25 @@ void /* int32_t */ removeChangeListener( /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle &listener); - namespace DXFeedEventListener { -// dxfg_feed_event_listener_t* dxfg_DXFeedEventListener_new(graal_isolatethread_t *thread, dxfg_feed_event_listener_function user_func, void *user_data); +/** + * Calls the Graal SDK function `dxfg_DXFeedEventListener_new` in isolation. + * @param userFunc A user function that is used as a callback for the listener. + * @param userData User data, which is placed each time as a callback parameter when called from listener. + * @return The DXFeedEventListener's handle. + * + * @throws std::invalid_argument if userFunc is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +JavaObjectHandle /* dxfg_feed_event_listener_t* */ +create(/* dxfg_feed_event_listener_function */ void *userFunc, void *userData); -} +} // namespace DXFeedEventListener -} +} // namespace isolated::api::IsolatedDXFeedSubscription DXFCPP_END_NAMESPACE - DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/src/api/DXEndpoint.cpp b/src/api/DXEndpoint.cpp index 440d78204..b494b7cf3 100644 --- a/src/api/DXEndpoint.cpp +++ b/src/api/DXEndpoint.cpp @@ -140,7 +140,7 @@ std::shared_ptr DXEndpoint::create(void *endpointHandle, DXEndpoint: auto id = ApiContext::getInstance()->getManager()->registerEntity(endpoint); endpoint->stateChangeListenerHandle_ = isolated::api::IsolatedDXEndpoint::StateChangeListener::create( - dxfcpp::bit_cast(&DXEndpoint::Impl::onPropertyChange), dxfcpp::bit_cast(id.getValue())); + dxfcpp::bit_cast(&Impl::onPropertyChange), dxfcpp::bit_cast(id.getValue())); isolated::api::IsolatedDXEndpoint::addStateChangeListener(endpoint->handle_, endpoint->stateChangeListenerHandle_); return endpoint; diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index e13df7751..441692831 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -15,7 +15,20 @@ DXFCPP_BEGIN_NAMESPACE -void DXFeedSubscription::attach(std::shared_ptr feed) noexcept { +struct DXFeedSubscription::Impl { + static void onEvents(graal_isolatethread_t * /*thread*/, dxfg_event_type_list *graalNativeEvents, void *userData) { + auto id = Id::from(dxfcpp::bit_cast::ValueType>(userData)); + auto sub = ApiContext::getInstance()->getManager()->getEntity(id); + + if (sub) { + auto &&events = EventMapper::fromGraalList(static_cast(graalNativeEvents)); + + sub->onEvent_(events); + } + }; +}; + +void DXFeedSubscription::attach(std::shared_ptr feed) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::attach(feed = " + feed->toString() + ")"); } @@ -23,7 +36,7 @@ void DXFeedSubscription::attach(std::shared_ptr feed) noexcept { feed->attachSubscription(sharedAs()); } -void DXFeedSubscription::detach(std::shared_ptr feed) noexcept { +void DXFeedSubscription::detach(std::shared_ptr feed) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::detach(feed = " + feed->toString() + ")"); } @@ -63,7 +76,7 @@ void DXFeedSubscription::removeChangeListener(std::size_t changeListenerId) { } } -void DXFeedSubscription::addSymbolImpl(void *graalSymbol) const noexcept { +void DXFeedSubscription::addSymbolImpl(void *graalSymbol) const { if (!handle_) { return; } @@ -76,7 +89,7 @@ void DXFeedSubscription::addSymbolImpl(void *graalSymbol) const noexcept { false); } -void DXFeedSubscription::addSymbolsImpl(void *graalSymbolList) const noexcept { +void DXFeedSubscription::addSymbolsImpl(void *graalSymbolList) const { if (!handle_) { return; } @@ -89,7 +102,7 @@ void DXFeedSubscription::addSymbolsImpl(void *graalSymbolList) const noexcept { false); } -void DXFeedSubscription::removeSymbolImpl(void *graalSymbol) const noexcept { +void DXFeedSubscription::removeSymbolImpl(void *graalSymbol) const { if (!handle_) { return; } @@ -102,7 +115,7 @@ void DXFeedSubscription::removeSymbolImpl(void *graalSymbol) const noexcept { false); } -void DXFeedSubscription::removeSymbolsImpl(void *graalSymbolList) const noexcept { +void DXFeedSubscription::removeSymbolsImpl(void *graalSymbolList) const { if (!handle_) { return; } @@ -115,7 +128,7 @@ void DXFeedSubscription::removeSymbolsImpl(void *graalSymbolList) const noexcept false); } -void DXFeedSubscription::setSymbolsImpl(void *graalSymbolList) const noexcept { +void DXFeedSubscription::setSymbolsImpl(void *graalSymbolList) const { if (!handle_) { return; } @@ -173,19 +186,11 @@ std::vector DXFeedSubscription::getDecoratedSymbolsImpl() const { return result; } -void DXFeedSubscription::closeImpl() const noexcept { - if (!handle_) { - return; - } - - runIsolatedOrElse( - [handle = static_cast(handle_.get())](auto threadHandle) { - return dxfg_DXFeedSubscription_close(static_cast(threadHandle), handle) == 0; - }, - false); +void DXFeedSubscription::closeImpl() const { + isolated::api::IsolatedDXFeedSubscription::close(handle_); } -void DXFeedSubscription::clearImpl() const noexcept { +void DXFeedSubscription::clearImpl() const { if (!handle_) { return; } @@ -209,65 +214,33 @@ bool DXFeedSubscription::isClosedImpl() const { false); } -DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag, const EventTypeEnum &eventType) - : eventTypes_{eventType}, handle_{}, eventListenerHandle_{}, onEvent_{} { +DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag) + : impl_(std::make_unique()) { +} + +DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag tag, const EventTypeEnum &eventType) + : DXFeedSubscription{tag} { if constexpr (Debugger::isDebug) { Debugger::debug("DXFeedSubscription(eventType = " + eventType.getName() + ")"); } - handle_ = JavaObjectHandle(runIsolatedOrElse( - [eventType](auto threadHandle) { - return dxfg_DXFeedSubscription_new(static_cast(threadHandle), - static_cast(eventType.getId())); - }, - nullptr)); + eventTypes_ = {eventType}; + handle_ = isolated::api::IsolatedDXFeedSubscription::create(eventType); } JavaObjectHandle DXFeedSubscription::createSubscriptionHandleFromEventClassList(const std::unique_ptr &list) { - if (!list) { - throw std::invalid_argument("EventClassList is nullptr"); - } - - return JavaObjectHandle(runIsolatedOrElse( - [listHandle = static_cast(list->getHandle())](auto threadHandle) { - return dxfg_DXFeedSubscription_new2(static_cast(threadHandle), listHandle); - }, - nullptr)); + return isolated::api::IsolatedDXFeedSubscription::create(list); } void DXFeedSubscription::setEventListenerHandle(Id id) { - auto onEvents = [](graal_isolatethread_t * /*thread*/, dxfg_event_type_list *graalNativeEvents, void *userData) { - auto id = Id::from(dxfcpp::bit_cast::ValueType>(userData)); - auto sub = ApiContext::getInstance()->getManager()->getEntity(id); - - if (sub) { - auto &&events = EventMapper::fromGraalList(static_cast(graalNativeEvents)); - - sub->onEvent_(events); - } - }; + eventListenerHandle_ = isolated::api::IsolatedDXFeedSubscription::DXFeedEventListener::create( + dxfcpp::bit_cast(&Impl::onEvents), dxfcpp::bit_cast(id.getValue())); - eventListenerHandle_ = JavaObjectHandle(runIsolatedOrElse( - [idValue = id.getValue(), onEvents](auto threadHandle) { - return dxfg_DXFeedEventListener_new(static_cast(threadHandle), onEvents, - dxfcpp::bit_cast(idValue)); - }, - nullptr)); - - if (handle_ && eventListenerHandle_) { - runIsolatedOrElse( - [handle = static_cast(handle_.get()), - eventListenerHandle = - static_cast(eventListenerHandle_.get())](auto threadHandle) { - return dxfg_DXFeedSubscription_addEventListener(static_cast(threadHandle), - handle, eventListenerHandle) == 0; - }, - false); - } + isolated::api::IsolatedDXFeedSubscription::addEventListener(handle_, eventListenerHandle_); } -bool DXFeedSubscription::tryToSetEventListenerHandle() noexcept { +bool DXFeedSubscription::tryToSetEventListenerHandle() { std::lock_guard lock{eventListenerMutex_}; if (!eventListenerHandle_) { @@ -288,4 +261,13 @@ std::string DXFeedSubscription::toString() const noexcept { return fmt::format("DXFeedSubscription{{{}}}", handle_.toString()); } +DXFeedSubscription::~DXFeedSubscription() { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug("DXFeedSubscription{" + handle_.toString() + "}::~DXFeedSubscription()"); + } + + closeImpl(); +} + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp index 968e2214c..aeb9b845e 100644 --- a/src/isolated/api/IsolatedDXFeedSubscription.cpp +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -10,6 +10,50 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::api::IsolatedDXFeedSubscription { +JavaObjectHandle /* dxfg_subscription_t* */ +create(/* dxfg_event_clazz_t */ const EventTypeEnum &eventType) { + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr( + dxfg_DXFeedSubscription_new, dxfcpp::bit_cast(eventType.getId()))); +} + +JavaObjectHandle /* dxfg_subscription_t* */ +create(/* dxfg_event_clazz_list_t * */ const std::unique_ptr &eventClassList) { + if (!eventClassList) { + throw std::invalid_argument("The eventClassList is nullptr"); + } + + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr( + dxfg_DXFeedSubscription_new2, static_cast(eventClassList->getHandle()))); +} + +void /* int32_t */ close(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_close`. The `sub` handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_close, + static_cast(sub.get())); +} + +void /* int32_t */ +addEventListener(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_feed_event_listener_t * */ const JavaObjectHandle &listener) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_addEventListener`. The `sub` handle is invalid"); + } + + if (!listener) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_addEventListener`. The " + "`listener` handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_addEventListener, + static_cast(sub.get()), + static_cast(listener.get())); +} + void /* int32_t */ addChangeListener( /* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle @@ -48,6 +92,20 @@ void /* int32_t */ removeChangeListener( static_cast(listener.get())); } +namespace DXFeedEventListener { + +JavaObjectHandle /* dxfg_feed_event_listener_t* */ +create(/* dxfg_feed_event_listener_function */ void *userFunc, void *userData) { + if (!userFunc) { + throw std::invalid_argument("Unable to create DXFeedEventListener. The `userFunc` parameter is nullptr"); + } + + return JavaObjectHandle(runGraalFunctionAndThrowIfNullptr( + dxfg_DXFeedEventListener_new, dxfcpp::bit_cast(userFunc), userData)); +} + +} // namespace DXFeedEventListener + } // namespace isolated::api::IsolatedDXFeedSubscription DXFCPP_END_NAMESPACE From 70eb5e6a19117e5761e6d5b00786efffcc34b24d Mon Sep 17 00:00:00 2001 From: ttldtor Date: Mon, 10 Jun 2024 00:26:50 +0300 Subject: [PATCH 08/28] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeedSubscription --- include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp | 2 +- src/api/DXFeedSubscription.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index c1c21d3d7..246e184d9 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -108,7 +108,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared Date: Mon, 10 Jun 2024 01:07:08 +0300 Subject: [PATCH 09/28] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeedSubscription --- include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index 246e184d9..af56ba90c 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -108,7 +108,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared{begin, end}; auto list = EventClassList::create(eventTypes_.begin(), eventTypes_.end()); From c2f8ebd9f14994995d32c04b642de4732975449a Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 10 Jun 2024 18:22:38 +0300 Subject: [PATCH 10/28] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeedSubscription::addSymbol --- .../api/DXFeedSubscription.hpp | 9 +------- .../api/IsolatedDXFeedSubscription.hpp | 18 ++++++++++++--- src/api/DXFeedSubscription.cpp | 22 +++++++++---------- .../api/IsolatedDXFeedSubscription.cpp | 17 ++++++++++++++ 4 files changed, 44 insertions(+), 22 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index af56ba90c..ce0e99944 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -272,14 +272,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared &sub, /* dxfg_feed_event_listener_t * */ const JavaObjectHandle &listener); +// int32_t dxfg_DXFeedSubscription_removeEventListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_event_listener_t *listener); + +// int32_t dxfg_DXFeedSubscription_addSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_addSymbol` in isolation. + * + * @param sub The subscription's handle. + * @param symbol The symbol. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid or the symbol is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ addSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_t * */ void* symbol); + /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addChangeListener` in isolation. * diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index 05072525c..e6b626336 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -25,7 +25,7 @@ struct DXFeedSubscription::Impl { sub->onEvent_(events); } - }; + } }; void DXFeedSubscription::attach(std::shared_ptr feed) { @@ -44,6 +44,15 @@ void DXFeedSubscription::detach(std::shared_ptr feed) { feed->detachSubscription(sharedAs()); } +void DXFeedSubscription::close() const { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug(toString() + "::close()"); + } + + closeImpl(); +} + std::size_t DXFeedSubscription::addChangeListener(std::shared_ptr listener) { isolated::api::IsolatedDXFeedSubscription::addChangeListener(handle_, listener->getHandle()); @@ -77,16 +86,7 @@ void DXFeedSubscription::removeChangeListener(std::size_t changeListenerId) { } void DXFeedSubscription::addSymbolImpl(void *graalSymbol) const { - if (!handle_) { - return; - } - - runIsolatedOrElse( - [handle = static_cast(handle_.get()), graalSymbol](auto threadHandle) { - return dxfg_DXFeedSubscription_addSymbol(static_cast(threadHandle), handle, - static_cast(graalSymbol)) == 0; - }, - false); + isolated::api::IsolatedDXFeedSubscription::addSymbol(handle_, graalSymbol); } void DXFeedSubscription::addSymbolsImpl(void *graalSymbolList) const { diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp index aeb9b845e..f4d37317a 100644 --- a/src/isolated/api/IsolatedDXFeedSubscription.cpp +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -54,6 +54,23 @@ addEventListener(/* dxfg_subscription_t * */ const JavaObjectHandle(listener.get())); } +void /* int32_t */ addSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_t * */ void *symbol) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_addSymbol`. The `sub` handle is invalid"); + } + + if (!symbol) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_addSymbol`. The " + "`symbol` is nullptr"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_addSymbol, + static_cast(sub.get()), + static_cast(symbol)); +} + void /* int32_t */ addChangeListener( /* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle From 94d54218e812b27719f9cc55bd2c4ecb8795e110 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 10 Jun 2024 18:35:50 +0300 Subject: [PATCH 11/28] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeedSubscription::addSymbols --- .../api/IsolatedDXFeedSubscription.hpp | 28 +++++++++++-------- src/api/DXFeedSubscription.cpp | 11 +------- .../api/IsolatedDXFeedSubscription.cpp | 16 +++++++++++ 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp index 45bd494f9..d127b828f 100644 --- a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp @@ -17,15 +17,6 @@ namespace isolated::api::IsolatedDXFeedSubscription { /* -int32_t dxfg_DXFeedSubscription_removeEventListener(graal_isolatethread_t *thread, dxfg_subscription_t -*sub, dxfg_feed_event_listener_t *listener); - -int32_t dxfg_DXFeedSubscription_addSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -dxfg_symbol_t *symbol); - -int32_t dxfg_DXFeedSubscription_addSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -dxfg_symbol_list *symbols); - int32_t dxfg_DXFeedSubscription_removeSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); @@ -112,19 +103,32 @@ addEventListener(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_t * */ void* symbol); +// int32_t dxfg_DXFeedSubscription_addSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +// dxfg_symbol_list *symbols); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_addSymbols` in isolation. + * + * @param sub The subscription's handle. + * @param symbols The subscription's symbols. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid or the symbols is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void* symbols); + + /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addChangeListener` in isolation. * diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index e6b626336..a68fead3c 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -90,16 +90,7 @@ void DXFeedSubscription::addSymbolImpl(void *graalSymbol) const { } void DXFeedSubscription::addSymbolsImpl(void *graalSymbolList) const { - if (!handle_) { - return; - } - - runIsolatedOrElse( - [handle = static_cast(handle_.get()), graalSymbolList](auto threadHandle) { - return dxfg_DXFeedSubscription_addSymbols(static_cast(threadHandle), handle, - static_cast(graalSymbolList)) == 0; - }, - false); + isolated::api::IsolatedDXFeedSubscription::addSymbols(handle_, graalSymbolList); } void DXFeedSubscription::removeSymbolImpl(void *graalSymbol) const { diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp index f4d37317a..749bc9dc7 100644 --- a/src/isolated/api/IsolatedDXFeedSubscription.cpp +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -71,6 +71,22 @@ void /* int32_t */ addSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle< static_cast(symbol)); } +void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void* symbols) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_addSymbols`. The `sub` handle is invalid"); + } + + if (!symbols) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_addSymbols`. The " + "`symbols` is nullptr"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_addSymbols, + static_cast(sub.get()), + static_cast(symbols)); +} + void /* int32_t */ addChangeListener( /* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle From dfe8fe21f4119a7467b702af65f45962fad09f73 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 10 Jun 2024 18:50:32 +0300 Subject: [PATCH 12/28] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeedSubscription::removeSymbol IsolatedDXFeedSubscription::removeSymbols --- .../api/IsolatedDXFeedSubscription.hpp | 41 +++++++++++++------ src/api/DXFeedSubscription.cpp | 22 +--------- .../api/IsolatedDXFeedSubscription.cpp | 37 ++++++++++++++++- 3 files changed, 67 insertions(+), 33 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp index d127b828f..bd41414f3 100644 --- a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp @@ -17,12 +17,6 @@ namespace isolated::api::IsolatedDXFeedSubscription { /* -int32_t dxfg_DXFeedSubscription_removeSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -dxfg_symbol_t *symbol); - -int32_t dxfg_DXFeedSubscription_removeSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -dxfg_symbol_list *symbols); - int32_t dxfg_DXFeedSubscription_clear(graal_isolatethread_t *thread, dxfg_subscription_t *sub); int32_t dxfg_DXFeedSubscription_attach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, @@ -101,7 +95,8 @@ void /* int32_t */ addEventListener(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_feed_event_listener_t * */ const JavaObjectHandle &listener); -// int32_t dxfg_DXFeedSubscription_removeEventListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_event_listener_t *listener); +// int32_t dxfg_DXFeedSubscription_removeEventListener(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +// dxfg_feed_event_listener_t *listener); /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addSymbol` in isolation. @@ -112,10 +107,8 @@ addEventListener(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_t * */ void* symbol); - -// int32_t dxfg_DXFeedSubscription_addSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -// dxfg_symbol_list *symbols); +void /* int32_t */ addSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_t * */ void *symbol); /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addSymbols` in isolation. @@ -126,8 +119,32 @@ void /* int32_t */ addSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle< * @throws JavaException if something happened with the dxFeed API backend. * @throws GraalException if something happened with the GraalVM. */ -void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void* symbols); +void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_list * */ void *symbols); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_removeSymbol` in isolation. + * + * @param sub The subscription's handle. + * @param symbol The subscription's symbol. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid or the symbol is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ removeSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_t * */ void *symbol); +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_removeSymbols` in isolation. + * + * @param sub The subscription's handle. + * @param symbols The subscription's symbols. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid or the symbols is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ removeSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_list * */ void *symbols); /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addChangeListener` in isolation. diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index a68fead3c..39c2aa6fb 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -94,29 +94,11 @@ void DXFeedSubscription::addSymbolsImpl(void *graalSymbolList) const { } void DXFeedSubscription::removeSymbolImpl(void *graalSymbol) const { - if (!handle_) { - return; - } - - runIsolatedOrElse( - [handle = static_cast(handle_.get()), graalSymbol](auto threadHandle) { - return dxfg_DXFeedSubscription_removeSymbol(static_cast(threadHandle), handle, - static_cast(graalSymbol)) == 0; - }, - false); + isolated::api::IsolatedDXFeedSubscription::removeSymbol(handle_, graalSymbol); } void DXFeedSubscription::removeSymbolsImpl(void *graalSymbolList) const { - if (!handle_) { - return; - } - - runIsolatedOrElse( - [handle = static_cast(handle_.get()), graalSymbolList](auto threadHandle) { - return dxfg_DXFeedSubscription_removeSymbols(static_cast(threadHandle), handle, - static_cast(graalSymbolList)) == 0; - }, - false); + isolated::api::IsolatedDXFeedSubscription::removeSymbols(handle_, graalSymbolList); } void DXFeedSubscription::setSymbolsImpl(void *graalSymbolList) const { diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp index 749bc9dc7..9e89ab1a4 100644 --- a/src/isolated/api/IsolatedDXFeedSubscription.cpp +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -71,7 +71,8 @@ void /* int32_t */ addSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle< static_cast(symbol)); } -void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void* symbols) { +void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_list * */ void *symbols) { if (!sub) { throw std::invalid_argument( "Unable to execute function `dxfg_DXFeedSubscription_addSymbols`. The `sub` handle is invalid"); @@ -87,6 +88,40 @@ void /* int32_t */ addSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle static_cast(symbols)); } +void /* int32_t */ removeSymbol(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_t * */ void *symbol) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_removeSymbol`. The `sub` handle is invalid"); + } + + if (!symbol) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_removeSymbol`. The " + "`symbol` is nullptr"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_removeSymbol, + static_cast(sub.get()), + static_cast(symbol)); +} + +void /* int32_t */ removeSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, + /* dxfg_symbol_list * */ void *symbols) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_removeSymbols`. The `sub` handle is invalid"); + } + + if (!symbols) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_removeSymbols`. The " + "`symbols` is nullptr"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_removeSymbols, + static_cast(sub.get()), + static_cast(symbols)); +} + void /* int32_t */ addChangeListener( /* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle From c59fd0267ae35364738db108d7aad29cb7b0f722 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 10 Jun 2024 19:05:38 +0300 Subject: [PATCH 13/28] [EN-7587] Implement FetchDailyCandles sample RelWithDebInfo --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2784a6154..67793e0c0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,7 +62,7 @@ jobs: xcode: '15.0' cc: 'clang' cxx: 'clang++' - buildType: [ Release, Debug ] + buildType: [ Release, Debug, RelWithDebInfo ] name: "${{ matrix.config.name }}-${{matrix.buildType}}" runs-on: ${{ matrix.config.image }} From 5d4c1c41dd5f0e722c7e0531d8073edb1304e1fe Mon Sep 17 00:00:00 2001 From: ttldtor Date: Tue, 11 Jun 2024 01:16:34 +0300 Subject: [PATCH 14/28] [EN-7587] Implement FetchDailyCandles sample _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR --- CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 80efdc7fe..151bf03dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -373,6 +373,14 @@ set(DXFCXX_GCC_LIKE_LINK_OPTIONS "-fPIC") #A workaround to fix 'relocation truncated to fit: IMAGE_REL_AMD64_SECREL' error (MinGW + Debug) set(DXFCXX_MINGW_DEBUG_LINK_OPTIONS "-Wl,--disable-dynamicbase,--disable-high-entropy-va,--default-image-base-low") +# https://developercommunity.visualstudio.com/t/Invalid-code-generation-in-release-1940/10678572?sort=newest&viewtype=all +# https://github.com/microsoft/STL/wiki/Changelog#vs-2022-1710 +# https://github.com/actions/runner-images/issues/10004 +if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + target_compile_definitions(${PROJECT_NAME} PUBLIC _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR) + target_compile_definitions(${PROJECT_NAME}_static PUBLIC _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR) +endif () + target_compile_options(${PROJECT_NAME} PUBLIC $<$:${DXFCXX_MSVC_COMPILE_OPTIONS}> From 4b48f6e2910c70588584fc54da6206d9ea42493a Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 17 Jun 2024 17:16:46 +0300 Subject: [PATCH 15/28] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeedSubscription::clear IsolatedDXFeedSubscription::isClosed --- .../api/IsolatedDXFeedSubscription.hpp | 33 +++++++++++++++---- src/api/DXFeedSubscription.cpp | 20 ++--------- .../api/IsolatedDXFeedSubscription.cpp | 20 +++++++++++ 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp index bd41414f3..589e51957 100644 --- a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp @@ -17,13 +17,6 @@ namespace isolated::api::IsolatedDXFeedSubscription { /* -int32_t dxfg_DXFeedSubscription_clear(graal_isolatethread_t *thread, dxfg_subscription_t *sub); - -int32_t dxfg_DXFeedSubscription_attach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -dxfg_feed_t *feed); - -int32_t dxfg_DXFeedSubscription_detach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -dxfg_feed_t *feed); int32_t dxfg_DXFeedSubscription_isClosed(graal_isolatethread_t *thread, dxfg_subscription_t *sub); @@ -146,6 +139,32 @@ void /* int32_t */ removeSymbol(/* dxfg_subscription_t * */ const JavaObjectHand void /* int32_t */ removeSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void *symbols); +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_clear` in isolation. + * + * @param sub The subscription's handle. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ clear(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); + +// int32_t dxfg_DXFeedSubscription_attach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_t *feed); + +// int32_t dxfg_DXFeedSubscription_detach(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_feed_t *feed); + +// int32_t dxfg_DXFeedSubscription_isClosed(graal_isolatethread_t *thread, dxfg_subscription_t *sub); +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_clear` in isolation. + * + * @param sub The subscription's handle. + * @return `true` if subscription is closed. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +bool /* int32_t */ isClosed(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); + /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addChangeListener` in isolation. * diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index 39c2aa6fb..b69b5a08e 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -164,27 +164,11 @@ void DXFeedSubscription::closeImpl() const { } void DXFeedSubscription::clearImpl() const { - if (!handle_) { - return; - } - - runIsolatedOrElse( - [handle = static_cast(handle_.get())](auto threadHandle) { - return dxfg_DXFeedSubscription_clear(static_cast(threadHandle), handle) == 0; - }, - false); + isolated::api::IsolatedDXFeedSubscription::clear(handle_); } bool DXFeedSubscription::isClosedImpl() const { - if (!handle_) { - return false; - } - - return runIsolatedOrElse( - [handle = static_cast(handle_.get())](auto threadHandle) { - return dxfg_DXFeedSubscription_isClosed(static_cast(threadHandle), handle) != 0; - }, - false); + return isolated::api::IsolatedDXFeedSubscription::isClosed(handle_); } DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag) diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp index 9e89ab1a4..c8748dc4f 100644 --- a/src/isolated/api/IsolatedDXFeedSubscription.cpp +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -122,6 +122,26 @@ void /* int32_t */ removeSymbols(/* dxfg_subscription_t * */ const JavaObjectHan static_cast(symbols)); } +void /* int32_t */ clear(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_clear`. The `sub` handle is invalid"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_clear, + static_cast(sub.get())); +} + +bool /* int32_t */ isClosed(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_isClosed`. The `sub` handle is invalid"); + } + + return runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_isClosed, + static_cast(sub.get())) == 1; +} + void /* int32_t */ addChangeListener( /* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle From 6d8b0e81a06326a84785abb8b70405b6873f2be5 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 17 Jun 2024 18:06:21 +0300 Subject: [PATCH 16/28] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeedSubscription::getSymbols IsolatedDXFeedSubscription::setSymbols IsolatedDXFeedSubscription::getDecoratedSymbols --- .../api/IsolatedDXFeedSubscription.hpp | 76 +++++++++++-------- src/api/DXFeedSubscription.cpp | 52 +------------ .../api/IsolatedDXFeedSubscription.cpp | 48 ++++++++++++ 3 files changed, 97 insertions(+), 79 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp index 589e51957..1bd18a5e0 100644 --- a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeedSubscription.hpp @@ -15,34 +15,6 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::api::IsolatedDXFeedSubscription { -/* - - -int32_t dxfg_DXFeedSubscription_isClosed(graal_isolatethread_t *thread, dxfg_subscription_t *sub); - -dxfg_event_clazz_list_t* dxfg_DXFeedSubscription_getEventTypes(graal_isolatethread_t *thread, dxfg_subscription_t -*sub); - -int32_t dxfg_DXFeedSubscription_containsEventType(graal_isolatethread_t *thread, dxfg_subscription_t -*sub, dxfg_event_clazz_t eventClazz); - -dxfg_symbol_list* dxfg_DXFeedSubscription_getSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub); - -int32_t dxfg_DXFeedSubscription_setSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -dxfg_symbol_t *symbol); - -int32_t dxfg_DXFeedSubscription_setSymbols(graal_isolatethread_t *thread, dxfg_subscription_t *sub, -dxfg_symbol_list *symbols); - -dxfg_symbol_list* dxfg_DXFeedSubscription_getDecoratedSymbols(graal_isolatethread_t *thread, dxfg_subscription_t -*sub); - -dxfg_executor_t* dxfg_DXFeedSubscription_getExecutor(graal_isolatethread_t *thread, dxfg_subscription_t *sub); - -int32_t dxfg_DXFeedSubscription_setExecutor(graal_isolatethread_t *thread, dxfg_executor_t *executor); - -*/ - /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_new` in isolation. * @@ -153,9 +125,8 @@ void /* int32_t */ clear(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); +// dxfg_event_clazz_list_t* dxfg_DXFeedSubscription_getEventTypes(graal_isolatethread_t *thread, dxfg_subscription_t +// *sub); + +// int32_t dxfg_DXFeedSubscription_containsEventType(graal_isolatethread_t *thread, dxfg_subscription_t *sub, +// dxfg_event_clazz_t eventClazz); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_getSymbols` in isolation. + * + * @param sub The subscription's handle. + * @return The subscription's symbols. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +std::vector /* dxfg_symbol_list* */ getSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); + +// int32_t dxfg_DXFeedSubscription_setSymbol(graal_isolatethread_t *thread, dxfg_subscription_t *sub, dxfg_symbol_t *symbol); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_setSymbols` in isolation. + * + * @param sub The subscription's handle. + * @param symbols The subscription's symbols. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid or the symbols is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ setSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void* symbols); + +/** + * Calls the Graal SDK function `dxfg_DXFeedSubscription_getDecoratedSymbols` in isolation. + * + * @param sub The subscription's handle. + * @return The subscription's decorated symbols. + * @throws std::invalid_argument if DXFeedSubscription's handle is invalid. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +std::vector /* dxfg_symbol_list* */ getDecoratedSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub); + +// dxfg_executor_t* dxfg_DXFeedSubscription_getExecutor(graal_isolatethread_t *thread, dxfg_subscription_t *sub); + +// int32_t dxfg_DXFeedSubscription_setExecutor(graal_isolatethread_t *thread, dxfg_executor_t *executor); + /** * Calls the Graal SDK function `dxfg_DXFeedSubscription_addChangeListener` in isolation. * diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index b69b5a08e..303f65e33 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -102,61 +102,15 @@ void DXFeedSubscription::removeSymbolsImpl(void *graalSymbolList) const { } void DXFeedSubscription::setSymbolsImpl(void *graalSymbolList) const { - if (!handle_) { - return; - } - - runIsolatedOrElse( - [handle = static_cast(handle_.get()), graalSymbolList](auto threadHandle) { - return dxfg_DXFeedSubscription_setSymbols(static_cast(threadHandle), handle, - static_cast(graalSymbolList)) == 0; - }, - false); + isolated::api::IsolatedDXFeedSubscription::setSymbols(handle_, graalSymbolList); } std::vector DXFeedSubscription::getSymbolsImpl() const { - if (!handle_) { - return {}; - } - - dxfg_symbol_list *list = runIsolatedOrElse( - [handle = static_cast(handle_.get())](auto threadHandle) { - return dxfg_DXFeedSubscription_getSymbols(static_cast(threadHandle), handle); - }, - nullptr); - - auto result = SymbolWrapper::SymbolListUtils::fromGraalList(static_cast(list)); - - runIsolatedOrElse( - [list](auto threadHandle) { - return dxfg_CList_symbol_release(static_cast(threadHandle), list) == 0; - }, - false); - - return result; + return isolated::api::IsolatedDXFeedSubscription::getSymbols(handle_); } std::vector DXFeedSubscription::getDecoratedSymbolsImpl() const { - if (!handle_) { - return {}; - } - - dxfg_symbol_list *list = runIsolatedOrElse( - [handle = static_cast(handle_.get())](auto threadHandle) { - return dxfg_DXFeedSubscription_getDecoratedSymbols(static_cast(threadHandle), - handle); - }, - nullptr); - - auto result = SymbolWrapper::SymbolListUtils::fromGraalList(static_cast(list)); - - runIsolatedOrElse( - [list](auto threadHandle) { - return dxfg_CList_symbol_release(static_cast(threadHandle), list) == 0; - }, - false); - - return result; + return isolated::api::IsolatedDXFeedSubscription::getDecoratedSymbols(handle_); } void DXFeedSubscription::closeImpl() const { diff --git a/src/isolated/api/IsolatedDXFeedSubscription.cpp b/src/isolated/api/IsolatedDXFeedSubscription.cpp index c8748dc4f..a76c818d4 100644 --- a/src/isolated/api/IsolatedDXFeedSubscription.cpp +++ b/src/isolated/api/IsolatedDXFeedSubscription.cpp @@ -142,6 +142,54 @@ bool /* int32_t */ isClosed(/* dxfg_subscription_t * */ const JavaObjectHandle(sub.get())) == 1; } +std::vector /* dxfg_symbol_list* */ getSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_getSymbols`. The `sub` handle is invalid"); + } + + dxfg_symbol_list *list = runGraalFunctionAndThrowIfNullptr( + dxfg_DXFeedSubscription_getSymbols, static_cast(sub.get())); + + auto result = SymbolWrapper::SymbolListUtils::fromGraalList(static_cast(list)); + + runGraalFunctionAndThrowIfLessThanZero(dxfg_CList_symbol_release, list); + + return result; +} + +void /* int32_t */ setSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_symbol_list * */ void* symbols) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_setSymbols`. The `sub` handle is invalid"); + } + + if (!symbols) { + throw std::invalid_argument("Unable to execute function `dxfg_DXFeedSubscription_setSymbols`. The " + "`symbols` is nullptr"); + } + + runGraalFunctionAndThrowIfLessThanZero(dxfg_DXFeedSubscription_setSymbols, + static_cast(sub.get()), + static_cast(symbols)); +} + +std::vector /* dxfg_symbol_list* */ getDecoratedSymbols(/* dxfg_subscription_t * */ const JavaObjectHandle &sub) { + if (!sub) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeedSubscription_getDecoratedSymbols`. The `sub` handle is invalid"); + } + + dxfg_symbol_list *list = runGraalFunctionAndThrowIfNullptr( + dxfg_DXFeedSubscription_getDecoratedSymbols, static_cast(sub.get())); + + auto result = SymbolWrapper::SymbolListUtils::fromGraalList(static_cast(list)); + + runGraalFunctionAndThrowIfLessThanZero(dxfg_CList_symbol_release, list); + + return result; +} + void /* int32_t */ addChangeListener( /* dxfg_subscription_t * */ const JavaObjectHandle &sub, /* dxfg_observable_subscription_change_listener_t * */ const JavaObjectHandle From 852515082b6e6ecc89703da040946aed8cc0f410 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 17 Jun 2024 19:07:51 +0300 Subject: [PATCH 17/28] [EN-7587] Implement FetchDailyCandles sample Tools: set default properties. --- tools/Tools/src/main.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/Tools/src/main.cpp b/tools/Tools/src/main.cpp index b90cd72df..70661a07c 100644 --- a/tools/Tools/src/main.cpp +++ b/tools/Tools/src/main.cpp @@ -28,6 +28,12 @@ using namespace dxfcpp::literals; int main(int argc, char *argv[]) { try { + System::setProperty(DXEndpoint::DXFEED_WILDCARD_ENABLE_PROPERTY, "true"); + // Enable experimental feature. + System::setProperty("dxfeed.experimental.dxlink.enable", "true"); + // Set scheme for dxLink. + System::setProperty("scheme", "ext:opt:sysprops,resource:dxlink.xml"); + const auto usage = tools::HelpTool::generateToolHelpScreen(); std::vector args{}; @@ -97,7 +103,7 @@ int main(int argc, char *argv[]) { } catch (const GraalException &e) { std::cerr << e.what() << '\n'; std::cerr << e.getStackTrace() << '\n'; - } catch (const std::runtime_error& e) { + } catch (const std::runtime_error &e) { std::cerr << e.what() << '\n'; } catch (...) { std::cerr << "Error!\n"; From 723de08e33c276e8149023b871185016c54ed372 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Wed, 19 Jun 2024 12:47:26 +0300 Subject: [PATCH 18/28] [EN-7587] Implement FetchDailyCandles sample Move implementations to TU. --- .../api/DXFeedSubscription.hpp | 139 ++-------- src/api/DXFeedSubscription.cpp | 243 ++++++++++++------ 2 files changed, 184 insertions(+), 198 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp index ce0e99944..ce23424ad 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeedSubscription.hpp @@ -39,6 +39,9 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared(-1)}; + /// + using OnEventHandler = SimpleHandler> &)>; + private: friend struct DXFeed; @@ -53,7 +56,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared eventListenerHandle_; - SimpleHandler> &)> onEvent_{}; + OnEventHandler onEvent_{}; std::unordered_map> changeListeners_; std::recursive_mutex changeListenersMutex_{}; @@ -64,26 +67,12 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared getSymbolsImpl() const; - - std::vector getDecoratedSymbolsImpl() const; - public: /// The alias to a type of shared pointer to the DXFeedSubscription object using Ptr = std::shared_ptr; @@ -101,8 +90,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared dxfcpp::ConvertibleTo; } #endif - DXFeedSubscription(LockExternalConstructionTag tag, EventTypeIt begin, EventTypeIt end) - : DXFeedSubscription{tag} { + DXFeedSubscription(LockExternalConstructionTag tag, EventTypeIt begin, EventTypeIt end) : DXFeedSubscription{tag} { if constexpr (Debugger::isDebug) { // ReSharper disable once CppDFAUnreachableCode Debugger::debug("DXFeedSubscription(eventTypes = " + namesToString(begin, end) + ")"); @@ -148,19 +136,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared create(const EventTypeEnum &eventType) { - if constexpr (Debugger::isDebug) { - // ReSharper disable once CppDFAUnreachableCode - Debugger::debug("DXFeedSubscription::create(eventType = " + eventType.getName() + ")"); - } - - auto sub = createShared(eventType); - auto id = ApiContext::getInstance()->getManager()->registerEntity(sub); - - dxfcpp::ignore_unused(id); - - return sub; - } + static std::shared_ptr create(const EventTypeEnum &eventType); /** * Creates detached subscription for the given collection of event types. @@ -214,14 +190,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShareddetached subscription for the given collection of event types. */ - static std::shared_ptr create(std::initializer_list eventTypes) { - auto sub = createShared(eventTypes); - auto id = ApiContext::getInstance()->getManager()->registerEntity(sub); - - dxfcpp::ignore_unused(id); - - return sub; - } + static std::shared_ptr create(std::initializer_list eventTypes); /** * Creates detached subscription for the given collection of event types. @@ -314,7 +283,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared> &)>::FAKE_ID; + return OnEventHandler::FAKE_ID; } return onEvent_ += listener; @@ -401,9 +370,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared collection) const { - addSymbols(collection.begin(), collection.end()); - } + void addSymbols(std::initializer_list collection) const; /** * Removes the specified collection (using iterators) of symbols from the set of subscribed symbols. @@ -600,9 +543,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared collection) const { - removeSymbols(collection.begin(), collection.end()); - } + void removeSymbols(std::initializer_list collection) const; /** * Changes the set of subscribed symbols so that it contains just the symbols from the specified collection (using @@ -661,21 +602,12 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared collection) const { - setSymbols(collection.begin(), collection.end()); - } + void setSymbols(std::initializer_list collection) const; /** * Clears the set of subscribed symbols. */ - void clear() const { - if constexpr (Debugger::isDebug) { - // ReSharper disable once CppDFAUnreachableCode - Debugger::debug(toString() + "::clear()"); - } - - clearImpl(); - } + void clear() const; /** * Returns `true` if this subscription is closed. @@ -684,23 +616,14 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared getEventTypes() override { - return eventTypes_; - } + std::unordered_set getEventTypes() override; /** * Returns `true` if this subscription contains the corresponding event type. @@ -710,9 +633,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared getSymbols() const { - if constexpr (Debugger::isDebug) { - // ReSharper disable once CppDFAUnreachableCode - Debugger::debug(toString() + "::getSymbols()"); - } - - return getSymbolsImpl(); - } + std::vector getSymbols() const; /** * Returns a set of decorated symbols (depending on the actual implementation of subscription). @@ -739,18 +653,7 @@ class DXFCPP_EXPORT DXFeedSubscription : public RequireMakeShared getDecoratedSymbols() const { - if constexpr (Debugger::isDebug) { - // ReSharper disable once CppDFAUnreachableCode - Debugger::debug(toString() + "::getDecoratedSymbols()"); - } - - return getDecoratedSymbolsImpl(); - } - - auto getExecutor(); - - template void setExecutor(Executor &&executor); + std::vector getDecoratedSymbols() const; std::size_t addChangeListener(std::shared_ptr listener) override; diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index 303f65e33..55702bf67 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -28,6 +28,97 @@ struct DXFeedSubscription::Impl { } }; +JavaObjectHandle +DXFeedSubscription::createSubscriptionHandleFromEventClassList(const std::unique_ptr &list) { + return isolated::api::IsolatedDXFeedSubscription::create(list); +} + +void DXFeedSubscription::setEventListenerHandle(Id id) { + eventListenerHandle_ = isolated::api::IsolatedDXFeedSubscription::DXFeedEventListener::create( + dxfcpp::bit_cast(&Impl::onEvents), dxfcpp::bit_cast(id.getValue())); + + isolated::api::IsolatedDXFeedSubscription::addEventListener(handle_, eventListenerHandle_); +} + +bool DXFeedSubscription::tryToSetEventListenerHandle() { + std::lock_guard lock{eventListenerMutex_}; + + if (!eventListenerHandle_) { + auto idOpt = + ApiContext::getInstance()->getManager()->getId(sharedAs()); + + if (!idOpt) { + return false; + } + + setEventListenerHandle(idOpt.value()); + } + + return true; +} + +void DXFeedSubscription::addSymbolsImpl(void *graalSymbolList) const { + isolated::api::IsolatedDXFeedSubscription::addSymbols(handle_, graalSymbolList); +} + +void DXFeedSubscription::removeSymbolsImpl(void *graalSymbolList) const { + isolated::api::IsolatedDXFeedSubscription::removeSymbols(handle_, graalSymbolList); +} + +void DXFeedSubscription::setSymbolsImpl(void *graalSymbolList) const { + isolated::api::IsolatedDXFeedSubscription::setSymbols(handle_, graalSymbolList); +} + +DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag) + : impl_(std::make_unique()) { +} + +DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag tag, const EventTypeEnum &eventType) + : DXFeedSubscription{tag} { + if constexpr (Debugger::isDebug) { + Debugger::debug("DXFeedSubscription(eventType = " + eventType.getName() + ")"); + } + + eventTypes_ = std::unordered_set{eventType}; + handle_ = isolated::api::IsolatedDXFeedSubscription::create(eventType); +} + +std::string DXFeedSubscription::toString() const noexcept { + return fmt::format("DXFeedSubscription{{{}}}", handle_.toString()); +} + +DXFeedSubscription::~DXFeedSubscription() { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug("DXFeedSubscription{" + handle_.toString() + "}::~DXFeedSubscription()"); + } + + close(); +} + +std::shared_ptr DXFeedSubscription::create(const EventTypeEnum &eventType) { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug("DXFeedSubscription::create(eventType = " + eventType.getName() + ")"); + } + + auto sub = createShared(eventType); + auto id = ApiContext::getInstance()->getManager()->registerEntity(sub); + + dxfcpp::ignore_unused(id); + + return sub; +} + +std::shared_ptr DXFeedSubscription::create(std::initializer_list eventTypes) { + auto sub = createShared(eventTypes); + auto id = ApiContext::getInstance()->getManager()->registerEntity(sub); + + dxfcpp::ignore_unused(id); + + return sub; +} + void DXFeedSubscription::attach(std::shared_ptr feed) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::attach(feed = " + feed->toString() + ")"); @@ -50,135 +141,127 @@ void DXFeedSubscription::close() const { Debugger::debug(toString() + "::close()"); } - closeImpl(); + isolated::api::IsolatedDXFeedSubscription::close(handle_); } -std::size_t DXFeedSubscription::addChangeListener(std::shared_ptr listener) { - isolated::api::IsolatedDXFeedSubscription::addChangeListener(handle_, listener->getHandle()); +void DXFeedSubscription::removeEventListener(std::size_t listenerId) { + onEvent_ -= listenerId; +} - std::lock_guard guard{changeListenersMutex_}; +DXFeedSubscription::OnEventHandler &DXFeedSubscription::onEvent() { + tryToSetEventListenerHandle(); - if (lastChangeListenerId_ >= FAKE_CHANGE_LISTENER_ID - 1) { - return FAKE_CHANGE_LISTENER_ID; - } + return onEvent_; +} - auto id = ++lastChangeListenerId_; +void DXFeedSubscription::addSymbols(const SymbolWrapper &symbolWrapper) const { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug(toString() + "::addSymbols(symbolWrapper = " + toStringAny(symbolWrapper) + ")"); + } - changeListeners_.emplace(id, listener); + auto graal = symbolWrapper.toGraalUnique(); - return id; + isolated::api::IsolatedDXFeedSubscription::addSymbol(handle_, graal.get()); } -void DXFeedSubscription::removeChangeListener(std::size_t changeListenerId) { - std::lock_guard guard{changeListenersMutex_}; - - if (changeListenerId == FAKE_CHANGE_LISTENER_ID) { - return; +void DXFeedSubscription::removeSymbols(const SymbolWrapper &symbolWrapper) const { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug(toString() + "::removeSymbols(symbolWrapper = " + toStringAny(symbolWrapper) + ")"); } - if (auto found = changeListeners_.find(changeListenerId); found != changeListeners_.end()) { - auto listener = found->second; - - isolated::api::IsolatedDXFeedSubscription::removeChangeListener(handle_, listener->getHandle()); + auto graal = symbolWrapper.toGraalUnique(); - changeListeners_.erase(found); - } + isolated::api::IsolatedDXFeedSubscription::removeSymbol(handle_, graal.get()); } -void DXFeedSubscription::addSymbolImpl(void *graalSymbol) const { - isolated::api::IsolatedDXFeedSubscription::addSymbol(handle_, graalSymbol); +void DXFeedSubscription::addSymbols(std::initializer_list collection) const { + addSymbols(collection.begin(), collection.end()); } -void DXFeedSubscription::addSymbolsImpl(void *graalSymbolList) const { - isolated::api::IsolatedDXFeedSubscription::addSymbols(handle_, graalSymbolList); +void DXFeedSubscription::removeSymbols(std::initializer_list collection) const { + removeSymbols(collection.begin(), collection.end()); } -void DXFeedSubscription::removeSymbolImpl(void *graalSymbol) const { - isolated::api::IsolatedDXFeedSubscription::removeSymbol(handle_, graalSymbol); +void DXFeedSubscription::setSymbols(std::initializer_list collection) const { + setSymbols(collection.begin(), collection.end()); } -void DXFeedSubscription::removeSymbolsImpl(void *graalSymbolList) const { - isolated::api::IsolatedDXFeedSubscription::removeSymbols(handle_, graalSymbolList); -} +void DXFeedSubscription::clear() const { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug(toString() + "::clear()"); + } -void DXFeedSubscription::setSymbolsImpl(void *graalSymbolList) const { - isolated::api::IsolatedDXFeedSubscription::setSymbols(handle_, graalSymbolList); + isolated::api::IsolatedDXFeedSubscription::clear(handle_); } -std::vector DXFeedSubscription::getSymbolsImpl() const { - return isolated::api::IsolatedDXFeedSubscription::getSymbols(handle_); -} +bool DXFeedSubscription::isClosed() override { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug(toString() + "::isClosed()"); + } -std::vector DXFeedSubscription::getDecoratedSymbolsImpl() const { - return isolated::api::IsolatedDXFeedSubscription::getDecoratedSymbols(handle_); + return isolated::api::IsolatedDXFeedSubscription::isClosed(handle_); } -void DXFeedSubscription::closeImpl() const { - isolated::api::IsolatedDXFeedSubscription::close(handle_); +std::unordered_set DXFeedSubscription::getEventTypes() override { + return eventTypes_; } -void DXFeedSubscription::clearImpl() const { - isolated::api::IsolatedDXFeedSubscription::clear(handle_); +bool DXFeedSubscription::containsEventType(const EventTypeEnum &eventType) override { + return eventTypes_.contains(eventType); } -bool DXFeedSubscription::isClosedImpl() const { - return isolated::api::IsolatedDXFeedSubscription::isClosed(handle_); -} +std::vector DXFeedSubscription::getSymbols() const { + if constexpr (Debugger::isDebug) { + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug(toString() + "::getSymbols()"); + } -DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag) - : impl_(std::make_unique()) { + return isolated::api::IsolatedDXFeedSubscription::getSymbols(handle_); } -DXFeedSubscription::DXFeedSubscription(LockExternalConstructionTag tag, const EventTypeEnum &eventType) - : DXFeedSubscription{tag} { +std::vector DXFeedSubscription::getDecoratedSymbols() const { if constexpr (Debugger::isDebug) { - Debugger::debug("DXFeedSubscription(eventType = " + eventType.getName() + ")"); + // ReSharper disable once CppDFAUnreachableCode + Debugger::debug(toString() + "::getDecoratedSymbols()"); } - eventTypes_ = std::unordered_set{eventType}; - handle_ = isolated::api::IsolatedDXFeedSubscription::create(eventType); + return isolated::api::IsolatedDXFeedSubscription::getDecoratedSymbols(handle_); } -JavaObjectHandle -DXFeedSubscription::createSubscriptionHandleFromEventClassList(const std::unique_ptr &list) { - return isolated::api::IsolatedDXFeedSubscription::create(list); -} +std::size_t DXFeedSubscription::addChangeListener(std::shared_ptr listener) { + isolated::api::IsolatedDXFeedSubscription::addChangeListener(handle_, listener->getHandle()); -void DXFeedSubscription::setEventListenerHandle(Id id) { - eventListenerHandle_ = isolated::api::IsolatedDXFeedSubscription::DXFeedEventListener::create( - dxfcpp::bit_cast(&Impl::onEvents), dxfcpp::bit_cast(id.getValue())); + std::lock_guard guard{changeListenersMutex_}; - isolated::api::IsolatedDXFeedSubscription::addEventListener(handle_, eventListenerHandle_); -} + if (lastChangeListenerId_ >= FAKE_CHANGE_LISTENER_ID - 1) { + return FAKE_CHANGE_LISTENER_ID; + } -bool DXFeedSubscription::tryToSetEventListenerHandle() { - std::lock_guard lock{eventListenerMutex_}; + auto id = ++lastChangeListenerId_; - if (!eventListenerHandle_) { - auto idOpt = - ApiContext::getInstance()->getManager()->getId(sharedAs()); + changeListeners_.emplace(id, listener); - if (!idOpt) { - return false; - } + return id; +} - setEventListenerHandle(idOpt.value()); +void DXFeedSubscription::removeChangeListener(std::size_t changeListenerId) { + std::lock_guard guard{changeListenersMutex_}; + + if (changeListenerId == FAKE_CHANGE_LISTENER_ID) { + return; } - return true; -} + if (auto found = changeListeners_.find(changeListenerId); found != changeListeners_.end()) { + auto listener = found->second; -std::string DXFeedSubscription::toString() const noexcept { - return fmt::format("DXFeedSubscription{{{}}}", handle_.toString()); -} + isolated::api::IsolatedDXFeedSubscription::removeChangeListener(handle_, listener->getHandle()); -DXFeedSubscription::~DXFeedSubscription() { - if constexpr (Debugger::isDebug) { - // ReSharper disable once CppDFAUnreachableCode - Debugger::debug("DXFeedSubscription{" + handle_.toString() + "}::~DXFeedSubscription()"); + changeListeners_.erase(found); } - - closeImpl(); } DXFCPP_END_NAMESPACE \ No newline at end of file From 11dfa2685e989d80ffdcdcabd8a54a94ba1762b8 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Wed, 19 Jun 2024 13:00:45 +0300 Subject: [PATCH 19/28] [EN-7587] Implement FetchDailyCandles sample Move implementations to TU: fix build --- src/api/DXFeedSubscription.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/DXFeedSubscription.cpp b/src/api/DXFeedSubscription.cpp index 55702bf67..3ce0dc80d 100644 --- a/src/api/DXFeedSubscription.cpp +++ b/src/api/DXFeedSubscription.cpp @@ -197,7 +197,7 @@ void DXFeedSubscription::clear() const { isolated::api::IsolatedDXFeedSubscription::clear(handle_); } -bool DXFeedSubscription::isClosed() override { +bool DXFeedSubscription::isClosed() { if constexpr (Debugger::isDebug) { // ReSharper disable once CppDFAUnreachableCode Debugger::debug(toString() + "::isClosed()"); @@ -206,11 +206,11 @@ bool DXFeedSubscription::isClosed() override { return isolated::api::IsolatedDXFeedSubscription::isClosed(handle_); } -std::unordered_set DXFeedSubscription::getEventTypes() override { +std::unordered_set DXFeedSubscription::getEventTypes() { return eventTypes_; } -bool DXFeedSubscription::containsEventType(const EventTypeEnum &eventType) override { +bool DXFeedSubscription::containsEventType(const EventTypeEnum &eventType) { return eventTypes_.contains(eventType); } From b9fc0794ea3070993610a02be5d19d523452d495 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Sun, 23 Jun 2024 22:55:27 +0300 Subject: [PATCH 20/28] [EN-7587] Implement FetchDailyCandles sample Promise --- include/dxfeed_graal_cpp_api/api.hpp | 2 + .../isolated/promise/IsolatedPromise.hpp | 84 +++++++++++++++++++ .../dxfeed_graal_cpp_api/promise/Promise.hpp | 22 +++++ 3 files changed, 108 insertions(+) create mode 100644 include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp create mode 100644 include/dxfeed_graal_cpp_api/promise/Promise.hpp diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index 6db5ba345..a9e7c98b6 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -63,4 +63,6 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "ondemand/OnDemandService.hpp" +#include "promise/Promise.hpp" + DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp b/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp new file mode 100644 index 000000000..13fa2192e --- /dev/null +++ b/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp @@ -0,0 +1,84 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../../internal/Conf.hpp" + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::api::IsolatedPromise { + +/* + +dxfg_event_type_t* dxfg_Promise_EventType_getResult(graal_isolatethread_t *thread, dxfg_promise_event_t *promise); +dxfg_event_type_list* dxfg_Promise_List_EventType_getResult(graal_isolatethread_t *thread, dxfg_promise_events_t *promise); +dxfg_exception_t* dxfg_Promise_getException(graal_isolatethread_t *thread, dxfg_promise_t *promise); +int32_t dxfg_Promise_await(graal_isolatethread_t *thread, dxfg_promise_t *promise); +int32_t dxfg_Promise_await2(graal_isolatethread_t *thread, dxfg_promise_t *promise, int32_t timeoutInMilliseconds); +int32_t dxfg_Promise_awaitWithoutException(graal_isolatethread_t *thread, dxfg_promise_t *promise, int32_t timeoutInMilliseconds); +int32_t dxfg_Promise_cancel(graal_isolatethread_t *thread, dxfg_promise_t *promise); +int32_t dxfg_Promise_List_EventType_complete(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_event_type_list* events); +int32_t dxfg_Promise_EventType_complete(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_event_type_t* event); +int32_t dxfg_Promise_completeExceptionally(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_exception_t* exception); +int32_t dxfg_Promise_whenDone(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_promise_handler_function promise_handler_function, void *user_data); +int32_t dxfg_Promise_whenDoneAsync(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_promise_handler_function promise_handler_function, void *user_data, dxfg_executor_t* executor); +dxfg_promise_t* dxfg_Promise_completed(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_java_object_handler *handler); +dxfg_promise_t* dxfg_Promise_failed(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_exception_t* exception); + +dxfg_promise_t* dxfg_Promises_allOf(graal_isolatethread_t *thread, dxfg_promise_list *promises); + +*/ + +/** + * Calls the Graal SDK function `dxfg_Promise_isDone` in isolation. + * + * @param promise The promise's handle. + * @return `true` when computation has completed normally or exceptionally or was cancelled. + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +bool /* int32_t */ isDone(/* dxfg_promise_t * */ void* promise); + +/** + * Calls the Graal SDK function `dxfg_Promise_hasResult` in isolation. + * + * @param promise The promise's handle. + * @return `true` when computation has completed normally + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +bool /* int32_t */ hasResult(/* dxfg_promise_t * */ void* promise); + +/** + * Calls the Graal SDK function `dxfg_Promise_hasException` in isolation. + * + * @param promise The promise's handle. + * @return `true` when computation has completed exceptionally or was cancelled. + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +bool /* int32_t */ hasException(/* dxfg_promise_t * */ void* promise); + +/** + * Calls the Graal SDK function `dxfg_Promise_isCancelled` in isolation. + * + * @param promise The promise's handle. + * @return `true` when computation was cancelled. + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +bool /* int32_t */ isCancelled(/* dxfg_promise_t * */ void* promise); + + +} + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/include/dxfeed_graal_cpp_api/promise/Promise.hpp b/include/dxfeed_graal_cpp_api/promise/Promise.hpp new file mode 100644 index 000000000..09ff4bb58 --- /dev/null +++ b/include/dxfeed_graal_cpp_api/promise/Promise.hpp @@ -0,0 +1,22 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../internal/Conf.hpp" + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +DXFCPP_BEGIN_NAMESPACE + +template +struct Promise {}; + +template <> +struct Promise> { + +}; + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file From 5e2f52c7dee5ace16719359b2fbc6a94e2b6c22e Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 24 Jun 2024 19:17:20 +0300 Subject: [PATCH 21/28] [EN-7587] Implement FetchDailyCandles sample IsolatedPromise --- CMakeLists.txt | 1 + .../exceptions/JavaException.hpp | 8 +++ .../isolated/promise/IsolatedPromise.hpp | 67 +++++++++++++++++-- src/exceptions/JavaException.cpp | 16 +++-- src/isolated/promise/IsolatedPromise.cpp | 47 +++++++++++++ 5 files changed, 129 insertions(+), 10 deletions(-) create mode 100644 src/isolated/promise/IsolatedPromise.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 151bf03dc..f100aee1e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -195,6 +195,7 @@ set(dxFeedGraalCxxApi_Isolated_Sources src/isolated/api/IsolatedDXPublisher.cpp src/isolated/api/IsolatedDXPublisherObservableSubscription.cpp src/isolated/api/osub/IsolatedObservableSubscriptionChangeListener.cpp + src/isolated/promise/IsolatedPromise.cpp src/isolated/internal/IsolatedString.cpp src/isolated/internal/IsolatedTimeFormat.cpp ) diff --git a/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp b/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp index 7679731ba..0b46f2e77 100644 --- a/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp +++ b/include/dxfeed_graal_cpp_api/exceptions/JavaException.hpp @@ -27,6 +27,14 @@ struct DXFCPP_EXPORT JavaException : public std::runtime_error { */ JavaException(const std::string &message, const std::string &className, std::string stackTrace); + /** + * Creates an exception using native (GraalVM) Java exception handle + * + * @param exceptionHandle The native Java exception handle. + * @return An exception. + */ + static JavaException create(void* exceptionHandle); + /// Throws a JavaException if it exists (i.e. intercepted by Graal SDK) static void throwIfJavaThreadExceptionExists(); diff --git a/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp b/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp index 13fa2192e..9a32dea42 100644 --- a/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp @@ -7,17 +7,18 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) +#include "../../event/EventType.hpp" +#include "../../exceptions/JavaException.hpp" + +#include +#include + DXFCPP_BEGIN_NAMESPACE -namespace isolated::api::IsolatedPromise { +namespace isolated::promise::IsolatedPromise { /* -dxfg_event_type_t* dxfg_Promise_EventType_getResult(graal_isolatethread_t *thread, dxfg_promise_event_t *promise); -dxfg_event_type_list* dxfg_Promise_List_EventType_getResult(graal_isolatethread_t *thread, dxfg_promise_events_t *promise); -dxfg_exception_t* dxfg_Promise_getException(graal_isolatethread_t *thread, dxfg_promise_t *promise); -int32_t dxfg_Promise_await(graal_isolatethread_t *thread, dxfg_promise_t *promise); -int32_t dxfg_Promise_await2(graal_isolatethread_t *thread, dxfg_promise_t *promise, int32_t timeoutInMilliseconds); int32_t dxfg_Promise_awaitWithoutException(graal_isolatethread_t *thread, dxfg_promise_t *promise, int32_t timeoutInMilliseconds); int32_t dxfg_Promise_cancel(graal_isolatethread_t *thread, dxfg_promise_t *promise); int32_t dxfg_Promise_List_EventType_complete(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_event_type_list* events); @@ -76,6 +77,60 @@ bool /* int32_t */ hasException(/* dxfg_promise_t * */ void* promise); */ bool /* int32_t */ isCancelled(/* dxfg_promise_t * */ void* promise); +/** + * Calls the Graal SDK function `dxfg_Promise_EventType_getResult` in isolation. + * + * @param promise The promise's handle. + * @return event by promise + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +std::shared_ptr /* dxfg_event_type_t* */ getResult(/* dxfg_promise_event_t * */ void* promise); + +/** + * Calls the Graal SDK function `dxfg_Promise_List_EventType_getResult` in isolation. + * + * @param promise The promise's handle. + * @return events by promise + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +std::vector> /* dxfg_event_type_list* */ getResults(/* dxfg_promise_events_t * */ void* promise); + +/** + * Calls the Graal SDK function `dxfg_Promise_getException` in isolation. + * + * @param promise The promise's handle. + * @return exception by promise + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +JavaException /* dxfg_exception_t* */ getException(/* dxfg_promise_t * */ void* promise); + +/** + * Calls the Graal SDK function `dxfg_Promise_await` in isolation. + * + * @param promise The promise's handle. + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ await(/* dxfg_promise_t * */ void* promise); + +/** + * Calls the Graal SDK function `dxfg_Promise_await2` in isolation. + * + * @param promise The promise's handle. + * @param timeoutInMilliseconds The promise's timeout. + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ await(/* dxfg_promise_t * */ void* promise, std::int32_t timeoutInMilliseconds); + } diff --git a/src/exceptions/JavaException.cpp b/src/exceptions/JavaException.cpp index 6988fb8b1..647e98411 100644 --- a/src/exceptions/JavaException.cpp +++ b/src/exceptions/JavaException.cpp @@ -19,9 +19,7 @@ void JavaException::throwIfJavaThreadExceptionExists() { return; } - auto message = toString(exception->message); - auto className = toString(exception->class_name); - auto stackTrace = toString(exception->print_stack_trace); + auto javaException = create(exception); runIsolatedThrow( [](auto threadHandle, auto &&...params) { @@ -29,7 +27,7 @@ void JavaException::throwIfJavaThreadExceptionExists() { }, exception); - throw JavaException(message, className, stackTrace); + throw javaException; } void JavaException::throwException() { @@ -98,6 +96,16 @@ JavaException::JavaException(const std::string &message, const std::string &clas stackTrace_{std::move(stackTrace) + "\n" + stackTraceToString(boost::stacktrace::stacktrace())} { } +JavaException create(void* exceptionHandle) { + if (exceptionHandle == nullptr) { + return JavaException("", "", ""); + } + + dxfg_exception_t *exception = dxfcpp::bit_cast(exceptionHandle); + + return JavaException(toString(exception->message), toString(exception->class_name), toString(exception->print_stack_trace)); +} + const std::string &JavaException::getStackTrace() const & { return stackTrace_; } diff --git a/src/isolated/promise/IsolatedPromise.cpp b/src/isolated/promise/IsolatedPromise.cpp new file mode 100644 index 000000000..bcfc5f1e9 --- /dev/null +++ b/src/isolated/promise/IsolatedPromise.cpp @@ -0,0 +1,47 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::promise::IsolatedPromise { + +bool /* int32_t */ isDone(/* dxfg_promise_t * */ void* promise) { + return {}; +} + +bool /* int32_t */ hasResult(/* dxfg_promise_t * */ void* promise) { + return {}; +} + +bool /* int32_t */ hasException(/* dxfg_promise_t * */ void* promise) { + return {}; +} + +std::shared_ptr /* dxfg_event_type_t* */ getResult(/* dxfg_promise_event_t * */ void* promise) { + return {}; +} + +std::vector> /* dxfg_event_type_list* */ getResults(/* dxfg_promise_events_t * */ void* promise) { + return {}; +} + +JavaException /* dxfg_exception_t* */ getException(/* dxfg_promise_t * */ void* promise) { + return {"", "", ""}; +} + +void /* int32_t */ await(/* dxfg_promise_t * */ void* promise) { + +} + +void /* int32_t */ await(/* dxfg_promise_t * */ void* promise, std::int32_t timeoutInMilliseconds) { + +} + +} + +DXFCPP_END_NAMESPACE From 04c38dadee400caee73532c28a106d0b2308c076 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Mon, 24 Jun 2024 19:20:51 +0300 Subject: [PATCH 22/28] [EN-7587] Implement FetchDailyCandles sample JavaException::create --- src/exceptions/JavaException.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/exceptions/JavaException.cpp b/src/exceptions/JavaException.cpp index 647e98411..ff0d172e8 100644 --- a/src/exceptions/JavaException.cpp +++ b/src/exceptions/JavaException.cpp @@ -96,7 +96,7 @@ JavaException::JavaException(const std::string &message, const std::string &clas stackTrace_{std::move(stackTrace) + "\n" + stackTraceToString(boost::stacktrace::stacktrace())} { } -JavaException create(void* exceptionHandle) { +JavaException JavaException::create(void* exceptionHandle) { if (exceptionHandle == nullptr) { return JavaException("", "", ""); } From a1cf71f4476bd7a3fc787c34d42e59c11ff6e1e6 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Tue, 25 Jun 2024 16:49:06 +0300 Subject: [PATCH 23/28] [EN-7587] Implement FetchDailyCandles sample JavaException::create --- src/exceptions/JavaException.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/exceptions/JavaException.cpp b/src/exceptions/JavaException.cpp index ff0d172e8..7ee697f33 100644 --- a/src/exceptions/JavaException.cpp +++ b/src/exceptions/JavaException.cpp @@ -27,7 +27,7 @@ void JavaException::throwIfJavaThreadExceptionExists() { }, exception); - throw javaException; + throw javaException; // NOLINT(*-throw-by-value-catch-by-reference) } void JavaException::throwException() { @@ -96,14 +96,14 @@ JavaException::JavaException(const std::string &message, const std::string &clas stackTrace_{std::move(stackTrace) + "\n" + stackTraceToString(boost::stacktrace::stacktrace())} { } -JavaException JavaException::create(void* exceptionHandle) { +JavaException JavaException::create(void *exceptionHandle) { if (exceptionHandle == nullptr) { - return JavaException("", "", ""); + return {"", "", ""}; } - dxfg_exception_t *exception = dxfcpp::bit_cast(exceptionHandle); + auto *exception = dxfcpp::bit_cast(exceptionHandle); - return JavaException(toString(exception->message), toString(exception->class_name), toString(exception->print_stack_trace)); + return {toString(exception->message), toString(exception->class_name), toString(exception->print_stack_trace)}; } const std::string &JavaException::getStackTrace() const & { From 2e23a3001a94bf7b67c539c337fc294d7de63874 Mon Sep 17 00:00:00 2001 From: Anatoly Kalin Date: Tue, 25 Jun 2024 19:11:38 +0300 Subject: [PATCH 24/28] [EN-7587] Implement FetchDailyCandles sample IsolatedPromise --- .../isolated/promise/IsolatedPromise.hpp | 52 ++++++++++----- src/isolated/promise/IsolatedPromise.cpp | 63 +++++++++++++++++++ 2 files changed, 99 insertions(+), 16 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp b/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp index 9a32dea42..6ad680278 100644 --- a/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/promise/IsolatedPromise.hpp @@ -17,22 +17,6 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::promise::IsolatedPromise { -/* - -int32_t dxfg_Promise_awaitWithoutException(graal_isolatethread_t *thread, dxfg_promise_t *promise, int32_t timeoutInMilliseconds); -int32_t dxfg_Promise_cancel(graal_isolatethread_t *thread, dxfg_promise_t *promise); -int32_t dxfg_Promise_List_EventType_complete(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_event_type_list* events); -int32_t dxfg_Promise_EventType_complete(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_event_type_t* event); -int32_t dxfg_Promise_completeExceptionally(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_exception_t* exception); -int32_t dxfg_Promise_whenDone(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_promise_handler_function promise_handler_function, void *user_data); -int32_t dxfg_Promise_whenDoneAsync(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_promise_handler_function promise_handler_function, void *user_data, dxfg_executor_t* executor); -dxfg_promise_t* dxfg_Promise_completed(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_java_object_handler *handler); -dxfg_promise_t* dxfg_Promise_failed(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_exception_t* exception); - -dxfg_promise_t* dxfg_Promises_allOf(graal_isolatethread_t *thread, dxfg_promise_list *promises); - -*/ - /** * Calls the Graal SDK function `dxfg_Promise_isDone` in isolation. * @@ -131,6 +115,42 @@ void /* int32_t */ await(/* dxfg_promise_t * */ void* promise); */ void /* int32_t */ await(/* dxfg_promise_t * */ void* promise, std::int32_t timeoutInMilliseconds); +/** + * Calls the Graal SDK function `dxfg_Promise_awaitWithoutException` in isolation. + * + * @param promise The promise's handle. + * @param timeoutInMilliseconds The promise's timeout. + * @return `true` if the computation has completed normally; `false` when wait timed out. + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +bool /* int32_t */ awaitWithoutException(/* dxfg_promise_t * */ void* promise, std::int32_t timeoutInMilliseconds); + +/** + * Calls the Graal SDK function `dxfg_Promise_cancel` in isolation. + * + * @param promise The promise's handle. + * @throws std::invalid_argument if promise handle is nullptr. + * @throws JavaException if something happened with the dxFeed API backend. + * @throws GraalException if something happened with the GraalVM. + */ +void /* int32_t */ cancel(/* dxfg_promise_t * */ void* promise); + +/* + +int32_t dxfg_Promise_List_EventType_complete(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_event_type_list* events); +int32_t dxfg_Promise_EventType_complete(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_event_type_t* event); +int32_t dxfg_Promise_completeExceptionally(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_exception_t* exception); +int32_t dxfg_Promise_whenDone(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_promise_handler_function promise_handler_function, void *user_data); +int32_t dxfg_Promise_whenDoneAsync(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_promise_handler_function promise_handler_function, void *user_data, dxfg_executor_t* executor); +dxfg_promise_t* dxfg_Promise_completed(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_java_object_handler *handler); +dxfg_promise_t* dxfg_Promise_failed(graal_isolatethread_t *thread, dxfg_promise_t *promise, dxfg_exception_t* exception); + +dxfg_promise_t* dxfg_Promises_allOf(graal_isolatethread_t *thread, dxfg_promise_list *promises); + +*/ + } diff --git a/src/isolated/promise/IsolatedPromise.cpp b/src/isolated/promise/IsolatedPromise.cpp index bcfc5f1e9..1c27fd2a6 100644 --- a/src/isolated/promise/IsolatedPromise.cpp +++ b/src/isolated/promise/IsolatedPromise.cpp @@ -11,35 +11,98 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::promise::IsolatedPromise { bool /* int32_t */ isDone(/* dxfg_promise_t * */ void* promise) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_isDone`. The `promise` is nullptr"); + } + return {}; } bool /* int32_t */ hasResult(/* dxfg_promise_t * */ void* promise) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_hasResult`. The `promise` is nullptr"); + } + return {}; } bool /* int32_t */ hasException(/* dxfg_promise_t * */ void* promise) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_hasException`. The `promise` is nullptr"); + } + + return {}; +} + +bool /* int32_t */ isCancelled(/* dxfg_promise_t * */ void* promise) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_isCancelled`. The `promise` is nullptr"); + } + return {}; } std::shared_ptr /* dxfg_event_type_t* */ getResult(/* dxfg_promise_event_t * */ void* promise) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_EventType_getResult`. The `promise` is nullptr"); + } + return {}; } std::vector> /* dxfg_event_type_list* */ getResults(/* dxfg_promise_events_t * */ void* promise) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_List_EventType_getResult`. The `promise` is nullptr"); + } + return {}; } JavaException /* dxfg_exception_t* */ getException(/* dxfg_promise_t * */ void* promise) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_getException`. The `promise` is nullptr"); + } + return {"", "", ""}; } void /* int32_t */ await(/* dxfg_promise_t * */ void* promise) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_await`. The `promise` is nullptr"); + } } void /* int32_t */ await(/* dxfg_promise_t * */ void* promise, std::int32_t timeoutInMilliseconds) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_await2`. The `promise` is nullptr"); + } + +} + +bool /* int32_t */ awaitWithoutException(/* dxfg_promise_t * */ void* promise, std::int32_t timeoutInMilliseconds) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_awaitWithoutException`. The `promise` is nullptr"); + } + + return {}; +} +void /* int32_t */ cancel(/* dxfg_promise_t * */ void* promise) { + if (!promise) { + throw std::invalid_argument( + "Unable to execute function `dxfg_Promise_cancel`. The `promise` is nullptr"); + } } } From 009f8d89096a0e00712905657d3d60a2a423d736 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 28 Jun 2024 14:23:01 +0300 Subject: [PATCH 25/28] [EN-7587] Implement FetchDailyCandles sample IsolatedPromise --- .../event/EventMapper.hpp | 4 + src/event/EventMapper.cpp | 400 +++++++----------- src/isolated/promise/IsolatedPromise.cpp | 101 +++-- 3 files changed, 213 insertions(+), 292 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/event/EventMapper.hpp b/include/dxfeed_graal_cpp_api/event/EventMapper.hpp index 9ad6531ef..3879ca98a 100644 --- a/include/dxfeed_graal_cpp_api/event/EventMapper.hpp +++ b/include/dxfeed_graal_cpp_api/event/EventMapper.hpp @@ -15,8 +15,12 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) DXFCPP_BEGIN_NAMESPACE struct DXFCPP_EXPORT EventMapper { + static std::shared_ptr fromGraal(void* graalNativeEvent); + static std::vector> fromGraalList(void *graalNativeList); + static void freeGraal(void *graalNativeEvent); + template static void *toGraalList(EventIt begin, EventIt end) { if constexpr (Debugger::isDebug) { Debugger::debug("EventMapper::toGraalList(symbols = " + elementsToString(begin, end) + ")"); diff --git a/src/event/EventMapper.cpp b/src/event/EventMapper.cpp index f0dc7a486..32add654a 100644 --- a/src/event/EventMapper.cpp +++ b/src/event/EventMapper.cpp @@ -16,6 +16,58 @@ DXFCPP_BEGIN_NAMESPACE +std::shared_ptr EventMapper::fromGraal(void *graalNativeEvent) { + if (!graalNativeEvent) { + throw std::invalid_argument("The `graalNativeEvent` is nullptr"); + } + + // TODO: implement other types [EN-8235] + switch (auto *e = dxfcpp::bit_cast(graalNativeEvent); e->clazz) { + case DXFG_EVENT_QUOTE: + return Quote::fromGraal(e); + case DXFG_EVENT_PROFILE: + return Profile::fromGraal(e); + case DXFG_EVENT_SUMMARY: + return Summary::fromGraal(e); + case DXFG_EVENT_GREEKS: + return Greeks::fromGraal(e); + case DXFG_EVENT_CANDLE: + return Candle::fromGraal(e); + case DXFG_EVENT_DAILY_CANDLE: + throw std::invalid_argument("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); + case DXFG_EVENT_UNDERLYING: + return Underlying::fromGraal(e); + case DXFG_EVENT_THEO_PRICE: + return TheoPrice::fromGraal(e); + case DXFG_EVENT_TRADE: + return Trade::fromGraal(e); + case DXFG_EVENT_TRADE_ETH: + return TradeETH::fromGraal(e); + case DXFG_EVENT_CONFIGURATION: + throw std::invalid_argument("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); + case DXFG_EVENT_MESSAGE: + return Message::fromGraal(e); + case DXFG_EVENT_TIME_AND_SALE: + return TimeAndSale::fromGraal(e); + case DXFG_EVENT_ORDER_BASE: + throw std::invalid_argument("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); + case DXFG_EVENT_ORDER: + return Order::fromGraal(e); + case DXFG_EVENT_ANALYTIC_ORDER: + return AnalyticOrder::fromGraal(e); + case DXFG_EVENT_OTC_MARKETS_ORDER: + return OtcMarketsOrder::fromGraal(e); + case DXFG_EVENT_SPREAD_ORDER: + return SpreadOrder::fromGraal(e); + case DXFG_EVENT_SERIES: + return Series::fromGraal(e); + case DXFG_EVENT_OPTION_SALE: + return OptionSale::fromGraal(e); + default: + throw std::invalid_argument("Unknown event type: " + std::to_string(static_cast(e->clazz))); + } +} + std::vector> EventMapper::fromGraalList(void *graalNativeList) { auto list = static_cast(graalNativeList); @@ -27,89 +79,7 @@ std::vector> EventMapper::fromGraalList(void *graalNa result.reserve(static_cast(list->size)); for (std::size_t i = 0; i < static_cast(list->size); i++) { - auto *e = list->elements[i]; - - // TODO: implement other types [EN-8235] - // TODO: type traits - switch (e->clazz) { - case DXFG_EVENT_QUOTE: - result.emplace_back(Quote::fromGraal(e)); - - break; - case DXFG_EVENT_PROFILE: - result.emplace_back(Profile::fromGraal(e)); - - break; - case DXFG_EVENT_SUMMARY: - result.emplace_back(Summary::fromGraal(e)); - - break; - case DXFG_EVENT_GREEKS: - result.emplace_back(Greeks::fromGraal(e)); - - break; - case DXFG_EVENT_CANDLE: - result.emplace_back(Candle::fromGraal(e)); - - break; - case DXFG_EVENT_DAILY_CANDLE: - break; - case DXFG_EVENT_UNDERLYING: - result.emplace_back(Underlying::fromGraal(e)); - - break; - case DXFG_EVENT_THEO_PRICE: - result.emplace_back(TheoPrice::fromGraal(e)); - - break; - case DXFG_EVENT_TRADE: - result.emplace_back(Trade::fromGraal(e)); - - break; - case DXFG_EVENT_TRADE_ETH: - result.emplace_back(TradeETH::fromGraal(e)); - - break; - case DXFG_EVENT_CONFIGURATION: - break; - case DXFG_EVENT_MESSAGE: - result.emplace_back(Message::fromGraal(e)); - - break; - case DXFG_EVENT_TIME_AND_SALE: - result.emplace_back(TimeAndSale::fromGraal(e)); - - break; - case DXFG_EVENT_ORDER_BASE: - break; - case DXFG_EVENT_ORDER: - result.emplace_back(Order::fromGraal(e)); - - break; - case DXFG_EVENT_ANALYTIC_ORDER: - result.emplace_back(AnalyticOrder::fromGraal(e)); - - break; - case DXFG_EVENT_OTC_MARKETS_ORDER: - result.emplace_back(OtcMarketsOrder::fromGraal(e)); - - break; - case DXFG_EVENT_SPREAD_ORDER: - result.emplace_back(SpreadOrder::fromGraal(e)); - - break; - case DXFG_EVENT_SERIES: - result.emplace_back(Series::fromGraal(e)); - - break; - case DXFG_EVENT_OPTION_SALE: - result.emplace_back(OptionSale::fromGraal(e)); - - break; - - default: - throw std::invalid_argument("Unknown event type: " + std::to_string(static_cast(e->clazz))); - } + result.emplace_back(fromGraal(list->elements[i])); } result.shrink_to_fit(); @@ -117,6 +87,95 @@ std::vector> EventMapper::fromGraalList(void *graalNa return result; } +void EventMapper::freeGraal(void *graalNativeEvent) { + if (!graalNativeEvent) { + return; + } + + // TODO: implement other types [EN-8235] + switch (auto *e = dxfcpp::bit_cast(graalNativeEvent); e->clazz) { + case DXFG_EVENT_QUOTE: + Quote::freeGraal(e); + + break; + case DXFG_EVENT_PROFILE: + Profile::freeGraal(e); + + break; + case DXFG_EVENT_SUMMARY: + Summary::freeGraal(e); + + break; + case DXFG_EVENT_GREEKS: + Greeks::freeGraal(e); + + break; + case DXFG_EVENT_CANDLE: + Candle::freeGraal(e); + + break; + case DXFG_EVENT_DAILY_CANDLE: + throw std::invalid_argument("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); + + case DXFG_EVENT_UNDERLYING: + Underlying::freeGraal(e); + + break; + case DXFG_EVENT_THEO_PRICE: + TheoPrice::freeGraal(e); + + break; + case DXFG_EVENT_TRADE: + Trade::freeGraal(e); + + break; + case DXFG_EVENT_TRADE_ETH: + TradeETH::freeGraal(e); + + break; + case DXFG_EVENT_CONFIGURATION: + throw std::invalid_argument("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); + + case DXFG_EVENT_MESSAGE: + Message::freeGraal(e); + + break; + case DXFG_EVENT_TIME_AND_SALE: + TimeAndSale::freeGraal(e); + + break; + case DXFG_EVENT_ORDER_BASE: + throw std::invalid_argument("Not emplemented event type: " + std::to_string(static_cast(e->clazz))); + + case DXFG_EVENT_ORDER: + Order::freeGraal(e); + + break; + case DXFG_EVENT_ANALYTIC_ORDER: + AnalyticOrder::freeGraal(e); + + break; + case DXFG_EVENT_OTC_MARKETS_ORDER: + OtcMarketsOrder::freeGraal(e); + + break; + case DXFG_EVENT_SPREAD_ORDER: + SpreadOrder::freeGraal(e); + + break; + case DXFG_EVENT_SERIES: + Series::freeGraal(e); + + break; + case DXFG_EVENT_OPTION_SALE: + OptionSale::freeGraal(e); + + break; + default: + throw std::invalid_argument("Unknown event type: " + std::to_string(static_cast(e->clazz))); + } +} + void EventMapper::freeGraalList(void *graalList) { if constexpr (Debugger::isDebug) { Debugger::debug("EventMapper::freeGraalList(graalList = " + toStringAny(graalList) + ")"); @@ -133,90 +192,7 @@ void EventMapper::freeGraalList(void *graalList) { if (list->size > 0 && list->elements != nullptr) { for (SizeType elementIndex = 0; elementIndex < list->size; elementIndex++) { - if (list->elements[elementIndex]) { - auto *e = list->elements[elementIndex]; - - // TODO: implement other types [EN-8235] - // TODO: type traits - switch (e->clazz) { - case DXFG_EVENT_QUOTE: - Quote::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_PROFILE: - Profile::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_SUMMARY: - Summary::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_GREEKS: - Greeks::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_CANDLE: - Candle::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_DAILY_CANDLE: - break; - case DXFG_EVENT_UNDERLYING: - Underlying::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_THEO_PRICE: - TheoPrice::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_TRADE: - Trade::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_TRADE_ETH: - TradeETH::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_CONFIGURATION: - break; - case DXFG_EVENT_MESSAGE: - Message::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_TIME_AND_SALE: - TimeAndSale::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_ORDER_BASE: - break; - case DXFG_EVENT_ORDER: - Order::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_ANALYTIC_ORDER: - AnalyticOrder::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_OTC_MARKETS_ORDER: - OtcMarketsOrder::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_SPREAD_ORDER: - SpreadOrder::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_SERIES: - Series::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_OPTION_SALE: - OptionSale::freeGraal(static_cast(e)); - - break; - default: - throw std::invalid_argument("Unknown event type: " + std::to_string(static_cast(e->clazz))); - } - } + freeGraal(list->elements[elementIndex]); } delete[] list->elements; @@ -231,7 +207,9 @@ std::ptrdiff_t EventMapper::calculateGraalListSize(std::ptrdiff_t initSize) noex if (initSize < 0) { return 0; - } else if (initSize > std::numeric_limits::max()) { + } + + if (initSize > std::numeric_limits::max()) { return std::numeric_limits::max(); } @@ -282,91 +260,7 @@ bool EventMapper::freeGraalListElements(void *graalList, std::ptrdiff_t count) { auto *list = static_cast(graalList); for (SizeType i = 0; i < count; i++) { - if (list->elements[i]) { - auto *e = list->elements[i]; - - // TODO: implement other types [EN-8235] - // TODO: type traits - switch (e->clazz) { - case DXFG_EVENT_QUOTE: - Quote::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_PROFILE: - Profile::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_SUMMARY: - Summary::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_GREEKS: - Greeks::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_CANDLE: - Candle::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_DAILY_CANDLE: - break; - case DXFG_EVENT_UNDERLYING: - Underlying::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_THEO_PRICE: - TheoPrice::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_TRADE: - Trade::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_TRADE_ETH: - TradeETH::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_CONFIGURATION: - break; - case DXFG_EVENT_MESSAGE: - Message::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_TIME_AND_SALE: - TimeAndSale::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_ORDER_BASE: - break; - case DXFG_EVENT_ORDER: - Order::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_ANALYTIC_ORDER: - AnalyticOrder::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_OTC_MARKETS_ORDER: - OtcMarketsOrder::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_SPREAD_ORDER: - SpreadOrder::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_SERIES: - Series::freeGraal(static_cast(e)); - - break; - case DXFG_EVENT_OPTION_SALE: - OptionSale::freeGraal(static_cast(e)); - - break; - - default: - throw std::invalid_argument("Unknown event type: " + std::to_string(static_cast(e->clazz))); - } - } + freeGraal(list->elements[i]); } delete[] list->elements; diff --git a/src/isolated/promise/IsolatedPromise.cpp b/src/isolated/promise/IsolatedPromise.cpp index 1c27fd2a6..a3049a084 100644 --- a/src/isolated/promise/IsolatedPromise.cpp +++ b/src/isolated/promise/IsolatedPromise.cpp @@ -3,6 +3,7 @@ #include +#include #include #include @@ -10,101 +11,123 @@ DXFCPP_BEGIN_NAMESPACE namespace isolated::promise::IsolatedPromise { -bool /* int32_t */ isDone(/* dxfg_promise_t * */ void* promise) { +bool /* int32_t */ isDone(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_isDone`. The `promise` is nullptr"); + throw std::invalid_argument("Unable to execute function `dxfg_Promise_isDone`. The `promise` is nullptr"); } - return {}; + return runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_isDone, static_cast(promise)) == 1; } -bool /* int32_t */ hasResult(/* dxfg_promise_t * */ void* promise) { +bool /* int32_t */ hasResult(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_hasResult`. The `promise` is nullptr"); + throw std::invalid_argument("Unable to execute function `dxfg_Promise_hasResult`. The `promise` is nullptr"); } - return {}; + return runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_hasResult, static_cast(promise)) == 1; } -bool /* int32_t */ hasException(/* dxfg_promise_t * */ void* promise) { +bool /* int32_t */ hasException(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_hasException`. The `promise` is nullptr"); + throw std::invalid_argument("Unable to execute function `dxfg_Promise_hasException`. The `promise` is nullptr"); } - return {}; + return runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_hasException, static_cast(promise)) == + 1; } -bool /* int32_t */ isCancelled(/* dxfg_promise_t * */ void* promise) { +bool /* int32_t */ isCancelled(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_isCancelled`. The `promise` is nullptr"); + throw std::invalid_argument("Unable to execute function `dxfg_Promise_isCancelled`. The `promise` is nullptr"); } - return {}; + return runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_isCancelled, static_cast(promise)) == + 1; } -std::shared_ptr /* dxfg_event_type_t* */ getResult(/* dxfg_promise_event_t * */ void* promise) { +std::shared_ptr /* dxfg_event_type_t* */ getResult(/* dxfg_promise_event_t * */ void *promise) { if (!promise) { throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_EventType_getResult`. The `promise` is nullptr"); + "Unable to execute function `dxfg_Promise_EventType_getResult`. The `promise` is nullptr"); } - return {}; + auto *graalEvent = + runGraalFunctionAndThrowIfNullptr(dxfg_Promise_EventType_getResult, static_cast(promise)); + + auto result = dxfcpp::EventMapper::fromGraal(graalEvent); + + runGraalFunctionAndThrowIfLessThanZero(dxfg_EventType_release, graalEvent); + + return result; } -std::vector> /* dxfg_event_type_list* */ getResults(/* dxfg_promise_events_t * */ void* promise) { +std::vector> /* dxfg_event_type_list* */ +getResults(/* dxfg_promise_events_t * */ void *promise) { if (!promise) { throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_List_EventType_getResult`. The `promise` is nullptr"); + "Unable to execute function `dxfg_Promise_List_EventType_getResult`. The `promise` is nullptr"); } - return {}; + auto *graalEvents = runGraalFunctionAndThrowIfNullptr(dxfg_Promise_List_EventType_getResult, + static_cast(promise)); + + auto result = dxfcpp::EventMapper::fromGraalList(graalEvents); + + runGraalFunctionAndThrowIfLessThanZero(dxfg_CList_EventType_release, graalEvents); + + return result; } -JavaException /* dxfg_exception_t* */ getException(/* dxfg_promise_t * */ void* promise) { +JavaException /* dxfg_exception_t* */ getException(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_getException`. The `promise` is nullptr"); + throw std::invalid_argument("Unable to execute function `dxfg_Promise_getException`. The `promise` is nullptr"); } - return {"", "", ""}; + auto *graalException = + runGraalFunctionAndThrowIfNullptr(dxfg_Promise_getException, static_cast(promise)); + + auto result = JavaException::create(graalException); + + runGraalFunctionAndThrowIfLessThanZero(dxfg_Exception_release, graalException); + + return result; } -void /* int32_t */ await(/* dxfg_promise_t * */ void* promise) { +void /* int32_t */ await(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_await`. The `promise` is nullptr"); + throw std::invalid_argument("Unable to execute function `dxfg_Promise_await`. The `promise` is nullptr"); } + runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_await, static_cast(promise)); } -void /* int32_t */ await(/* dxfg_promise_t * */ void* promise, std::int32_t timeoutInMilliseconds) { +void /* int32_t */ await(/* dxfg_promise_t * */ void *promise, std::int32_t timeoutInMilliseconds) { if (!promise) { - throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_await2`. The `promise` is nullptr"); + throw std::invalid_argument("Unable to execute function `dxfg_Promise_await2`. The `promise` is nullptr"); } + runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_await2, static_cast(promise), + timeoutInMilliseconds); } -bool /* int32_t */ awaitWithoutException(/* dxfg_promise_t * */ void* promise, std::int32_t timeoutInMilliseconds) { +bool /* int32_t */ awaitWithoutException(/* dxfg_promise_t * */ void *promise, std::int32_t timeoutInMilliseconds) { if (!promise) { throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_awaitWithoutException`. The `promise` is nullptr"); + "Unable to execute function `dxfg_Promise_awaitWithoutException`. The `promise` is nullptr"); } - return {}; + return runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_awaitWithoutException, + static_cast(promise), timeoutInMilliseconds) == 1; } -void /* int32_t */ cancel(/* dxfg_promise_t * */ void* promise) { +void /* int32_t */ cancel(/* dxfg_promise_t * */ void *promise) { if (!promise) { - throw std::invalid_argument( - "Unable to execute function `dxfg_Promise_cancel`. The `promise` is nullptr"); + throw std::invalid_argument("Unable to execute function `dxfg_Promise_cancel`. The `promise` is nullptr"); } -} + runGraalFunctionAndThrowIfLessThanZero(dxfg_Promise_cancel, static_cast(promise)); } +} // namespace isolated::promise::IsolatedPromise + DXFCPP_END_NAMESPACE From 349dd21b0e9e71a8fbd1848f32d0f4216e5a3b56 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Fri, 28 Jun 2024 15:24:21 +0300 Subject: [PATCH 26/28] [EN-7587] Implement FetchDailyCandles sample IsolatedPromise --- include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp | 8 ++++++++ src/isolated/promise/IsolatedPromise.cpp | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp b/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp index 7e6aaeb5a..e5c8a501b 100644 --- a/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp +++ b/include/dxfeed_graal_cpp_api/isolated/IsolatedCommon.hpp @@ -46,6 +46,14 @@ constexpr auto throwIfMinusOne = [](auto v) { return JavaException::throwIfMinusOne(v); }; +constexpr auto runGraalFunction(auto graalFunction, auto &&...params) { + return runIsolatedThrow( + [](auto threadHandle, auto &&graalFunction, auto &&...params) { + return graalFunction(static_cast(threadHandle), params...); + }, + graalFunction, params...); +} + constexpr auto runGraalFunctionAndThrow(auto resultCheckerConverter, auto graalFunction, auto &&...params) { return runIsolatedThrow( [](auto threadHandle, auto &&resultCheckerConverter, auto &&graalFunction, auto &&...params) { diff --git a/src/isolated/promise/IsolatedPromise.cpp b/src/isolated/promise/IsolatedPromise.cpp index a3049a084..b88776ab2 100644 --- a/src/isolated/promise/IsolatedPromise.cpp +++ b/src/isolated/promise/IsolatedPromise.cpp @@ -51,8 +51,8 @@ std::shared_ptr /* dxfg_event_type_t* */ getResult(/* dxfg_promise_ev "Unable to execute function `dxfg_Promise_EventType_getResult`. The `promise` is nullptr"); } - auto *graalEvent = - runGraalFunctionAndThrowIfNullptr(dxfg_Promise_EventType_getResult, static_cast(promise)); + auto *graalEvent = runGraalFunctionAndThrowIfNullptr(dxfg_Promise_EventType_getResult, + static_cast(promise)); auto result = dxfcpp::EventMapper::fromGraal(graalEvent); @@ -69,7 +69,7 @@ getResults(/* dxfg_promise_events_t * */ void *promise) { } auto *graalEvents = runGraalFunctionAndThrowIfNullptr(dxfg_Promise_List_EventType_getResult, - static_cast(promise)); + static_cast(promise)); auto result = dxfcpp::EventMapper::fromGraalList(graalEvents); @@ -88,7 +88,7 @@ JavaException /* dxfg_exception_t* */ getException(/* dxfg_promise_t * */ void * auto result = JavaException::create(graalException); - runGraalFunctionAndThrowIfLessThanZero(dxfg_Exception_release, graalException); + runGraalFunction(dxfg_Exception_release, graalException); return result; } From 46378433960daf774c8635cbc7717fa967d8d6d1 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Sun, 30 Jun 2024 01:00:46 +0300 Subject: [PATCH 27/28] [EN-7587] Implement FetchDailyCandles sample IsolatedDXFeed --- CMakeLists.txt | 1 + include/dxfeed_graal_cpp_api/api.hpp | 1 + include/dxfeed_graal_cpp_api/api/DXFeed.hpp | 21 +++++--- .../internal/JavaObjectHandle.hpp | 41 ++++++++++++++++ .../isolated/api/IsolatedDXFeed.hpp | 48 ++++++++++++++++++ .../dxfeed_graal_cpp_api/promise/Promise.hpp | 49 +++++++++++++++++-- src/api/DXFeed.cpp | 23 ++++++--- src/internal/JavaObjectHandle.cpp | 26 +++++++++- src/isolated/api/IsolatedDXFeed.cpp | 36 ++++++++++++++ 9 files changed, 226 insertions(+), 20 deletions(-) create mode 100644 include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeed.hpp create mode 100644 src/isolated/api/IsolatedDXFeed.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f100aee1e..45f75ded4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -190,6 +190,7 @@ set(dxFeedGraalCxxApi_Exceptions_Sources ) set(dxFeedGraalCxxApi_Isolated_Sources + src/isolated/api/IsolatedDXFeed.cpp src/isolated/api/IsolatedDXEndpoint.cpp src/isolated/api/IsolatedDXFeedSubscription.cpp src/isolated/api/IsolatedDXPublisher.cpp diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index a9e7c98b6..343660403 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -52,6 +52,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "exceptions/JavaException.hpp" #include "exceptions/GraalException.hpp" +#include "isolated/api/IsolatedDXFeed.hpp" #include "isolated/api/IsolatedDXEndpoint.hpp" #include "isolated/api/IsolatedDXFeedSubscription.hpp" #include "isolated/api/IsolatedDXPublisher.hpp" diff --git a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp index c264d79ea..a17650624 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp @@ -12,6 +12,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) #include "../internal/Handler.hpp" #include "../internal/Isolate.hpp" #include "../internal/JavaObjectHandle.hpp" +#include "../promise/Promise.hpp" #include "DXFeedSubscription.hpp" @@ -146,7 +147,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * * @return The DXFeed instance */ - static std::shared_ptr getInstance() noexcept; + static std::shared_ptr getInstance(); /** * Attaches the given subscription to this feed. This method does nothing if the @@ -164,7 +165,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * @param subscription The subscription. * @see DXFeedSubscription */ - void attachSubscription(std::shared_ptr subscription) noexcept; + void attachSubscription(std::shared_ptr subscription); /** * Detaches the given subscription from this feed. This method does nothing if the @@ -178,7 +179,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * @param subscription The subscription. * @see DXFeedSubscription */ - void detachSubscription(std::shared_ptr subscription) noexcept; + void detachSubscription(std::shared_ptr subscription); /** * Detaches the given subscription from this feed and clears data delivered to this subscription @@ -188,7 +189,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * @param subscription The subscription. * @see DXFeed::detachSubscription() */ - void detachSubscriptionAndClear(std::shared_ptr subscription) noexcept; + void detachSubscriptionAndClear(std::shared_ptr subscription); /** * Creates new subscription for a single event type that is attached to this feed. @@ -202,7 +203,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * @param eventType The type of event * @return The new subscription */ - std::shared_ptr createSubscription(const EventTypeEnum &eventType) noexcept; + std::shared_ptr createSubscription(const EventTypeEnum &eventType); /** * Creates new subscription for multiple event types that is attached to this feed. @@ -235,7 +236,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * @return The new subscription */ template - std::shared_ptr createSubscription(EventTypeIt begin, EventTypeIt end) noexcept { + std::shared_ptr createSubscription(EventTypeIt begin, EventTypeIt end) { if constexpr (Debugger::isDebug) { Debugger::debug("{}::createSubscription(eventTypes = " + namesToString(begin, end) + ")"); } @@ -259,7 +260,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * @param eventTypes The initializer list of event types * @return The new subscription */ - std::shared_ptr createSubscription(std::initializer_list eventTypes) noexcept; + std::shared_ptr createSubscription(std::initializer_list eventTypes); /** * Creates new subscription for multiple event types that is attached to this feed. @@ -281,7 +282,7 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { * @return The new subscription */ template - std::shared_ptr createSubscription(EventTypesCollection &&eventTypes) noexcept { + std::shared_ptr createSubscription(EventTypesCollection &&eventTypes) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::createSubscription(eventTypes = " + namesToString(std::begin(eventTypes), std::end(eventTypes)) + ")"); @@ -294,6 +295,10 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { return sub; } + Promise>> getTimeSeriesPromise(const EventTypeEnum &eventType, + const SymbolWrapper &symbol, std::int64_t fromTime, + std::int64_t toTime); + std::string toString() const noexcept override; }; diff --git a/include/dxfeed_graal_cpp_api/internal/JavaObjectHandle.hpp b/include/dxfeed_graal_cpp_api/internal/JavaObjectHandle.hpp index 7474193c6..7dd5b613f 100644 --- a/include/dxfeed_graal_cpp_api/internal/JavaObjectHandle.hpp +++ b/include/dxfeed_graal_cpp_api/internal/JavaObjectHandle.hpp @@ -55,6 +55,47 @@ template struct JavaObjectHandle { std::unique_ptr impl_; }; +template struct JavaObjectHandleList { +#if DXFCPP_DEBUG == 1 + static auto getDebugName() { + return std::string("JavaObjectHandleList<") + typeid(T).name() + ">"; + } +#endif + + using Type = T; + + static DXFCPP_EXPORT void deleter(void *handle) noexcept; + explicit JavaObjectHandleList(void *handle = nullptr) noexcept : impl_{handle, &deleter} { + if constexpr (Debugger::isDebug) { + Debugger::debug(getDebugName() + "(handle = " + dxfcpp::toString(handle) + ")"); + } + } + + JavaObjectHandleList(const JavaObjectHandleList &) = delete; + JavaObjectHandleList(JavaObjectHandleList &&) noexcept = default; + JavaObjectHandleList &operator=(const JavaObjectHandleList &) = delete; + JavaObjectHandleList &operator=(JavaObjectHandleList &&) noexcept = default; + virtual ~JavaObjectHandleList() noexcept = default; + + [[nodiscard]] std::string toString() const noexcept { + if (impl_) + return dxfcpp::toString(impl_.get()); + else + return "nullptr"; + } + + [[nodiscard]] void *get() const noexcept { + return impl_.get(); + } + + explicit operator bool() const noexcept { + return static_cast(impl_); + } + + private: + std::unique_ptr impl_; +}; + DXFCPP_END_NAMESPACE DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeed.hpp b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeed.hpp new file mode 100644 index 000000000..8fe95894e --- /dev/null +++ b/include/dxfeed_graal_cpp_api/isolated/api/IsolatedDXFeed.hpp @@ -0,0 +1,48 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include "../../internal/Conf.hpp" + +DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) + +#include "../../api/DXFeed.hpp" + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::api::IsolatedDXFeed { + +/* + +dxfg_feed_t* dxfg_DXFeed_getInstance(graal_isolatethread_t *thread); +dxfg_subscription_t* dxfg_DXFeed_createSubscription(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz); +dxfg_subscription_t* dxfg_DXFeed_createSubscription2(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_list_t *eventClazzes); +dxfg_time_series_subscription_t* dxfg_DXFeed_createTimeSeriesSubscription(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz); +dxfg_time_series_subscription_t* dxfg_DXFeed_createTimeSeriesSubscription2(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_list_t *eventClazzes); +int32_t dxfg_DXFeed_attachSubscription(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_subscription_t *sub); +int32_t dxfg_DXFeed_detachSubscription(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_subscription_t *sub); +int32_t dxfg_DXFeed_detachSubscriptionAndClear(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_subscription_t *sub); +dxfg_event_type_t* dxfg_DXFeed_getLastEventIfSubscribed(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol); +dxfg_event_type_list* dxfg_DXFeed_getIndexedEventsIfSubscribed(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol, const char *source); +dxfg_event_type_list* dxfg_DXFeed_getTimeSeriesIfSubscribed(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol, int64_t from_time, int64_t to_time); +// use dxfg_EventType_new to create an empty structure so that java tries to free up memory when replacing subjects +int32_t dxfg_DXFeed_getLastEvent(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_type_t *event); +int32_t dxfg_DXFeed_getLastEvents(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_type_list *events); +dxfg_promise_event_t* dxfg_DXFeed_getLastEventPromise(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol); +dxfg_promise_list* dxfg_DXFeed_getLastEventsPromises(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_list *symbols); +dxfg_promise_events_t* dxfg_DXFeed_getIndexedEventsPromise(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t eventClazz, dxfg_symbol_t *symbol, dxfg_indexed_event_source_t* source); +dxfg_promise_events_t* dxfg_DXFeed_getTimeSeriesPromise(graal_isolatethread_t *thread, dxfg_feed_t *feed, dxfg_event_clazz_t clazz, dxfg_symbol_t *symbol, int64_t fromTime, int64_t toTime); + +*/ + + +/* dxfg_promise_events_t* */ void* getTimeSeriesPromise(/* dxfg_feed_t * */ const JavaObjectHandle& feed, /* dxfg_event_clazz_t */ const EventTypeEnum &eventType, /* dxfg_symbol_t * */ const SymbolWrapper &symbol, std::int64_t fromTime, + std::int64_t toTime); + + +} + +DXFCPP_END_NAMESPACE + +DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/include/dxfeed_graal_cpp_api/promise/Promise.hpp b/include/dxfeed_graal_cpp_api/promise/Promise.hpp index 09ff4bb58..738480fba 100644 --- a/include/dxfeed_graal_cpp_api/promise/Promise.hpp +++ b/include/dxfeed_graal_cpp_api/promise/Promise.hpp @@ -7,16 +7,57 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) +#include +#include + DXFCPP_BEGIN_NAMESPACE -template -struct Promise {}; +struct TimeSeriesEvent; +struct LastingEvent; + +struct PromiseImpl { + +}; + +template struct Promise { +}; + +template +concept Derived = std::is_base_of_v; -template <> -struct Promise> { +template T> struct Promise> { }; +template T> struct Promise> { + +}; + +template T> struct Promise>> { + +}; + + +// +// Promise> x{}; +// auto _ = x.z(); +// +// template struct PromiseSFINAE { +// int x() { +// return {}; +// } +// }; +// +// template +// struct PromiseSFINAE::value>::type> { +// int z() { +// return 0; +// } +// }; +// +// PromiseSFINAE> xx{}; +// auto __ = xx.z(); + DXFCPP_END_NAMESPACE DXFCXX_DISABLE_MSC_WARNINGS_POP() \ No newline at end of file diff --git a/src/api/DXFeed.cpp b/src/api/DXFeed.cpp index 087c05fc3..170f95c35 100644 --- a/src/api/DXFeed.cpp +++ b/src/api/DXFeed.cpp @@ -16,7 +16,7 @@ DXFCPP_BEGIN_NAMESPACE -std::shared_ptr DXFeed::getInstance() noexcept { +std::shared_ptr DXFeed::getInstance() { if constexpr (Debugger::isDebug) { Debugger::debug("DXFeed::getInstance()"); } @@ -24,7 +24,7 @@ std::shared_ptr DXFeed::getInstance() noexcept { return DXEndpoint::getInstance()->getFeed(); } -void DXFeed::attachSubscription(std::shared_ptr subscription) noexcept { +void DXFeed::attachSubscription(std::shared_ptr subscription) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::attachSubscription(" + subscription->toString() + ")"); } @@ -43,7 +43,7 @@ void DXFeed::attachSubscription(std::shared_ptr subscription } } -void DXFeed::detachSubscription(std::shared_ptr subscription) noexcept { +void DXFeed::detachSubscription(std::shared_ptr subscription) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::detachSubscription(" + subscription->toString() + ")"); } @@ -62,7 +62,7 @@ void DXFeed::detachSubscription(std::shared_ptr subscription } } -void DXFeed::detachSubscriptionAndClear(std::shared_ptr subscription) noexcept { +void DXFeed::detachSubscriptionAndClear(std::shared_ptr subscription) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::detachSubscriptionAndClear(" + subscription->toString() + ")"); } @@ -81,7 +81,7 @@ void DXFeed::detachSubscriptionAndClear(std::shared_ptr subs } } -std::shared_ptr DXFeed::createSubscription(const EventTypeEnum &eventType) noexcept { +std::shared_ptr DXFeed::createSubscription(const EventTypeEnum &eventType) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::createSubscription(eventType = " + eventType.getName() + ")"); } @@ -93,8 +93,7 @@ std::shared_ptr DXFeed::createSubscription(const EventTypeEn return sub; } -std::shared_ptr -DXFeed::createSubscription(std::initializer_list eventTypes) noexcept { +std::shared_ptr DXFeed::createSubscription(std::initializer_list eventTypes) { if constexpr (Debugger::isDebug) { Debugger::debug(toString() + "::createSubscription(eventTypes = " + namesToString(eventTypes.begin(), eventTypes.end()) + ")"); @@ -122,6 +121,16 @@ std::shared_ptr DXFeed::create(void *feedHandle) { return feed; } +Promise>> DXFeed::getTimeSeriesPromise(const EventTypeEnum &eventType, + const SymbolWrapper &symbol, + std::int64_t fromTime, + std::int64_t toTime) { + + // TODO: impelement + + return {}; +} + std::string DXFeed::toString() const noexcept { return fmt::format("DXFeed{{{}}}", handle_.toString()); } diff --git a/src/internal/JavaObjectHandle.cpp b/src/internal/JavaObjectHandle.cpp index 21893ddc0..87e84284e 100644 --- a/src/internal/JavaObjectHandle.cpp +++ b/src/internal/JavaObjectHandle.cpp @@ -26,7 +26,31 @@ template void JavaObjectHandle::deleter(void *handle) noexcept { dxfcpp::ignore_unused(result); if constexpr (Debugger::isDebug) { - Debugger::debug(getDebugName() + "::deleter(handle = " + dxfcpp::toString(handle) + ") -> " + dxfcpp::toString(result)); + Debugger::debug(getDebugName() + "::deleter(handle = " + dxfcpp::toString(handle) + ") -> " + + dxfcpp::toString(result)); + } +} + +template void JavaObjectHandleList::deleter(void *handle) noexcept { + auto result = runIsolatedOrElse( + [handle = handle](auto threadHandle) { + if constexpr (Debugger::isDebug) { + Debugger::debug(getDebugName() + "::deleter(handle = " + dxfcpp::toString(handle) + ")"); + } + + if (handle) { + return dxfg_CList_JavaObjectHandler_release(static_cast(threadHandle), + static_cast(handle)) == 0; + } + + return true; + }, + false); + dxfcpp::ignore_unused(result); + + if constexpr (Debugger::isDebug) { + Debugger::debug(getDebugName() + "::deleter(handle = " + dxfcpp::toString(handle) + ") -> " + + dxfcpp::toString(result)); } } diff --git a/src/isolated/api/IsolatedDXFeed.cpp b/src/isolated/api/IsolatedDXFeed.cpp new file mode 100644 index 000000000..1358bd752 --- /dev/null +++ b/src/isolated/api/IsolatedDXFeed.cpp @@ -0,0 +1,36 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +namespace isolated::api::IsolatedDXFeed { + +/* dxfg_promise_events_t* */ void *getTimeSeriesPromise(/* dxfg_feed_t * */ const JavaObjectHandle &feed, + /* dxfg_event_clazz_t */ const EventTypeEnum &eventType, + /* dxfg_symbol_t * */ const SymbolWrapper &symbol, + std::int64_t fromTime, std::int64_t toTime) { + if (!feed) { + throw std::invalid_argument( + "Unable to execute function `dxfg_DXFeed_getTimeSeriesPromise`. The `feed` handle is invalid"); + } + + auto graalSymbol = symbol.toGraal(); + + auto result = dxfcpp::bit_cast( + runGraalFunctionAndThrowIfNullptr(dxfg_DXFeed_getTimeSeriesPromise, static_cast(feed.get()), + static_cast(eventType.getId()), + static_cast(graalSymbol), fromTime, toTime)); + + SymbolWrapper::freeGraal(graalSymbol); + + return result; +} + +} // namespace isolated::api::IsolatedDXFeed + +DXFCPP_END_NAMESPACE \ No newline at end of file From 20ccd9fb9aaf22b7543f53eb76bb09848f5aeef8 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Mon, 1 Jul 2024 00:38:21 +0300 Subject: [PATCH 28/28] [EN-7587] Implement FetchDailyCandles sample --- CMakeLists.txt | 5 + README.md | 2 + include/dxfeed_graal_cpp_api/api.hpp | 1 + include/dxfeed_graal_cpp_api/api/DXFeed.hpp | 21 +- .../dxfeed_graal_cpp_api/promise/Promise.hpp | 343 ++++++++++++++++-- samples/cpp/FetchDailyCandles/src/main.cpp | 14 +- src/api/DXFeed.cpp | 11 +- src/exceptions/JavaException.cpp | 2 +- src/internal/JavaObjectHandle.cpp | 4 + src/promise/Promise.cpp | 80 ++++ 10 files changed, 437 insertions(+), 46 deletions(-) create mode 100644 src/promise/Promise.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 45f75ded4..154d73136 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -230,6 +230,10 @@ set(dxFeedGraalCxxApi_OnDemand_Sources src/ondemand/OnDemandService.cpp ) +set(dxFeedGraalCxxApi_Promise_Sources + src/promise/Promise.cpp +) + set(dxFeedGraalCxxApi_Symbols_Sources src/symbols/StringSymbol.cpp src/symbols/SymbolWrapper.cpp @@ -317,6 +321,7 @@ set(dxFeedGraalCxxApi_Sources ${dxFeedGraalCxxApi_ApiOsub_Sources} ${dxFeedGraalCxxApi_Ipf_Sources} ${dxFeedGraalCxxApi_OnDemand_Sources} + ${dxFeedGraalCxxApi_Promise_Sources} ${dxFeedGraalCxxApi_Symbols_Sources} ${dxFeedGraalCxxApi_System_Sources} ${dxFeedGraalCxxApi_Event_Sources} diff --git a/README.md b/README.md index 7e65d43ad..e8e09ffd1 100644 --- a/README.md +++ b/README.md @@ -355,6 +355,8 @@ versions): is a simple demonstration of how to get various scheduling information for instruments - [x] [OnDemandSample](https://github.com/dxFeed/dxfeed-graal-cxx-api/blob/main/samples/cpp/OnDemandSample/src/main.cpp) a sample that demonstrates how to use the dxFeed on-demand history data replay service API +- [x] [FetchDailyCandles](https://github.com/dxFeed/dxfeed-graal-cxx-api/blob/main/samples/cpp/FetchDailyCandles/src/main.cpp) + a sample that demonstrates how to fetch last 20 days of candles for a specified symbol and print them. ## Current State diff --git a/include/dxfeed_graal_cpp_api/api.hpp b/include/dxfeed_graal_cpp_api/api.hpp index 343660403..26a9222fb 100644 --- a/include/dxfeed_graal_cpp_api/api.hpp +++ b/include/dxfeed_graal_cpp_api/api.hpp @@ -58,6 +58,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996) #include "isolated/api/IsolatedDXPublisher.hpp" #include "isolated/api/IsolatedDXPublisherObservableSubscription.hpp" #include "isolated/api/osub/IsolatedObservableSubscriptionChangeListener.hpp" +#include "isolated/promise/IsolatedPromise.hpp" #include "isolated/internal/IsolatedString.hpp" #include "isolated/internal/IsolatedTimeFormat.hpp" #include "isolated/internal/IsolatedTools.hpp" diff --git a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp index a17650624..acce0eae5 100644 --- a/include/dxfeed_graal_cpp_api/api/DXFeed.hpp +++ b/include/dxfeed_graal_cpp_api/api/DXFeed.hpp @@ -125,6 +125,9 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { JavaObjectHandle handle_; static std::shared_ptr create(void *feedHandle); + void *getTimeSeriesPromiseImpl(const EventTypeEnum &eventType, const SymbolWrapper &symbol, std::int64_t fromTime, + std::int64_t toTime) const; + protected: DXFeed() noexcept : handle_{} { if constexpr (Debugger::isDebug) { @@ -295,9 +298,21 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity { return sub; } - Promise>> getTimeSeriesPromise(const EventTypeEnum &eventType, - const SymbolWrapper &symbol, std::int64_t fromTime, - std::int64_t toTime); + /** + * Requests time series of events for the specified event type, symbol, and a range of time. + * @tparam E The type of event. + * @param symbol The symbol. + * @param fromTime The time, inclusive, to request events from (see TimeSeriesEvent::getTime()). + * @param toTime The time, inclusive, to request events to (see TimeSeriesEvent::getTime()). + * Use `std::numeric_limits::max()` or `LLONG_MAX` macro to retrieve events without an + * upper limit on time. + * @return The promise for the result of the request. + */ + template E> + Promise>> getTimeSeriesPromise(const SymbolWrapper &symbol, std::int64_t fromTime, + std::int64_t toTime) const { + return Promise>>(getTimeSeriesPromiseImpl(E::TYPE, symbol, fromTime, toTime)); + } std::string toString() const noexcept override; }; diff --git a/include/dxfeed_graal_cpp_api/promise/Promise.hpp b/include/dxfeed_graal_cpp_api/promise/Promise.hpp index 738480fba..5bfc5c809 100644 --- a/include/dxfeed_graal_cpp_api/promise/Promise.hpp +++ b/include/dxfeed_graal_cpp_api/promise/Promise.hpp @@ -3,60 +3,349 @@ #pragma once +#include "../exceptions/JavaException.hpp" #include "../internal/Conf.hpp" DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251) +#include #include #include DXFCPP_BEGIN_NAMESPACE -struct TimeSeriesEvent; -struct LastingEvent; +struct EventType; +struct JavaException; + +template +concept Derived = std::is_base_of_v; + +template EDerived> +std::shared_ptr convertEvent(const std::shared_ptr &source) { + return source->template sharedAs(); +} + +template EDerived> +std::vector> convertEvents(const std::vector> &source) { + std::vector> result{}; + + result.reserve(source.size()); + + for (const auto &e : source) { + result.emplace_back(e->template sharedAs()); + } + + return result; +} struct PromiseImpl { + protected: + void *handle = nullptr; + + public: + explicit PromiseImpl(void *handle); + bool isDone() const; + bool hasResult() const; + bool hasException() const; + bool isCancelled() const; + JavaException getException() const; + void await() const; + void await(std::int32_t timeoutInMilliseconds) const; + bool awaitWithoutException(std::int32_t timeoutInMilliseconds) const; + void cancel() const; }; -template struct Promise { +struct EventPromiseImpl : PromiseImpl { + void *handle = nullptr; + + explicit EventPromiseImpl(void *handle); + ~EventPromiseImpl(); + std::shared_ptr getResult() const; }; -template -concept Derived = std::is_base_of_v; +struct EventsPromiseImpl : PromiseImpl { + void *handle = nullptr; + + explicit EventsPromiseImpl(void *handle); + ~EventsPromiseImpl(); + std::vector> getResult() const; +}; + +/** + * Mixin for wrapping calls to common promise methods. + * + * @tparam P The promise type + */ +template struct CommonPromiseMixin { + /** + * Returns `true` when computation has completed normally, or exceptionally, or was cancelled. + * + * @return `true` when computation has completed. + */ + bool isDone() const { + return static_cast(this)->impl.isDone(); + } + + /** + * Returns `true` when computation has completed normally. + * Use ::getResult() method to get the result of the computation. + * @return `true` when computation has completed normally. + * @see ::getResult() + */ + bool hasResult() const { + return static_cast(this)->impl.hasResult(); + } + + /** + * Returns `true` when computation has completed exceptionally or was cancelled. + * Use ::getException() method to get the exceptional outcome of the computation. + * @return `true` when computation has completed exceptionally or was cancelled. + */ + bool hasException() const { + return static_cast(this)->impl.hasException(); + } + + /** + * Returns `true` when computation was cancelled. + * Use ::getException() method to get the corresponding CancellationException. + * @return `true` when computation was cancelled. + * @see ::getException() + */ + bool isCancelled() const { + return static_cast(this)->impl.isCancelled(); + } + + /** + * Returns exceptional outcome of computation. If computation has no ::hasException() exception, + * then this method returns an exception with a message "null". If computation has completed exceptionally or was + * cancelled, then the result of this method is not an exception with a message "null". If computation was @ref + * ::isCancelled() "cancelled", then this method returns "an instance of CancellationException". + * + * @return exceptional outcome of computation. + * @see ::hasException() + */ + JavaException getException() const { + return static_cast(this)->impl.getException(); + } + + /** + * Wait for computation to complete or timeout or throw an exception in case of exceptional completion. + * If the wait is interrupted, then the computation is @ref ::cancel() "cancelled", + * the interruption flag on the current thread is set, and "CancellationException" is thrown. + * + *

If the wait times out, then the computation is @ref ::cancel() "cancelled" and this method returns `false`. + * Use this method in the code that shall continue normal execution in case of timeout. + * + * @param timeoutInMilliseconds The timeout. + * @return `true` if the computation has completed normally; `false` when wait timed out. + * @throws CancellationException if computation was cancelled. + * @throws PromiseException if computation has completed exceptionally. + */ + bool awaitWithoutException(std::int32_t timeoutInMilliseconds) const { + return static_cast(this)->impl.awaitWithoutException(timeoutInMilliseconds); + } + + /** + * Wait for computation to complete or timeout or throw an exception in case of exceptional completion. + * If the wait is interrupted, then the computation is @ref ::cancel() "cancelled", + * the interruption flag on the current thread is set, and "CancellationException" is thrown. + * + *

If the wait times out, then the computation is @ref ::cancel() "cancelled" and this method returns `false`. + * Use this method in the code that shall continue normal execution in case of timeout. + * + * @param timeoutInMilliseconds The timeout. + * @return `true` if the computation has completed normally; `false` when wait timed out. + * @throws CancellationException if computation was cancelled. + * @throws PromiseException if computation has completed exceptionally. + */ + bool awaitWithoutException(const std::chrono::milliseconds &timeoutInMilliseconds) const { + auto timeout = timeoutInMilliseconds.count(); + + if (timeout > std::numeric_limits::max()) { + timeout = std::numeric_limits::max(); + } -template T> struct Promise> { + return static_cast(this)->impl.awaitWithoutException(timeout); + } + /** + * Cancels computation. This method does nothing if computation has already @ref ::isDone() "completed". + * + *

If cancelled, then ::getException() will return "CancellationException", + * @ref ::isDone() "isDone", @ref ::isCancelled() "isCancelled", and @ref ::hasException() "hasException" will + * return `true`, all handlers that were installed with `whenDone` method are notified by invoking their + * `promiseDone` method, and all waiters on @ref ::await() "join" method throw "CancellationException". + */ + void cancel() const { + static_cast(this)->impl.cancel(); + } }; -template T> struct Promise> { +/** + * Mixin for wrapping Promise method calls for a single event. + * @tparam E The event type. + * @tparam P The promise type. + */ +template struct EventPromiseMixin { + /** + * Returns result of computation. If computation has no @ref CommonPromiseMixin::hasResult() "result", then + * this method returns `std::shared_ptr(nullptr)`. + * + * @return The result of computation. + * @see CommonPromiseMixin::hasResult() + */ + std::shared_ptr getResult() const { + return convertEvent(static_cast(this)->impl.getResult()); + } + /** + * Wait for computation to complete and return its result or throw an exception in case of exceptional completion. + * @return result of computation. + * @throws CancellationException if computation was cancelled. + * @throws PromiseException if computation has completed exceptionally. + */ + std::shared_ptr await() const { + static_cast(this)->impl.await(); + + return getResult(); + } + + /** + * Wait for computation to complete or timeout and return its result or throw an exception in case of exceptional + * completion or timeout. + * + * @param timeoutInMilliseconds The timeout. + * @return The result of computation. + * @throws CancellationException if computation was cancelled or timed out. + * @throws PromiseException if computation has completed exceptionally. + */ + std::shared_ptr await(std::int32_t timeoutInMilliseconds) const & { + static_cast(this)->impl.await(timeoutInMilliseconds); + + return getResult(); + } + + /** + * Wait for computation to complete or timeout and return its result or throw an exception in case of exceptional + * completion or timeout. + * + * @param timeoutInMilliseconds The timeout. + * @return The result of computation. + * @throws CancellationException if computation was cancelled or timed out. + * @throws PromiseException if computation has completed exceptionally. + */ + std::shared_ptr await(const std::chrono::milliseconds &timeoutInMilliseconds) const & { + auto timeout = timeoutInMilliseconds.count(); + + if (timeout > std::numeric_limits::max()) { + timeout = std::numeric_limits::max(); + } + + static_cast(this)->impl.await(timeout); + + return getResult(); + } }; -template T> struct Promise>> { +template struct EventsPromiseMixin { + /** + * Returns result of computation. If computation has no @ref CommonPromiseMixin::hasResult() "result", then + * this method returns an empty ollection. + * + * @return The result of computation. + * @see CommonPromiseMixin::hasResult() + */ + std::vector> getResult() const { + return convertEvents(static_cast(this)->impl.getResult()); + } + + /** + * Wait for computation to complete and return its result or throw an exception in case of exceptional completion. + * @return result of computation. + * @throws CancellationException if computation was cancelled. + * @throws PromiseException if computation has completed exceptionally. + */ + std::vector> await() const { + static_cast(this)->impl.await(); + + return getResult(); + } + + /** + * Wait for computation to complete or timeout and return its result or throw an exception in case of exceptional + * completion or timeout. + * + * @param timeoutInMilliseconds The timeout. + * @return The result of computation. + * @throws CancellationException if computation was cancelled or timed out. + * @throws PromiseException if computation has completed exceptionally. + */ + std::vector> await(std::int32_t timeoutInMilliseconds) const & { + static_cast(this)->impl.await(timeoutInMilliseconds); + + return getResult(); + } + /** + * Wait for computation to complete or timeout and return its result or throw an exception in case of exceptional + * completion or timeout. + * + * @param timeoutInMilliseconds The timeout. + * @return The result of computation. + * @throws CancellationException if computation was cancelled or timed out. + * @throws PromiseException if computation has completed exceptionally. + */ + std::vector> await(const std::chrono::milliseconds &timeoutInMilliseconds) const & { + auto timeout = timeoutInMilliseconds.count(); + + if (timeout > std::numeric_limits::max()) { + timeout = std::numeric_limits::max(); + } + + static_cast(this)->impl.await(timeout); + + return getResult(); + } +}; + +/** + * Result of a computation that will be completed normally or exceptionally in the future. + * @tparam T The result type. + */ +template struct Promise {}; + +/** + * Result of an event receiving that will be completed normally or exceptionally in the future. + * @tparam E The event type. + */ +template +struct Promise> : CommonPromiseMixin>>, + EventPromiseMixin>> { + friend struct CommonPromiseMixin; + friend struct EventPromiseMixin; + + EventsPromiseImpl impl; + + explicit Promise(void *handle) : impl(handle) { + } }; +/** + * Result of an collection of events receiving that will be completed normally or exceptionally in the future. + * @tparam E The event type. + */ +template +struct Promise>> : CommonPromiseMixin>>>, + EventsPromiseMixin>>> { + friend struct CommonPromiseMixin; + friend struct EventsPromiseMixin; -// -// Promise> x{}; -// auto _ = x.z(); -// -// template struct PromiseSFINAE { -// int x() { -// return {}; -// } -// }; -// -// template -// struct PromiseSFINAE::value>::type> { -// int z() { -// return 0; -// } -// }; -// -// PromiseSFINAE> xx{}; -// auto __ = xx.z(); + EventsPromiseImpl impl; + + explicit Promise(void *handle) : impl(handle) { + } +}; DXFCPP_END_NAMESPACE diff --git a/samples/cpp/FetchDailyCandles/src/main.cpp b/samples/cpp/FetchDailyCandles/src/main.cpp index 9ef1f6726..a2d653922 100644 --- a/samples/cpp/FetchDailyCandles/src/main.cpp +++ b/samples/cpp/FetchDailyCandles/src/main.cpp @@ -8,13 +8,13 @@ void fetchAndPrint(const dxfcpp::CandleSymbol &candleSymbol, std::int64_t toTime, std::int64_t fromTime) { // Use default DXFeed instance for that data feed address is defined by dxfeed.properties file - // auto result = dxfcpp::DXFeed::getInstance() - // ->getTimeSeriesPromise(candleSymbol, fromTime, toTime) - // ->await(std::chrono::seconds(5)); - // - // for (auto candle : result) { - // std::cout << candle->toString(); - // } + auto result = dxfcpp::DXFeed::getInstance() + ->getTimeSeriesPromise(candleSymbol, fromTime, toTime) + .await(std::chrono::seconds(5)); + + for (const auto &candle : result) { + std::cout << candle->toString() << "\n"; + } } // Fetches last 20 days of candles for a specified symbol, prints them, and exits. diff --git a/src/api/DXFeed.cpp b/src/api/DXFeed.cpp index 170f95c35..1925bd97e 100644 --- a/src/api/DXFeed.cpp +++ b/src/api/DXFeed.cpp @@ -121,14 +121,9 @@ std::shared_ptr DXFeed::create(void *feedHandle) { return feed; } -Promise>> DXFeed::getTimeSeriesPromise(const EventTypeEnum &eventType, - const SymbolWrapper &symbol, - std::int64_t fromTime, - std::int64_t toTime) { - - // TODO: impelement - - return {}; +void *DXFeed::getTimeSeriesPromiseImpl(const EventTypeEnum &eventType, const SymbolWrapper &symbol, + std::int64_t fromTime, std::int64_t toTime) const { + return isolated::api::IsolatedDXFeed::getTimeSeriesPromise(handle_, eventType, symbol, fromTime, toTime); } std::string DXFeed::toString() const noexcept { diff --git a/src/exceptions/JavaException.cpp b/src/exceptions/JavaException.cpp index 7ee697f33..b3ee9a5a8 100644 --- a/src/exceptions/JavaException.cpp +++ b/src/exceptions/JavaException.cpp @@ -98,7 +98,7 @@ JavaException::JavaException(const std::string &message, const std::string &clas JavaException JavaException::create(void *exceptionHandle) { if (exceptionHandle == nullptr) { - return {"", "", ""}; + return {"null", "", ""}; } auto *exception = dxfcpp::bit_cast(exceptionHandle); diff --git a/src/internal/JavaObjectHandle.cpp b/src/internal/JavaObjectHandle.cpp index 87e84284e..d45ac45a6 100644 --- a/src/internal/JavaObjectHandle.cpp +++ b/src/internal/JavaObjectHandle.cpp @@ -83,4 +83,8 @@ template struct JavaObjectHandle; template struct JavaObjectHandle; template struct JavaObjectHandle; +template struct JavaObjectHandle; +template struct JavaObjectHandle; +template struct JavaObjectHandle; + DXFCPP_END_NAMESPACE \ No newline at end of file diff --git a/src/promise/Promise.cpp b/src/promise/Promise.cpp new file mode 100644 index 000000000..f36d0ef72 --- /dev/null +++ b/src/promise/Promise.cpp @@ -0,0 +1,80 @@ +// Copyright (c) 2024 Devexperts LLC. +// SPDX-License-Identifier: MPL-2.0 + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include + +DXFCPP_BEGIN_NAMESPACE + +PromiseImpl::PromiseImpl(void *handle) : handle(handle) { +} + +bool PromiseImpl::isDone() const { + return isolated::promise::IsolatedPromise::isDone(handle); +} + +bool PromiseImpl::hasResult() const { + return isolated::promise::IsolatedPromise::hasResult(handle); +} + +bool PromiseImpl::hasException() const { + return isolated::promise::IsolatedPromise::hasException(handle); +} + +bool PromiseImpl::isCancelled() const { + return isolated::promise::IsolatedPromise::isCancelled(handle); +} + +JavaException PromiseImpl::getException() const { + return isolated::promise::IsolatedPromise::getException(handle); +} + +void PromiseImpl::await() const { + isolated::promise::IsolatedPromise::await(handle); +} + +void PromiseImpl::await(std::int32_t timeoutInMilliseconds) const { + isolated::promise::IsolatedPromise::await(handle, timeoutInMilliseconds); +} + +bool PromiseImpl::awaitWithoutException(std::int32_t timeoutInMilliseconds) const { + return isolated::promise::IsolatedPromise::awaitWithoutException(handle, timeoutInMilliseconds); +} + +void PromiseImpl::cancel() const { + isolated::promise::IsolatedPromise::cancel(handle); +} + +EventPromiseImpl::EventPromiseImpl(void *handle) : PromiseImpl(handle), handle(handle) { +} + +EventPromiseImpl::~EventPromiseImpl() { + JavaObjectHandle::deleter(handle); +} + +std::shared_ptr EventPromiseImpl::getResult() const { + return isolated::promise::IsolatedPromise::getResult(handle); +} + +EventsPromiseImpl::EventsPromiseImpl(void *handle) : PromiseImpl(handle), handle(handle) { +} + +EventsPromiseImpl::~EventsPromiseImpl() { + JavaObjectHandle::deleter(handle); +} + +std::vector> EventsPromiseImpl::getResult() const { + return isolated::promise::IsolatedPromise::getResults(handle); +} + +DXFCPP_END_NAMESPACE \ No newline at end of file