Skip to content

Commit

Permalink
[MDAPI-83][C++] Implement IndexedTxModel
Browse files Browse the repository at this point in the history
TxModelListener
  • Loading branch information
AnatolyKalin committed Nov 18, 2024
1 parent 20f3323 commit bb0b3d7
Show file tree
Hide file tree
Showing 12 changed files with 130 additions and 32 deletions.
22 changes: 22 additions & 0 deletions include/dxfeed_graal_cpp_api/entity/SharedEntity.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@

DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251)

#include "../internal/Common.hpp"

#include <memory>
#include <vector>
#include <string>

#include "Entity.hpp"

Expand Down Expand Up @@ -89,6 +93,24 @@ struct RequireMakeShared : SharedEntity {
}
};

template <typename EBase, Derived<EBase> EDerived>
static std::shared_ptr<EDerived> convertEvent(const std::shared_ptr<EBase> &source) {
return source->template sharedAs<EDerived>();
}

template <typename EBase, Derived<EBase> EDerived>
static std::vector<std::shared_ptr<EDerived>> convertEvents(const std::vector<std::shared_ptr<EBase>> &source) {
std::vector<std::shared_ptr<EDerived>> result{};

result.reserve(source.size());

for (const auto &e : source) {
result.emplace_back(e->template sharedAs<EDerived>());
}

return result;
}

DXFCPP_END_NAMESPACE

DXFCXX_DISABLE_MSC_WARNINGS_POP()
3 changes: 3 additions & 0 deletions include/dxfeed_graal_cpp_api/internal/Common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ concept EnumConcept = std::is_enum_v<T>;
template <class From, class To>
concept ConvertibleTo = std::is_convertible_v<From, To> && requires { static_cast<To>(std::declval<From>()); };

template <class T, class U>
concept Derived = std::is_base_of_v<U, T>;

namespace detail {
template <typename T>
struct RemoveAllPointers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ JavaObjectHandle<IndexedTxModel::Builder> withSymbol(const JavaObjectHandle<Inde
// dxfg_indexed_tx_model_builder_t* dxfg_IndexedTxModel_Builder_withListener(graal_isolatethread_t* thread,
// dxfg_indexed_tx_model_builder_t* source, dxfg_tx_model_listener_t* listener);
JavaObjectHandle<IndexedTxModel::Builder> withListener(const JavaObjectHandle<IndexedTxModel::Builder> &builder,
const JavaObjectHandle<TxModelListener> &listener);
const JavaObjectHandle<TxModelListenerTag> &listener);

// dxfg_indexed_tx_model_builder_t* dxfg_IndexedTxModel_Builder_withExecutor(graal_isolatethread_t* thread,
// dxfg_indexed_tx_model_builder_t* source, dxfg_executor_t* executor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ JavaObjectHandle<TimeSeriesTxModel::Builder> withSymbol(const JavaObjectHandle<T
// dxfg_time_series_tx_model_builder_t* dxfg_TimeSeriesTxModel_Builder_withListener(graal_isolatethread_t* thread,
// dxfg_time_series_tx_model_builder_t* source, dxfg_tx_model_listener_t* listener);
JavaObjectHandle<TimeSeriesTxModel::Builder> withListener(const JavaObjectHandle<TimeSeriesTxModel::Builder> &builder,
const JavaObjectHandle<TxModelListener> &listener);
const JavaObjectHandle<TxModelListenerTag> &listener);

// dxfg_time_series_tx_model_builder_t* dxfg_TimeSeriesTxModel_Builder_withExecutor(graal_isolatethread_t* thread,
// dxfg_time_series_tx_model_builder_t* source, dxfg_executor_t* executor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace isolated::model::IsolatedTxModelListener {
// typedef void (*dxfg_TxModelListener_function_eventsReceived)(graal_isolatethread_t* thread, dxfg_indexed_event_source_t* source, dxfg_event_type_list* events, int32_t /* boolean */ isSnapshot, void* user_data);

// dxfg_tx_model_listener_t* dxfg_TxModelListener_new(graal_isolatethread_t* thread, dxfg_TxModelListener_function_eventsReceived function_eventsReceived, void* user_data);
JavaObjectHandle<TxModelListener> create(void* functionEventsReceived, void* userData);
JavaObjectHandle<TxModelListenerTag> create(void* functionEventsReceived, void* userData);

}

