38 template <
typename Feed,
typename... Arguments>
41 template <
typename Feed,
typename Argument>
43 : std::is_base_of<Feed, typename std::decay<Argument>::type>{};
45 template <
typename Message>
50 static auto test(
int) ->
decltype(
asSpan(std::declval<T>()), std::true_type{});
53 static std::false_type test(...);
59 template <
typename Message>
61 IsMessageRecipe<typename std::decay<Message>::type>::value ||
62 IsSpanCompatibleMessage<Message>::value>
65 template <typename Message, bool = IsMessageRecipe<typename std::decay<Message>::type>::value>
70 : message_(std::forward<Message>(message))
76 return asSpan(std::forward<Message>(message_));
83 template <
typename Message>
86 using Recipe =
typename std::decay<Message>::type;
91 recipe.applyTo(holder_);
100 typename Recipe::HolderType holder_;
130template <
typename Delivery>
133 template <
bool...>
struct BooleanPack{};
134 template <
bool... Values>
using All = std::is_same<BooleanPack<Values...,
true>, BooleanPack<
true, Values...>>;
141 template <
typename... Messages>
147 template <
typename Result,
typename... Messages>
149 (
sizeof...(Messages) > 0)
151 && All<!std::is_base_of<PacketHeader, typename std::decay<Messages>::type>::value...>::value
152 && All<details::IsMaterializableMessage<Messages>::value...>::value,
158 template <
typename Result,
typename... Messages>
164 static_assert(MaxSpansCount >= 2,
"must include the packet header and at least one message.");
170 template <
typename... Arguments,
typename std::enable_if<
173 : Delivery(
std::forward<Arguments>(arguments)...)
198 template <
typename... Messages>
202 validateMessageCount<Messages...>();
205 return materializeMessages<0>(consumer, messageSpans, std::forward<Messages>(messages)...);
215 template <
typename... Messages>
221 validateMessageCount<Messages...>();
223 SendMessages consumer{*
this, seqNum, sendingTime,
false};
224 return materializeMessages<0>(consumer, messageSpans, std::forward<Messages>(messages)...);
246 template <
class Collection, details::EnableIfByteSpanCollection<Collection> = 0>
261 template <
class Collection, details::EnableIfByteSpanCollection<Collection> = 0>
266 return send(seqNum, sendingTime, checked.data, checked.count);
282 template <
typename... Messages>
287 return sendPacketHolder(seqNum, packet);
297 template <
typename... Messages>
302 return sendPacketHolder(seqNum, sendingTime, packet);
319 template <
typename... Messages>
324 return sendPacketHolder(seqNum, packet);
334 template <
typename... Messages>
339 return sendPacketHolder(seqNum, sendingTime, packet);
358 template <
typename... Messages>
361 validateMessageCount<Messages...>();
364 materializeMessages<0>(consumer, messageSpans, std::forward<Messages>(messages)...);
373 template <
typename... Messages>
377 validateMessageCount<Messages...>();
379 SendPrimaryMessages consumer{*
this, seqNum, sendingTime,
false};
380 materializeMessages<0>(consumer, messageSpans, std::forward<Messages>(messages)...);
399 template <
class Collection, details::EnableIfByteSpanCollection<Collection> = 0>
412 template <
class Collection, details::EnableIfByteSpanCollection<Collection> = 0>
416 sendPrimary(seqNum, sendingTime, checked.data, checked.count);
430 template <
typename... Messages>
434 sendPrimaryPacketHolder(seqNum, packet);
443 template <
typename... Messages>
447 sendPrimaryPacketHolder(seqNum, sendingTime, packet);
463 template <
typename... Messages>
467 sendPrimaryPacketHolder(seqNum, packet);
476 template <
typename... Messages>
480 sendPrimaryPacketHolder(seqNum, sendingTime, packet);
499 template <
typename... Messages>
502 validateMessageCount<Messages...>();
505 materializeMessages<0>(consumer, messageSpans, std::forward<Messages>(messages)...);
514 template <
typename... Messages>
518 validateMessageCount<Messages...>();
520 SendSecondaryMessages consumer{*
this, seqNum, sendingTime,
false};
521 materializeMessages<0>(consumer, messageSpans, std::forward<Messages>(messages)...);
540 template <
class Collection, details::EnableIfByteSpanCollection<Collection> = 0>
553 template <
class Collection, details::EnableIfByteSpanCollection<Collection> = 0>
557 sendSecondary(seqNum, sendingTime, checked.data, checked.count);
571 template <
typename... Messages>
575 sendSecondaryPacketHolder(seqNum, packet);
584 template <
typename... Messages>
588 sendSecondaryPacketHolder(seqNum, sendingTime, packet);
604 template <
typename... Messages>
608 sendSecondaryPacketHolder(seqNum, packet);
617 template <
typename... Messages>
621 sendSecondaryPacketHolder(seqNum, sendingTime, packet);
629 return Delivery::primaryFeed();
637 return Delivery::secondaryFeed();
645 return Delivery::hasSecondary();
666 sequenceNumber, useCurrentTime ?
UtcWatch::now() : sendingTime,
671 struct SendPrimaryMessages
676 SequenceNumber sequenceNumber;
677 Messaging::Timestamp sendingTime;
680 void operator()(
const ByteSpan* spans,
size_t count)
const
682 feed.sendPrimary(sequenceNumber, useCurrentTime ? UtcWatch::now() : sendingTime, spans, count);
686 struct SendSecondaryMessages
691 SequenceNumber sequenceNumber;
692 Messaging::Timestamp sendingTime;
695 void operator()(
const ByteSpan* spans,
size_t count)
const
697 feed.sendSecondary(sequenceNumber, useCurrentTime ? UtcWatch::now() : sendingTime, spans, count);
701 template <std::
size_t Index,
typename Consumer, std::
size_t Count>
702 static typename std::enable_if<Index == Count, typename Consumer::Result>::type
703 materializeMessages(Consumer& consumer, std::array<ByteSpan, Count>& spans)
705 return consumer(spans.data(), spans.size());
708 template <std::size_t Index,
typename Consumer, std::size_t Count,
typename Message,
typename... Messages>
709 static typename Consumer::Result
710 materializeMessages(Consumer& consumer, std::array<ByteSpan, Count>& spans, Message&& message, Messages&&... messages)
712 details::MaterializedMessage<Message> materialized(std::forward<Message>(message));
713 spans[Index] = materialized.span();
714 return materializeMessages<Index + 1>(consumer, spans, std::forward<Messages>(messages)...);
717 template <
typename... Messages>
718 Threading::Event sendPacketHolder(SequenceNumber seqNum, PacketHolder<Messages...>& packet)
720 const auto messageSpans = makeMessageSpans(packet);
721 return send(seqNum, UtcWatch::now(), messageSpans.data(), messageSpans.size());
724 template <
typename... Messages>
725 Threading::Event sendPacketHolder(SequenceNumber seqNum, Messaging::Timestamp sendingTime, PacketHolder<Messages...>& packet)
727 const auto messageSpans = makeMessageSpans(packet);
728 return send(seqNum, sendingTime, messageSpans.data(), messageSpans.size());
731 template <
typename... Messages>
732 void sendPrimaryPacketHolder(SequenceNumber seqNum, PacketHolder<Messages...>& packet)
734 const auto messageSpans = makeMessageSpans(packet);
735 sendPrimary(seqNum, UtcWatch::now(), messageSpans.data(), messageSpans.size());
738 template <
typename... Messages>
739 void sendPrimaryPacketHolder(SequenceNumber seqNum, Messaging::Timestamp sendingTime, PacketHolder<Messages...>& packet)
741 const auto messageSpans = makeMessageSpans(packet);
742 sendPrimary(seqNum, sendingTime, messageSpans.data(), messageSpans.size());
745 template <
typename... Messages>
746 void sendSecondaryPacketHolder(SequenceNumber seqNum, PacketHolder<Messages...>& packet)
748 const auto messageSpans = makeMessageSpans(packet);
749 sendSecondary(seqNum, UtcWatch::now(), messageSpans.data(), messageSpans.size());
752 template <
typename... Messages>
753 void sendSecondaryPacketHolder(SequenceNumber seqNum, Messaging::Timestamp sendingTime, PacketHolder<Messages...>& packet)
755 const auto messageSpans = makeMessageSpans(packet);
756 sendSecondary(seqNum, sendingTime, messageSpans.data(), messageSpans.size());
759 template <
typename... Messages>
760 static typename PacketHolder<Messages...>::MessageSpans makeMessageSpans(PacketHolder<Messages...>& packet)
noexcept
762 validateMessageCount<Messages...>();
763 return packet.toNetworkMessageSpans();
766 template <
typename... Messages>
767 static void validateMessageCount() noexcept
769 static_assert(
sizeof...(Messages) < MaxSpansCount,
"packet contains too many messages.");
772 template <
typename Sender>
773 static auto sendPacket(SequenceNumber seqNum, Messaging::Timestamp sendingTime,
const ByteSpan messages[],
size_t messagesCnt, Sender&& sender)
774 ->
decltype(sender(std::declval<const ByteSpan*>(), std::size_t{}))
776 PacketHeader packetHeader;
777 packetHeader.seqNumber(seqNum);
778 packetHeader.sendingTime(sendingTime);
780 std::array<ByteSpan, MaxSpansCount> packet{};
781 packet[0] =
asSpan(packetHeader);
783 for (std::size_t index = 0; index < messagesCnt; ++index)
784 packet[index + 1] = messages[index];
786 return sender(packet.data(), messagesCnt + 1);
789 Threading::Event send(SequenceNumber seqNum, Messaging::Timestamp sendingTime,
const ByteSpan messages[], std::size_t messagesCnt)
792 [
this](
const ByteSpan packet[], std::size_t spansCount) {
return Delivery::send(packet, spansCount);};
794 return sendPacket(seqNum, sendingTime, messages, messagesCnt, sender);
797 void sendPrimary(SequenceNumber seqNum, Messaging::Timestamp sendingTime,
const ByteSpan messages[], std::size_t messagesCnt)
800 [
this](
const ByteSpan packet[], std::size_t spansCount) { Delivery::sendPrimary(packet, spansCount);};
802 sendPacket(seqNum, sendingTime, messages, messagesCnt, sender);
805 void sendSecondary(SequenceNumber seqNum, Messaging::Timestamp sendingTime,
const ByteSpan messages[], std::size_t messagesCnt)
808 [
this](
const ByteSpan packet[], std::size_t spansCount) { Delivery::sendSecondary(packet, spansCount);};
810 sendPacket(seqNum, sendingTime, messages, messagesCnt, sender);
#define ONIXS_CME_MDH_TESTING_NAMESPACE_END
#define ONIXS_CME_MDH_TESTING_NAMESPACE_BEGIN
#define ONIXS_CMEMDH_NODISCARD
The time point without the time-zone information.
Builds CME MDP packets and delegates their delivery to a delivery policy.
void sendSecondary(SequenceNumber seqNum, Messaging::Timestamp sendingTime, Collection &&messages)
Sends encoded messages to the secondary feed with an explicit packet sending time.
auto sendPrimary(SequenceNumber seqNum, Messaging::Timestamp sendingTime, PacketHolder< Messages... > &packet) -> EnablePacketHolderSend< void, Messages... >
Sends a packet holder to the primary feed with an explicit packet sending time.
auto sendPrimary(SequenceNumber seqNum, Messaging::Timestamp sendingTime, PacketHolder< Messages... > &&packet) -> EnablePacketHolderSend< void, Messages... >
Sends a temporary packet holder to the primary feed with an explicit packet sending time.
auto sendSecondary(SequenceNumber seqNum, Messaging::Timestamp sendingTime, PacketHolder< Messages... > &packet) -> EnablePacketHolderSend< void, Messages... >
Sends a packet holder to the secondary feed with an explicit packet sending time.
auto send(SequenceNumber seqNum, Messaging::Timestamp sendingTime, PacketHolder< Messages... > &&packet) -> EnablePacketHolderSend< Threading::Event, Messages... >
Sends a temporary packet holder's messages with an explicit packet sending time.
void sendPrimary(SequenceNumber seqNum, Collection &&messages)
Sends a contiguous collection of encoded messages to the primary feed.
NetFeedRole::Enum secondaryFeed() const noexcept
Returns the secondary feed role reported by the delivery policy.
auto send(SequenceNumber seqNum, Messages &&... messages) -> EnableSend< Threading::Event, Messages... >
Sends one or more held messages as one packet through the delivery policy.
Threading::Event send(SequenceNumber seqNum, Messaging::Timestamp sendingTime, Collection &&messages)
Sends a contiguous collection of encoded messages with an explicit packet sending time.
Threading::Event send(SequenceNumber seqNum, Collection &&messages)
Sends a contiguous collection of encoded messages as one packet.
NetFeedRole::Enum primaryFeed() const noexcept
Returns the primary feed role reported by the delivery policy.
bool hasSecondary() const noexcept
Returns whether the delivery policy reports a secondary feed.
auto send(SequenceNumber seqNum, Messaging::Timestamp sendingTime, PacketHolder< Messages... > &packet) -> EnablePacketHolderSend< Threading::Event, Messages... >
Sends a packet holder's messages with an explicit packet sending time.
typename std::enable_if<(sizeof...(Messages) > 0) &&(sizeof...(Messages)< SendMaxSpansCount) &&All<!std::is_base_of< PacketHeader, typename std::decay< Messages >::type >::value... >::value &&All< details::IsMaterializableMessage< Messages >::value... >::value, Result >::type EnableSend
Enables a result type for a non-empty materializable message pack.
auto sendSecondary(SequenceNumber seqNum, Messages &&... messages) -> EnableSend< void, Messages... >
Sends one or more held messages as one packet to the secondary feed.
void sendPrimary(SequenceNumber seqNum, Messaging::Timestamp sendingTime, Collection &&messages)
Sends encoded messages to the primary feed with an explicit packet sending time.
auto sendPrimary(SequenceNumber seqNum, Messages &&... messages) -> EnableSend< void, Messages... >
Sends one or more held messages as one packet to the primary feed.
auto sendSecondary(SequenceNumber seqNum, PacketHolder< Messages... > &packet) -> EnablePacketHolderSend< void, Messages... >
Sends a packet holder's messages to the secondary feed.
auto sendSecondary(SequenceNumber seqNum, Messaging::Timestamp sendingTime, PacketHolder< Messages... > &&packet) -> EnablePacketHolderSend< void, Messages... >
Sends a temporary packet holder to the secondary feed with an explicit packet sending time.
auto send(SequenceNumber seqNum, PacketHolder< Messages... > &packet) -> EnablePacketHolderSend< Threading::Event, Messages... >
Sends a packet holder's messages through the delivery policy.
auto sendSecondary(SequenceNumber seqNum, Messaging::Timestamp sendingTime, Messages &&... messages) -> EnableSend< void, Messages... >
Sends one or more held messages to the secondary feed with an explicit packet sending time.
void sendSecondary(SequenceNumber seqNum, Collection &&messages)
Sends a contiguous collection of encoded messages to the secondary feed.
auto send(SequenceNumber seqNum, PacketHolder< Messages... > &&packet) -> EnablePacketHolderSend< Threading::Event, Messages... >
Sends a temporary packet holder's messages through the delivery policy.
auto sendPrimary(SequenceNumber seqNum, PacketHolder< Messages... > &packet) -> EnablePacketHolderSend< void, Messages... >
Sends a packet holder's messages to the primary feed.
auto send(SequenceNumber seqNum, Messaging::Timestamp sendingTime, Messages &&... messages) -> EnableSend< Threading::Event, Messages... >
Sends one or more held messages with an explicit packet sending time.
virtual ~DataFeed()=default
Destroys the selected delivery policy and its resources.
std::array< ByteSpan, sizeof...(Messages)> MessageSpans
Fixed-size array of non-owning message byte views.
auto sendSecondary(SequenceNumber seqNum, PacketHolder< Messages... > &&packet) -> EnablePacketHolderSend< void, Messages... >
Sends a temporary packet holder's messages to the secondary feed.
typename std::enable_if<(sizeof...(Messages)< SendMaxSpansCount), Result >::type EnablePacketHolderSend
Enables a result type for a packet holder within the delivery span limit.
auto sendPrimary(SequenceNumber seqNum, PacketHolder< Messages... > &&packet) -> EnablePacketHolderSend< void, Messages... >
Sends a temporary packet holder's messages to the primary feed.
auto sendPrimary(SequenceNumber seqNum, Messaging::Timestamp sendingTime, Messages &&... messages) -> EnableSend< void, Messages... >
Sends one or more held messages to the primary feed with an explicit packet sending time.
DataFeed(Arguments &&... arguments)
Constructs the selected delivery policy with the supplied arguments.
Owns a fixed set of CME message holders for sending in one packet.
MaterializedMessage(const Recipe &recipe)
MaterializedMessage(Message &&message) noexcept
static Messaging::Timestamp now() noexcept
Returns current UTC time.
SpanRange checkedSpans(Collection &spans, std::size_t maxSpansCount, std::size_t minSpansCount=0)
ByteSpan asSpan(const PacketHeader &header) noexcept
Provides a read-only byte view of a packet header.
std::span< const std::uint8_t > ByteSpan
Provides a non-owning read-only view over contiguous byte storage.
SharedFuture< void > Event
Completion signal for an asynchronous operation that does not produce a value.
Messaging::UInt32 SequenceNumber
Identifies a packet within an MDP packet sequence.
Enum
Supported feed roles.
static constexpr bool value