6 #ifndef SWIFT_MISC_TIMESTAMPOBJECTLIST_H
7 #define SWIFT_MISC_TIMESTAMPOBJECTLIST_H
44 return QStringLiteral(
"Min: %1ms Max: %2ms Mean: %3ms").
arg(
min).
arg(
max).
arg(
mean, 0,
'f', 2);
50 template <
class OBJ,
class CONTAINER>
53 static_assert(std::is_base_of_v<ITimestampBased, OBJ>,
"OBJ needs to implement ITimestampBased");
70 return this->
container().findBy([&](
const OBJ &obj) {
return obj.isOlderThan(msSinceEpoch); });
76 const CONTAINER before = this->
findBefore(msSinceEpoch);
77 if (before.isEmpty()) {
return OBJ(); }
78 return before.latestObject();
101 return this->
container().findBy([&](
const OBJ &obj) {
return obj.isNewerThan(msSinceEpoch); });
113 const CONTAINER after = this->
findAfter(msSinceEpoch);
114 if (after.isEmpty()) {
return OBJ(); }
115 return after.oldestObject();
121 return this->
container().findBy([&](
const OBJ &obj) {
return !obj.hasValidTimestamp(); });
127 if (this->
container().isEmpty()) {
return OBJ(); }
128 const auto closest = std::min_element(this->
container().cbegin(), this->
container().cend(),
156 if (tsObj.hasValidTimestamp()) {
continue; }
157 tsObj.setCurrentUtcTime();
164 if (this->
container().isEmpty()) {
return {}; }
178 if (this->
container().isEmpty()) {
return {}; }
192 if (this->
container().isEmpty()) {
return OBJ(); }
195 return a.getMSecsSinceEpoch() < b.getMSecsSinceEpoch();
203 if (this->
container().isEmpty()) {
return OBJ(); }
206 return a.getMSecsSinceEpoch() < b.getMSecsSinceEpoch();
217 return this->
container().removeIf([&](
const OBJ &obj) {
return obj.isOlderThan(msSinceEpoch); });
224 return this->
container().removeIf([&](
const OBJ &obj) {
return obj.isOlderThan(epoch); });
240 Q_ASSERT_X(maxElements < 0 || maxElements > 1, Q_FUNC_INFO,
"Max.value wrong range");
242 if (replaceSameTimestamp && !c.isEmpty() && c[0].getMSecsSinceEpoch() == value.getMSecsSinceEpoch())
245 if (maxElements > 0) { c.truncate(maxElements); }
249 if (maxElements > 0) { c.truncate(maxElements - 1); }
250 const bool needSort = !c.isEmpty() && value.isOlderThan(c.front());
271 const qint64 newMs = newObject.getMSecsSinceEpoch();
272 const qint64 oldMs = this->
container().back().getMSecsSinceEpoch();
284 OBJ newObjectCopy(newObject);
285 newObjectCopy.setMSecsSinceEpoch(newTsMsSinceEpoch);
286 this->
container().push_back(newObjectCopy);
292 if (this->
container().isEmpty()) {
return; }
293 qint64 currentMs = startTimeStampMs;
296 it->setMSecsSinceEpoch(currentMs);
297 currentMs += deltaTimeMs;
307 if (obj.getMSecsSinceEpoch() == newObject.getMSecsSinceEpoch())
320 if (this->
container().size() < 2) {
return true; }
324 if (!obj.hasValidTimestamp()) {
return false; }
325 if (obj.getMSecsSinceEpoch() < max) {
return false; }
326 max = obj.getMSecsSinceEpoch();
335 if (this->
container().size() < 2) {
return true; }
336 qint64 min = std::numeric_limits<qint64>::max();
339 if (!obj.hasValidTimestamp()) {
return false; }
340 if (obj.getMSecsSinceEpoch() > min) {
return false; }
341 min = obj.getMSecsSinceEpoch();
349 if (msToAdd == 0) {
return; }
363 if (container.size() < 2) {
return mmm; }
366 if (
container.m_tsSortHint == NoTimestampSortHint)
369 copy.sortLatestFirst();
370 copy.m_tsSortHint = TimestampLatestFirst;
371 return copy.getTimestampDifferenceMinMaxMean();
374 mmm.
max = std::numeric_limits<qint64>::min();
375 mmm.
min = std::numeric_limits<qint64>::max();
387 mmm.
max = std::max(diff, mmm.
max);
388 mmm.
min = std::min(diff, mmm.
min);
404 const CONTAINER &
container()
const {
return static_cast<const CONTAINER &
>(*this); }
407 CONTAINER &
container() {
return static_cast<CONTAINER &
>(*this); }
414 template <
class OBJ,
class CONTAINER>
417 static_assert(std::is_base_of_v<ITimestampWithOffsetBased, OBJ>,
"OBJ needs to implement ITimestampBased");
423 NoAdjustedTimestampSortHint,
424 AdjustedTimestampLatestFirst
430 this->
container().sortAdjustedOldestFirst();
438 copy.sortAdjustedLatestFirst();
445 if (this->
container().size() < 2) {
return CONTAINER(); }
446 CONTAINER copy(alreadySortedLatestFirst ? this->
container() :
481 Q_ASSERT_X(maxElements < 0 || maxElements > 1, Q_FUNC_INFO,
"Max.value wrong range");
483 if (replaceSameTimestamp && !c.isEmpty() && c[0].getMSecsSinceEpoch() == value.getMSecsSinceEpoch())
486 if (maxElements > 0) { c.truncate(maxElements); }
490 if (maxElements > 0) { c.truncate(maxElements - 1); }
491 const bool needSort = !c.isEmpty() && value.isOlderThanAdjusted(c.front());
499 int maxElements = -1)
512 if (c.size() < 2) {
return; }
518 const qint64 minReqOs =
521 const qint64 os = qMax(minReqOs + 1, avgOs);
534 int maxElements = -1)
550 const qint64 osTime = value.getTimeOffsetMs();
551 const qint64 os = -1 * qAbs(deltaTimeMs < 0 ? osTime : deltaTimeMs);
554 SWIFT_VERIFY_X(os < 0, Q_FUNC_INFO,
"Need negative offset time to prefill time");
557 for (
int i = 1; i < elements; i++)
560 copy.addMsecs(os * i);
570 if (this->
container().isEmpty()) {
return false; }
571 if (this->
container().size() < 2) {
return true; }
575 if (!obj.hasValidTimestamp()) {
return false; }
576 if (obj.getAdjustedMSecsSinceEpoch() < max) {
return false; }
577 max = obj.getAdjustedMSecsSinceEpoch();
586 if (this->
container().size() < 2) {
return true; }
587 qint64 min = std::numeric_limits<qint64>::max();
590 if (!obj.hasValidTimestamp()) {
return false; }
591 if (obj.getAdjustedMSecsSinceEpoch() > min) {
return false; }
592 min = obj.getAdjustedMSecsSinceEpoch();
608 if (after.isEmpty()) {
return OBJ(); }
609 return after.oldestAdjustedObject();
623 if (before.isEmpty()) {
return OBJ(); }
624 return before.latestAdjustedObject();
630 if (this->
container().isEmpty()) {
return OBJ(); }
643 if (this->
container().isEmpty()) {
return OBJ(); }
650 return a.getAdjustedMSecsSinceEpoch() < b.getAdjustedMSecsSinceEpoch();
658 if (this->
container().isEmpty()) {
return OBJ(); }
665 return a.getAdjustedMSecsSinceEpoch() < b.getAdjustedMSecsSinceEpoch();
673 if (this->
container().isEmpty()) {
return {}; }
680 if (this->
container().isEmpty()) {
return {}; }
687 if (this->
container().isEmpty()) {
return -1; }
695 if (this->
container().isEmpty()) {
return -1; }
710 if (container.size() < 1) {
return mmm; }
712 mmm.
max = std::numeric_limits<qint64>::min();
713 mmm.
min = std::numeric_limits<qint64>::max();
719 if (!
object.hasNonZeroOffsetTime()) {
continue; }
720 const qint64 os =
object.getTimeOffsetMs();
721 mmm.
max = std::max(os, mmm.
max);
722 mmm.
min = std::min(os, mmm.
min);
727 if (c > 0) { mmm.
mean = mean / c; }
static bool isLocalDeveloperDebugBuild()
Local build for developers.
qint64 getMSecsSinceEpoch() const
Timestamp as ms value.
qint64 getTimeDifferenceMs(qint64 compareTime) const
Time difference in ms.
qint64 getAbsTimeDifferenceMs(qint64 compareTime) const
Time difference in ms.
List of objects with timestamp. Such objects should implement.
OBJ findObjectBeforeOrDefault(qint64 msSinceEpoch) const
Object before timestamp or default (older)
qint64 latestTimestampMsecsSinceEpoch() const
Latest timestamp.
QDateTime latestTimestamp() const
Latest timestamp.
void push_backOverrideTimestamp(const OBJ &newObject, qint64 newTsMsSinceEpoch)
Push back, but set new timestamp.
void setSortHint(HintTimestampSort hint)
Set the hint.
HintTimestampSort m_tsSortHint
sort hint
void sortOldestFirst()
Sort by timestamp.
OBJ oldestObject() const
Latest object.
int removeBefore(qint64 msSinceEpoch)
Remove objects with timestamp before dateTime.
CONTAINER findBeforeNowMinusOffset(qint64 msOffset) const
List of objects before now - offset.
int replaceIfSameTimestamp(const OBJ &newObject)
Replace if an object has the same timestamp.
CONTAINER findAfter(const QDateTime &dateTime) const
List of objects after dateTime (newer)
void addMsecs(qint64 msToAdd)
Adds a time to all values.
const CONTAINER & container() const
Container.
qint64 oldestTimestampMsecsSinceEpoch() const
Oldest timestamp.
CONTAINER findBeforeAndRemove(qint64 msSinceEpoch)
Get objects before msSinceEpoch and remove those.
MillisecondsMinMaxMean getTimestampDifferenceMinMaxMean() const
Difference of timestamp values.
CONTAINER findAfter(qint64 msSinceEpoch) const
List of objects after msSinceEpoch (newer)
ITimestampObjectList()=default
Constructor.
void setCurrentUtcTime()
Set all timestamps to now.
OBJ findObjectAfterOrDefault(qint64 msSinceEpoch) const
List of objects after msSinceEpoch (newer)
void setInvalidTimestampsToCurrentUtcTime()
Set invalid timestamps to now.
OBJ latestObject() const
Latest object.
void sortLatestFirst()
Sort by timestamp.
HintTimestampSort
Hint if the list is sorted.
void push_backIncreaseTimestamp(const OBJ &newObject)
Push back and increase the timestamp at least by +1ms if equal to last element.
int removeBefore(const QDateTime &dateTime)
Remove objects with timestamp before dateTime.
int removeOlderThanNowMinusOffset(qint64 offsetMs)
Remove objects older than seconds.
bool isSortedLatestLast() const
Is completely sorted: latest last.
CONTAINER & container()
Container.
void push_frontKeepLatestFirst(const OBJ &value, bool replaceSameTimestamp=true, int maxElements=-1)
Insert as first element by keeping maxElements and the latest first.
QDateTime oldestTimestamp() const
Oldest timestamp.
CONTAINER findBefore(const QDateTime &dateTime) const
List of objects before dateTime (older)
CONTAINER findBefore(qint64 msSinceEpoch) const
List of objects before msSinceEpoch (older)
bool hasInvalidTimestamps() const
Has invalid timestamp.
void setUtcTime(qint64 msSinceEpoch)
Set all timestamps to given time.
CONTAINER findInvalidTimestamps() const
Objects without valid timestamp.
bool isSortedLatestFirst() const
Is completely sorted: latest last.
void setNewTimestampStartingLast(qint64 startTimeStampMs, qint64 deltaTimeMs)
Set new timestamps starting with the last element.
CONTAINER findAfterNowMinusOffset(qint64 msOffset) const
List of objects before now - offset.
OBJ findClosestTimeDistance(qint64 msSinceEpoch) const
Find closest (or default)
qint64 getAdjustedMSecsSinceEpoch() const
Timestamp with offset added for interpolation.
qint64 getTimeOffsetMs() const
Milliseconds to add to timestamp for interpolation.
bool isNewerThanAdjusted(const ITimestampWithOffsetBased &otherTimestampObj) const
Is this newer than other?
bool isOlderThanAdjusted(const ITimestampWithOffsetBased &otherTimestampObj) const
Is this older than other?
qint64 getAdjustedTimeDifferenceMs(qint64 compareTime) const
Time difference in ms (this -> compare)
void setTimeOffsetMs(qint64 offset)
Milliseconds to add to timestamp for interpolation.
List of objects with timestamp and offset. Such objects should implement.
OBJ findClosestTimeDistanceAdjusted(qint64 msSinceEpoch) const
Closest adjusted time difference.
bool containsZeroOrNegativeOffsetTime() const
Any negative or zero offset time?
CONTAINER getLatestAdjustedTwoObjects(bool alreadySortedLatestFirst=false) const
Get the latest 2 values.
HintAdjustedTimestampSort
Hint if the list is sorted.
QDateTime oldestAdjustedTimestamp() const
Oldest adjusted timestamp.
bool isSortedAdjustedLatestFirst() const
Is completely sorted: latest last.
OBJ findObjectBeforeAdjustedOrDefault(qint64 msSinceEpoch) const
Object before timestamp (older)
void setAdjustedSortHint(HintAdjustedTimestampSort hint)
Set the hint.
CONTAINER findBeforeAdjusted(qint64 msSinceEpoch) const
List of objects before msSinceEpoch (older)
OBJ latestAdjustedObject() const
Latest adjusted object.
bool isSortedAdjustedLatestLast() const
Is completely sorted: latest last.
MillisecondsMinMaxMean getOffsetMinMaxMean() const
Difference of timestamp values.
void addMsecsToOffset(qint64 msToAdd)
Adds a time to all offset values.
void push_frontKeepLatestAdjustedFirst(const OBJ &value, bool replaceSameTimestamp=true, int maxElements=-1)
Insert as first element by keeping maxElements and the latest first.
qint64 oldestAdjustedTimestampMsecsSinceEpoch() const
Oldest adjusted timestamp.
void sortAdjustedLatestFirst()
Sort by adjusted timestamp.
bool containsNegativeOffsetTime() const
Any negative offset time?
CONTAINER getSortedAdjustedLatestFirst() const
As sorted copy.
void prefillLatestAdjustedFirst(const OBJ &value, int elements, qint64 deltaTimeMs=-1)
Prefill with elements.
QDateTime latestAdjustedTimestamp() const
Latest adjusted timestamp.
OBJ oldestAdjustedObject() const
Oldest adjusted object.
void push_frontKeepLatestFirstAdjustOffset(const OBJ &value, bool replaceSameTimestamp=true, int maxElements=-1)
Insert as first element by keeping maxElements and the latest first.
HintAdjustedTimestampSort m_tsAdjustedSortHint
sort hint
void push_frontKeepLatestFirstIgnoreOverlapping(const OBJ &value, bool replaceSameTimestamp=true, int maxElements=-1)
Add value, but ignore overlapping (past) values.
qint64 latestAdjustedTimestampMsecsSinceEpoch() const
Latest adjusted timestamp.
CONTAINER findAfterAdjusted(qint64 msSinceEpoch) const
List of objects after msSinceEpoch (newer)
OBJ findObjectAfterAdjustedOrDefault(qint64 msSinceEpoch) const
List of objects after msSinceEpoch (newer)
ITimestampWithOffsetObjectList()=default
Constructor.
void sortAdjustedOldestFirst()
Sort by adjusted timestamp.
auto MemberLess(Ts... vs)
Predicate which compares the return values of some member functions of two objects.
Free functions in swift::misc.
T::const_iterator begin(const LockFreeReader< T > &reader)
Non-member begin() and end() for so LockFree containers can be used in ranged for loops.
T::const_iterator end(const LockFreeReader< T > &reader)
Non-member begin() and end() for so LockFree containers can be used in ranged for loops.
qint64 currentMSecsSinceEpoch()
bool isValid() const const
qint64 toMSecsSinceEpoch() const const
QString arg(Args &&... args) const const
Milliseconds minimum/maximum/mean.
bool isValid() const
Valid?
void reset()
Reset the values.
double mean
Mean (average)
QString asString() const
As string.
#define SWIFT_VERIFY_X(COND, WHERE, WHAT)
A weaker kind of assert.