Expand Down
36 changes: 33 additions & 3 deletions include/dxfeed_graal_cpp_api/model/TxModelListener.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,49 @@
#pragma once

#include "../internal/Conf.hpp"
#include "../internal/Handler.hpp"

DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251)

#include "../symbols/SymbolWrapper.hpp"
//#include "../entity/SharedEntity.hpp"
#include "../entity/SharedEntity.hpp"
#include "../event/IndexedEvent.hpp"
#include "../event/IndexedEventSource.hpp"
#include "../internal/JavaObjectHandle.hpp"

#include <functional>
#include <memory>
#include <mutex>
#include <thread>
#include <unordered_set>
#include <vector>

DXFCPP_BEGIN_NAMESPACE

struct DXFCPP_EXPORT TxModelListener {
class IndexedEventSource;

struct TxModelListenerTag {};

struct DXFCPP_EXPORT TxModelListener : RequireMakeShared<TxModelListener> {
explicit TxModelListener(LockExternalConstructionTag);
~TxModelListener() noexcept override;

static std::shared_ptr<TxModelListener>
create(std::function<void(const IndexedEventSource & /* source */,
const std::vector<std::shared_ptr<EventType>> & /* events */, bool /* isSnapshot */)>
onEventsReceived);

const JavaObjectHandle<TxModelListenerTag> &getHandle() const;

private:
mutable std::recursive_mutex mutex_{};
JavaObjectHandle<TxModelListenerTag> handle_;
SimpleHandler<void(const IndexedEventSource & /* source */,
const std::vector<std::shared_ptr<EventType>> & /* events */, bool /* isSnapshot */)>
onEventsReceived_{};

struct Impl;

std::unique_ptr<Impl> impl_;
};

DXFCPP_END_NAMESPACE
21 changes: 0 additions & 21 deletions include/dxfeed_graal_cpp_api/promise/Promise.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,6 @@ struct EventType;
struct JavaException;
struct Promises;

template <class T, class U>
concept Derived = std::is_base_of_v<U, T>;

template <typename EBase, Derived<EBase> EDerived>
std::shared_ptr<EDerived> convertEvent(const std::shared_ptr<EBase> &source) {
return source->template sharedAs<EDerived>();
}

template <typename EBase, Derived<EBase> EDerived>
std::vector<std::shared_ptr<EDerived>> convertEvents(const std::vector<std::shared_ptr<EBase>> &source) {
std::vector<std::shared_ptr<EDerived>> result{};

result.reserve(source.size());

for (const auto &e : source) {
result.emplace_back(e->template sharedAs<EDerived>());
}

return result;
}

struct PromiseImpl {
protected:
void *handle = nullptr;
Expand Down
2 changes: 1 addition & 1 deletion src/internal/JavaObjectHandle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ template struct JavaObjectHandle<TimePeriod>;

template struct JavaObjectHandle<AuthToken>;

template struct JavaObjectHandle<TxModelListener>;
template struct JavaObjectHandle<TxModelListenerTag>;
template struct JavaObjectHandle<IndexedTxModel>;
template struct JavaObjectHandle<IndexedTxModel::Builder>;
template struct JavaObjectHandle<TimeSeriesTxModel>;
Expand Down
2 changes: 1 addition & 1 deletion src/isolated/model/IsolatedIndexedTxModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ JavaObjectHandle<IndexedTxModel::Builder> withSymbol(const JavaObjectHandle<Inde
// dxfg_indexed_tx_model_builder_t* dxfg_IndexedTxModel_Builder_withListener(graal_isolatethread_t* thread,
// dxfg_indexed_tx_model_builder_t* source, dxfg_tx_model_listener_t* listener);
JavaObjectHandle<IndexedTxModel::Builder> withListener(const JavaObjectHandle<IndexedTxModel::Builder> &builder,
const JavaObjectHandle<TxModelListener> &listener) {
const JavaObjectHandle<TxModelListenerTag> &listener) {
if (!builder) {
throw InvalidArgumentException("Unable to execute function `dxfg_IndexedTxModel_Builder_withListener`. The "
"`builder` handle is invalid");
Expand Down
2 changes: 1 addition & 1 deletion src/isolated/model/IsolatedTimeSeriesTxModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ JavaObjectHandle<TimeSeriesTxModel::Builder> withSymbol(const JavaObjectHandle<T
// dxfg_time_series_tx_model_builder_t* dxfg_TimeSeriesTxModel_Builder_withListener(graal_isolatethread_t* thread,
// dxfg_time_series_tx_model_builder_t* source, dxfg_tx_model_listener_t* listener);
JavaObjectHandle<TimeSeriesTxModel::Builder> withListener(const JavaObjectHandle<TimeSeriesTxModel::Builder> &builder,
const JavaObjectHandle<TxModelListener> &listener) {
const JavaObjectHandle<TxModelListenerTag> &listener) {
if (!builder) {
throw InvalidArgumentException("Unable to execute function `dxfg_TimeSeriesTxModel_Builder_withListener`. The "
"`builder` handle is invalid");
Expand Down
4 changes: 2 additions & 2 deletions src/isolated/model/IsolatedTxModelListener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ namespace isolated::model::IsolatedTxModelListener {

// dxfg_tx_model_listener_t* dxfg_TxModelListener_new(graal_isolatethread_t* thread,
// dxfg_TxModelListener_function_eventsReceived function_eventsReceived, void* user_data);
JavaObjectHandle<TxModelListener> create(void *functionEventsReceived, void *userData) {
JavaObjectHandle<TxModelListenerTag> create(void *functionEventsReceived, void *userData) {
if (!functionEventsReceived) {
throw InvalidArgumentException(
"Unable to execute function `dxfg_TxModelListener_new`. The `functionEventsReceived` is nullptr");
}

return JavaObjectHandle<TxModelListener>{runGraalFunctionAndThrowIfNullptr(
return JavaObjectHandle<TxModelListenerTag>{runGraalFunctionAndThrowIfNullptr(
dxfg_TxModelListener_new,
dxfcpp::bit_cast<dxfg_TxModelListener_function_eventsReceived>(functionEventsReceived), userData)};
}
Expand Down
64 changes: 64 additions & 0 deletions src/model/TxModelListener.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) 2024 Devexperts LLC.
// SPDX-License-Identifier: MPL-2.0

#include "dxfeed_graal_cpp_api/event/EventMapper.hpp"

#include <dxfeed_graal_cpp_api/internal/Id.hpp>
#include <dxfeed_graal_cpp_api/internal/context/ApiContext.hpp>
#include <dxfeed_graal_cpp_api/isolated/model/IsolatedTxModelListener.hpp>
#include <dxfeed_graal_cpp_api/model/TxModelListener.hpp>

struct graal_isolatethread_t;
struct dxfg_indexed_event_source_t;
struct dxfg_event_type_list;

DXFCPP_BEGIN_NAMESPACE

struct TxModelListener::Impl {
// typedef void (*dxfg_TxModelListener_function_eventsReceived)(graal_isolatethread_t* thread,
// dxfg_indexed_event_source_t* source, dxfg_event_type_list* events, int32_t isSnapshot, void* user_data);
static void onEventsReceived(graal_isolatethread_t * /* thread */, dxfg_indexed_event_source_t *source,
dxfg_event_type_list *events, int32_t isSnapshot, void *userData) {
if (!source || !events) {
return;
}

auto id = Id<TxModelListener>::from(userData);
auto listener = ApiContext::getInstance()->getManager<EntityManager<TxModelListener>>()->getEntity(id);

if (!listener) {
return;
}

listener->onEventsReceived_(IndexedEventSource::fromGraal(source), EventMapper::fromGraalList(events),
isSnapshot == 1);
}
};

TxModelListener::TxModelListener(LockExternalConstructionTag) : handle_{}, impl_{std::make_unique<Impl>()} {
}

TxModelListener::~TxModelListener() noexcept {
}

std::shared_ptr<TxModelListener> TxModelListener::create(
std::function<void(const IndexedEventSource & /* source */,
const std::vector<std::shared_ptr<EventType>> & /* events */, bool /* isSnapshot */)>
onEventsReceived) {
auto listener = createShared();
auto id = ApiContext::getInstance()->getManager<EntityManager<TxModelListener>>()->registerEntity(listener);

listener->handle_ = isolated::model::IsolatedTxModelListener::create(
dxfcpp::bit_cast<void *>(&Impl::onEventsReceived), dxfcpp::bit_cast<void *>(id.getValue()));
listener->onEventsReceived_ += std::move(onEventsReceived);

return listener;
}

const JavaObjectHandle<TxModelListenerTag> &TxModelListener::getHandle() const {
std::lock_guard guard{mutex_};

return handle_;
}

DXFCPP_END_NAMESPACE

0 comments on commit bb0b3d7

Please sign in to comment.