Skip to content

Commit

Permalink
[DXFC-407] Add a TimeSeriesSubscriptionSymbol and IndexedEventSubscri…
Browse files Browse the repository at this point in the history
…ptionSymbol support
  • Loading branch information
AnatolyKalin committed Jun 19, 2023
1 parent f1bb865 commit 879ce97
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,55 @@ namespace dxfcpp {
class IndexedEventSource;
struct SymbolWrapper;

/**
* Represents subscription to a specific source of indexed events.
* This is symbol is observed by ObservableSubscriptionChangeListener
* methods @ref ObservableSubscriptionChangeListener::symbolsAdded() "symbolsAdded"
* and @ref ObservableSubscriptionChangeListener::symbolsRemoved() "symbolsRemoved"
* when subscription to IndexedEvent is defined.
*
* <p>Instances of this class can be used with DXFeedSubscription to specify subscription
* to a particular source of indexed events. By default, when subscribing to indexed events by
* their event symbol object, the subscription is performed to all supported sources.
*
* <h3>Equality and hash codes</h3>
*
* Indexed event subscription symbols are compared based on their @ref ::getEventSymbol() "eventSymbol" and
* @ref ::getSource() "source".
*/
class DXFCPP_EXPORT IndexedEventSubscriptionSymbol final {
std::unique_ptr<SymbolWrapper> eventSymbol_;
IndexedEventSource source_;
struct Impl;
std::unique_ptr<Impl> impl_;

public:
/**
* Creates indexed event subscription symbol with a specified event symbol and source.
*
* @param eventSymbol the wrapped event symbol (CandleSymbol, WildcardSymbol, etc).
* @param source the source.
*/
IndexedEventSubscriptionSymbol(const SymbolWrapper &eventSymbol, const IndexedEventSource &source) noexcept;

IndexedEventSubscriptionSymbol(const IndexedEventSubscriptionSymbol &indexedEventSubscriptionSymbol) noexcept;
IndexedEventSubscriptionSymbol(IndexedEventSubscriptionSymbol &&indexedEventSubscriptionSymbol) noexcept;
IndexedEventSubscriptionSymbol &
operator=(const IndexedEventSubscriptionSymbol &indexedEventSubscriptionSymbol) noexcept;
IndexedEventSubscriptionSymbol &operator=(IndexedEventSubscriptionSymbol &&indexedEventSubscriptionSymbol) noexcept;
IndexedEventSubscriptionSymbol() noexcept;
virtual ~IndexedEventSubscriptionSymbol() noexcept;

IndexedEventSubscriptionSymbol() noexcept = default;
virtual ~IndexedEventSubscriptionSymbol() noexcept = default;

/**
* Returns the wrapped event symbol (CandleSymbol, WildcardSymbol, etc).
*
* @return the wrapped event symbol.
*/
const std::unique_ptr<SymbolWrapper> &getEventSymbol() const;

/**
* Returns indexed event source.
*
* @return indexed event source.
*/
const IndexedEventSource &getSource() const;

void *toGraal() const noexcept;
Expand All @@ -43,6 +74,11 @@ class DXFCPP_EXPORT IndexedEventSubscriptionSymbol final {

static IndexedEventSubscriptionSymbol fromGraal(void* graal) noexcept;

/**
* Returns string representation of this indexed event subscription symbol.
*
* @return string representation of this indexed event subscription symbol.
*/
std::string toString() const noexcept;

bool operator==(const IndexedEventSubscriptionSymbol &indexedEventSubscriptionSymbol) const noexcept;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,71 @@ namespace dxfcpp {

struct SymbolWrapper;

/**
* Represents subscription to time-series of events.
* This is symbol is observed by ObservableSubscriptionChangeListener
* methods @ref ObservableSubscriptionChangeListener::symbolsAdded() "symbolsAdded"
* and @ref ObservableSubscriptionChangeListener::symbolsRemoved() "symbolsRemoved"
* when time-series subscription is created via DXFeedTimeSeriesSubscription class.
*
* <p>Instances of this class can be used with DXFeedSubscription to specify subscription
* for time series events from a specific time. By default, subscribing to time-series events by
* their event symbol object, the subscription is performed to a stream of new events as they happen only.
*
* <p>TimeSeriesEvent represents a special subtype of IndexedEvent.
* The source identifier of a time-series event is always zero and thus
*
* <h3>Equality and hash codes</h3>
*
* This is a FilteredSubscriptionSymbol.
* Time-series subscription symbols are compared based on their @ref ::getEventSymbol() "eventSymbol" only.
* It means, that a set of time-series subscription symbols can contain at most one time-series subscription
* for each event symbol.
*/
class DXFCPP_EXPORT TimeSeriesSubscriptionSymbol final {
std::unique_ptr<SymbolWrapper> eventSymbol_;
std::int64_t fromTime_;

public:
TimeSeriesSubscriptionSymbol(const SymbolWrapper &eventSymbol, std::int64_t fromTime);
/**
* Creates time-series subscription symbol with a specified event symbol and subscription time.
* @param eventSymbol the wrapped event symbol (CandleSymbol, WildcardSymbol, etc).
* @param fromTime the subscription time.
*/
TimeSeriesSubscriptionSymbol(const SymbolWrapper &eventSymbol, std::int64_t fromTime) noexcept;

TimeSeriesSubscriptionSymbol(const TimeSeriesSubscriptionSymbol &timeSeriesSubscriptionSymbol) noexcept;
TimeSeriesSubscriptionSymbol(TimeSeriesSubscriptionSymbol &&timeSeriesSubscriptionSymbol) noexcept;
TimeSeriesSubscriptionSymbol &operator=(const TimeSeriesSubscriptionSymbol &timeSeriesSubscriptionSymbol) noexcept;
TimeSeriesSubscriptionSymbol &operator=(TimeSeriesSubscriptionSymbol &&timeSeriesSubscriptionSymbol) noexcept;
TimeSeriesSubscriptionSymbol() noexcept = default;
virtual ~TimeSeriesSubscriptionSymbol() noexcept = default;

/**
* Returns the wrapped event symbol (CandleSymbol, WildcardSymbol, etc).
*
* @return the wrapped event symbol.
*/
const std::unique_ptr<SymbolWrapper> &getEventSymbol() const;

/**
* Returns the subscription time.
*
* @return the subscription time.
*/
std::int64_t getFromTime() const;

void *toGraal() const noexcept;

static void freeGraal(void* graal) noexcept;
static void freeGraal(void *graal) noexcept;

static TimeSeriesSubscriptionSymbol fromGraal(void* graal) noexcept;
static TimeSeriesSubscriptionSymbol fromGraal(void *graal) noexcept;

/**
* Returns string representation of this time-series subscription symbol.
*
* @return string representation of this time-series subscription symbol.
*/
std::string toString() const noexcept;

bool operator==(const TimeSeriesSubscriptionSymbol &timeSeriesSubscriptionSymbol) const noexcept;
Expand Down
34 changes: 32 additions & 2 deletions include/dxfeed_graal_cpp_api/api/osub/WildcardSymbol.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,32 @@

namespace dxfcpp {

/**
* Represents [wildcard] subscription to all events of the specific event type.
* The @ref WildcardSymbol::ALL constant can be added to any DXFeedSubscription instance with @ref
* DXFeedSubscription::addSymbols() "addSymbols" method to the effect of subscribing to all possible event symbols. The
* corresponding subscription will start receiving all published events of the corresponding types.
*/
struct DXFCPP_EXPORT WildcardSymbol final {
/**
* Symbol prefix that is reserved for wildcard subscriptions.
* Any subscription starting with "*" is ignored with the exception of WildcardSymbol subscription.
*/
static const std::string RESERVED_PREFIX;

/**
* Represents [wildcard] subscription to all events of the specific event type.
*
* <p><b>NOTE:</b> Wildcard subscription can create extremely high network and CPU load for certain kinds of
* high-frequency events like quotes. It requires a special arrangement on the side of upstream data provider and
* is disabled by default in upstream feed configuration. Make that sure you have adequate resources and understand
* the impact before using it. It can be used for low-frequency events only (like Forex quotes), because each instance
* of DXFeedSubscription processes events in a single thread and there is no provision to load-balance wildcard
* subscription amongst multiple threads.
* Contact your data provider for the corresponding configuration arrangement if needed.
*
* @see WildcardSymbol
*/
static const WildcardSymbol ALL;

private:
Expand All @@ -31,10 +56,15 @@ struct DXFCPP_EXPORT WildcardSymbol final {

void *toGraal() const noexcept;

static void freeGraal(void* graal) noexcept;
static void freeGraal(void *graal) noexcept;

static const WildcardSymbol& fromGraal(void* graal) noexcept;
static const WildcardSymbol &fromGraal(void *graal) noexcept;

/**
* Returns string representation of this wildcard subscription symbol.
*
* @return string representation of this wildcard subscription symbol.
*/
std::string toString() const noexcept {
if constexpr (Debugger::isDebug) {
return "WildcardSymbol{" + symbol_ + "}";
Expand Down
8 changes: 7 additions & 1 deletion include/dxfeed_graal_cpp_api/symbols/StringSymbol.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,13 @@ struct DXFCPP_EXPORT StringSymbol final {
*
* @return a string representation
*/
std::string toString() const noexcept { return "StringSymbol{" + data_ + "}"; }
std::string toString() const noexcept {
if constexpr (Debugger::isDebug) {
return "StringSymbol{" + data_ + "}";
} else {
return data_;
}
}

const std::string &getData() const;

Expand Down
5 changes: 5 additions & 0 deletions include/dxfeed_graal_cpp_api/symbols/SymbolWrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ struct DXFCPP_EXPORT SymbolWrapper final {
static SymbolWrapper fromGraal(void *graal) noexcept;

void *toGraal() const noexcept {
if constexpr (Debugger::isDebug) {
Debugger::debug(
"SymbolWrapper::toGraal()");
}

return std::visit([](const auto &symbol) { return symbol.toGraal(); }, data_);
}

Expand Down
59 changes: 8 additions & 51 deletions src/api/osub/IndexedEventSubscriptionSymbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,45 +9,6 @@

namespace dxfcpp {

// TODO: implement recursive construction\destruction
struct IndexedEventSubscriptionSymbol::Impl final {
dxfg_indexed_event_subscription_symbol_t graalSymbol;

Impl() noexcept : graalSymbol{{INDEXED_EVENT_SUBSCRIPTION}, nullptr} {}

Impl(const Impl &) noexcept {
graalSymbol.supper = {INDEXED_EVENT_SUBSCRIPTION};
graalSymbol.symbol = nullptr;
}

Impl(Impl &&) noexcept {
graalSymbol.supper = {INDEXED_EVENT_SUBSCRIPTION};
graalSymbol.symbol = nullptr;
}

Impl &operator=(const Impl &impl) noexcept {
if (this == &impl) {
return *this;
}

graalSymbol.supper = {INDEXED_EVENT_SUBSCRIPTION};
graalSymbol.symbol = nullptr;

return *this;
}

Impl &operator=(Impl &&impl) noexcept {
if (this == &impl) {
return *this;
}

graalSymbol.supper = {INDEXED_EVENT_SUBSCRIPTION};
graalSymbol.symbol = nullptr;

return *this;
}
};

IndexedEventSubscriptionSymbol::IndexedEventSubscriptionSymbol(const SymbolWrapper &eventSymbol,
const IndexedEventSource &source) noexcept
: eventSymbol_(std::make_unique<SymbolWrapper>(eventSymbol)), source_(source) {}
Expand All @@ -58,8 +19,7 @@ const IndexedEventSource &IndexedEventSubscriptionSymbol::getSource() const { re

void *IndexedEventSubscriptionSymbol::toGraal() const noexcept {
if constexpr (Debugger::isDebug) {
Debugger::debug(
"IndexedEventSubscriptionSymbol::toGraal()");
Debugger::debug("IndexedEventSubscriptionSymbol::toGraal()");
}

auto *graalSymbol = new (std::nothrow)
Expand All @@ -72,8 +32,7 @@ void *IndexedEventSubscriptionSymbol::toGraal() const noexcept {

void IndexedEventSubscriptionSymbol::freeGraal(void *graal) noexcept {
if constexpr (Debugger::isDebug) {
Debugger::debug(
"IndexedEventSubscriptionSymbol::freeGraal(graal = " + toStringAny(graal) + ")");
Debugger::debug("IndexedEventSubscriptionSymbol::freeGraal(graal = " + toStringAny(graal) + ")");
}

if (graal == nullptr) {
Expand All @@ -90,8 +49,7 @@ void IndexedEventSubscriptionSymbol::freeGraal(void *graal) noexcept {

IndexedEventSubscriptionSymbol IndexedEventSubscriptionSymbol::fromGraal(void *graal) noexcept {
if constexpr (Debugger::isDebug) {
Debugger::debug(
"IndexedEventSubscriptionSymbol::fromGraal(graal = " + toStringAny(graal) + ")");
Debugger::debug("IndexedEventSubscriptionSymbol::fromGraal(graal = " + toStringAny(graal) + ")");
}

if (graal == nullptr) {
Expand All @@ -104,7 +62,11 @@ IndexedEventSubscriptionSymbol IndexedEventSubscriptionSymbol::fromGraal(void *g
}

std::string IndexedEventSubscriptionSymbol::toString() const noexcept {
return eventSymbol_->toString() + "{source=" + source_.toString() + "}";
if constexpr (Debugger::isDebug) {
return "IndexedEventSubscriptionSymbol{" + eventSymbol_->toString() + ", source = " + source_.toString() + "}";
} else {
return eventSymbol_->toString() + "{source=" + source_.toString() + "}";
}
}

bool IndexedEventSubscriptionSymbol::operator==(
Expand Down Expand Up @@ -147,9 +109,4 @@ IndexedEventSubscriptionSymbol::operator=(IndexedEventSubscriptionSymbol &&index
return *this;
}

IndexedEventSubscriptionSymbol::IndexedEventSubscriptionSymbol() noexcept
: impl_{std::make_unique<IndexedEventSubscriptionSymbol::Impl>()} {}

IndexedEventSubscriptionSymbol::~IndexedEventSubscriptionSymbol() noexcept = default;

} // namespace dxfcpp
18 changes: 10 additions & 8 deletions src/api/osub/TimeSeriesSubscriptionSymbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace dxfcpp {

TimeSeriesSubscriptionSymbol::TimeSeriesSubscriptionSymbol(const SymbolWrapper &eventSymbol, int64_t fromTime)
TimeSeriesSubscriptionSymbol::TimeSeriesSubscriptionSymbol(const SymbolWrapper &eventSymbol, int64_t fromTime) noexcept
: eventSymbol_(std::make_unique<SymbolWrapper>(eventSymbol)), fromTime_(fromTime) {}

const std::unique_ptr<SymbolWrapper> &TimeSeriesSubscriptionSymbol::getEventSymbol() const { return eventSymbol_; }
Expand All @@ -17,8 +17,7 @@ int64_t TimeSeriesSubscriptionSymbol::getFromTime() const { return fromTime_; }

void *TimeSeriesSubscriptionSymbol::toGraal() const noexcept {
if constexpr (Debugger::isDebug) {
Debugger::debug(
"TimeSeriesSubscriptionSymbol::toGraal()");
Debugger::debug("TimeSeriesSubscriptionSymbol::toGraal()");
}

auto *graalSymbol = new (std::nothrow) dxfg_time_series_subscription_symbol_t{
Expand All @@ -29,8 +28,7 @@ void *TimeSeriesSubscriptionSymbol::toGraal() const noexcept {

void TimeSeriesSubscriptionSymbol::freeGraal(void *graal) noexcept {
if constexpr (Debugger::isDebug) {
Debugger::debug(
"TimeSeriesSubscriptionSymbol::freeGraal(graal = " + toStringAny(graal) + ")");
Debugger::debug("TimeSeriesSubscriptionSymbol::freeGraal(graal = " + toStringAny(graal) + ")");
}

if (graal == nullptr) {
Expand All @@ -46,8 +44,7 @@ void TimeSeriesSubscriptionSymbol::freeGraal(void *graal) noexcept {

TimeSeriesSubscriptionSymbol TimeSeriesSubscriptionSymbol::fromGraal(void *graal) noexcept {
if constexpr (Debugger::isDebug) {
Debugger::debug(
"TimeSeriesSubscriptionSymbol::fromGraal(graal = " + toStringAny(graal) + ")");
Debugger::debug("TimeSeriesSubscriptionSymbol::fromGraal(graal = " + toStringAny(graal) + ")");
}

if (graal == nullptr) {
Expand All @@ -60,7 +57,12 @@ TimeSeriesSubscriptionSymbol TimeSeriesSubscriptionSymbol::fromGraal(void *graal
}

std::string TimeSeriesSubscriptionSymbol::toString() const noexcept {
return eventSymbol_->toString() + "{fromTime=" + formatTimeStampWithMillis(fromTime_) + "}";
if constexpr (Debugger::isDebug) {
return "TimeSeriesSubscriptionSymbol{" + eventSymbol_->toString() +
", fromTime = " + formatTimeStampWithMillis(fromTime_) + "}";
} else {
return eventSymbol_->toString() + "{fromTime=" + formatTimeStampWithMillis(fromTime_) + "}";
}
}

bool TimeSeriesSubscriptionSymbol::operator==(
Expand Down
Loading

0 comments on commit 879ce97

Please sign in to comment.