forSubscriber needs to act like set_intersection
* fix #1269 * Update TopicTree.h * improve performance * cleanup * indent * move variables * latestMatch * group emitted messages * whitespace * typo * improve performance
This commit is contained in:
+39
-32
@@ -86,43 +86,50 @@ struct Intersection {
|
|||||||
/* How far we already emitted of the two dataChannels */
|
/* How far we already emitted of the two dataChannels */
|
||||||
std::pair<size_t, size_t> emitted = {};
|
std::pair<size_t, size_t> emitted = {};
|
||||||
|
|
||||||
/* Holes are global to the entire topic tree, so we are not guaranteed to find
|
|
||||||
* holes in this intersection - they are sorted, though */
|
|
||||||
unsigned int examinedHoles = 0;
|
|
||||||
|
|
||||||
/* This is a slow path of sorts, most subscribers will be observers, not active senders */
|
/* This is a slow path of sorts, most subscribers will be observers, not active senders */
|
||||||
for (unsigned int id : senderForMessages) {
|
if (!senderForMessages.empty()) {
|
||||||
|
|
||||||
std::pair<size_t, size_t> toEmit = {};
|
std::pair<size_t, size_t> toEmit = {};
|
||||||
std::pair<size_t, size_t> toIgnore = {};
|
unsigned int startAt = 0;
|
||||||
|
|
||||||
/* This linear search is most probably very small - it could be made log2 if every hole
|
/* Iterate each message looking for any to skip */
|
||||||
* knows about its previous accumulated length, which is easy to set up. However this
|
for (auto &message : holes) {
|
||||||
* log2 search will most likely never be a warranted perf. gain */
|
|
||||||
for (; examinedHoles < holes.size(); examinedHoles++) {
|
/* If this message was sent by this subscriber skip it */
|
||||||
if (holes[examinedHoles].messageId == id) {
|
bool skipMessage = false;
|
||||||
toIgnore.first += holes[examinedHoles].lengths.first;
|
for (unsigned int i = startAt; i < senderForMessages.size(); i++) {
|
||||||
toIgnore.second += holes[examinedHoles].lengths.second;
|
if (senderForMessages[i] > message.messageId) {
|
||||||
examinedHoles++;
|
startAt = i;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
if (message.messageId == senderForMessages[i]) {
|
||||||
|
skipMessage = true;
|
||||||
|
startAt = ++i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Collect messages until a skip, then emit messages */
|
||||||
|
if (!skipMessage) {
|
||||||
|
toEmit.first += message.lengths.first;
|
||||||
|
toEmit.second += message.lengths.second;
|
||||||
|
} else {
|
||||||
|
if (toEmit.first || toEmit.second) {
|
||||||
|
std::pair<std::string_view, std::string_view> cutDataChannels = {
|
||||||
|
std::string_view(dataChannels.first.data() + emitted.first, toEmit.first),
|
||||||
|
std::string_view(dataChannels.second.data() + emitted.second, toEmit.second),
|
||||||
|
};
|
||||||
|
/* Only need to test the first data channel for "FIN" */
|
||||||
|
cb(cutDataChannels, emitted.first + toEmit.first + message.lengths.first == dataChannels.first.length());
|
||||||
|
emitted.first += toEmit.first;
|
||||||
|
emitted.second += toEmit.second;
|
||||||
|
toEmit = {};
|
||||||
|
}
|
||||||
|
/* This message is now accounted for, mark as emitted */
|
||||||
|
emitted.first += message.lengths.first;
|
||||||
|
emitted.second += message.lengths.second;
|
||||||
}
|
}
|
||||||
/* We are not the sender of this message so we should emit it in this segment */
|
|
||||||
toEmit.first += holes[examinedHoles].lengths.first;
|
|
||||||
toEmit.second += holes[examinedHoles].lengths.second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Emit this segment */
|
|
||||||
if (toEmit.first || toEmit.second) {
|
|
||||||
std::pair<std::string_view, std::string_view> cutDataChannels = {
|
|
||||||
std::string_view(dataChannels.first.data() + emitted.first, toEmit.first),
|
|
||||||
std::string_view(dataChannels.second.data() + emitted.second, toEmit.second),
|
|
||||||
};
|
|
||||||
|
|
||||||
/* We only need to test the first data channel for "FIN" */
|
|
||||||
cb(cutDataChannels, emitted.first + toEmit.first + toIgnore.first == dataChannels.first.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
emitted.first += toEmit.first + toIgnore.first;
|
|
||||||
emitted.second += toEmit.second + toIgnore.second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emitted.first == dataChannels.first.length() && emitted.second == dataChannels.second.length()) {
|
if (emitted.first == dataChannels.first.length() && emitted.second == dataChannels.second.length()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user