Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions score/mw/com/impl/bindings/lola/sample_ptr.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class SamplePtr final
TransactionLogSet::TransactionLogIndex transaction_log_idx) noexcept
: SamplePtr{ptr, std::make_optional<SlotDecrementer>(&event_data_ctrl, slot_indicator, transaction_log_idx)}
{
timestamp_ = (event_data_ctrl)[slot_indicator.GetIndex()].GetTimeStamp();
}

~SamplePtr() noexcept = default;
Expand Down Expand Up @@ -103,6 +104,31 @@ class SamplePtr final
return managed_object_;
}

/// \brief Compares two SamplePtr instances based on their timestamp
/// \param other SamplePtr to compare against
/// \return true if this instance is older than \p other, false otherwise or if any of the SamplePtr are invalid
bool operator<(const SamplePtr& other) const noexcept
{
if (!(*this) || !other)
{
return false;
}

return timestamp_ < other.timestamp_;
}

/// \brief Compares two SamplePtr instances based on their timestamp
/// \param other SamplePtr to compare against
/// \return true if this instance is newer than \p other, false otherwise or if any of the SamplePtr are invalid
bool operator>(const SamplePtr& other) const noexcept
{
if (!(*this) || !other)
{
return false;
}
return timestamp_ > other.timestamp_;
}

private:
explicit SamplePtr(pointer managed_object, std::optional<SlotDecrementer>&& slog_decrementer) noexcept
: managed_object_{managed_object}, slot_decrementer_{std::move(slog_decrementer)}
Expand All @@ -111,6 +137,7 @@ class SamplePtr final

pointer managed_object_;
std::optional<SlotDecrementer> slot_decrementer_;
EventSlotStatus::EventTimeStamp timestamp_;
};

} // namespace score::mw::com::impl::lola
Expand Down
156 changes: 156 additions & 0 deletions score/mw/com/impl/bindings/lola/sample_ptr_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,19 @@ class SamplePtrTest : public ::testing::Test
event_data_control_.EventReady(slot, timestamp);
return slot.GetIndex();
}

SamplePtr<std::uint8_t> CreateSamplePtr(const EventSlotStatus::EventTimeStamp timestamp,
const std::size_t slot_index)
{
AllocateSlot(timestamp);
auto slot_indicator = event_data_control_.ReferenceNextEvent(slot_index, transaction_log_index_);
EXPECT_TRUE(slot_indicator.IsValid());

dummy_storage_.push_back(std::make_unique<std::uint8_t>(0U));
return SamplePtr<std::uint8_t>{
dummy_storage_.back().get(), event_data_control_, slot_indicator, transaction_log_index_};
}
std::vector<std::unique_ptr<std::uint8_t>> dummy_storage_;
};

/// \brief Templated test fixture for SamplePtr functionality that works for both void and non-void types
Expand Down Expand Up @@ -183,5 +196,148 @@ TEST_F(SamplePtrTest, StarOp)
EXPECT_EQ(val1.member2_, 44);
}

TEST_F(SamplePtrTest, GreaterThanReturnsTrueWhenLeftSampleHasNewerTimestamp)
{
constexpr EventSlotStatus::EventTimeStamp kOlderTimestamp{10U};
constexpr EventSlotStatus::EventTimeStamp kNewerTimestamp{42U};

auto older_sample = CreateSamplePtr(kOlderTimestamp, 0U);
auto newer_sample = CreateSamplePtr(kNewerTimestamp, 1U);

const bool result = newer_sample > older_sample;

EXPECT_TRUE(result);
}

TEST_F(SamplePtrTest, GreaterThanReturnsFalseWhenLeftSampleHasOlderTimestamp)
{
constexpr EventSlotStatus::EventTimeStamp kOlderTimestamp{10U};
constexpr EventSlotStatus::EventTimeStamp kNewerTimestamp{42U};

auto older_sample = CreateSamplePtr(kOlderTimestamp, 0U);
auto newer_sample = CreateSamplePtr(kNewerTimestamp, 1U);

const bool result = older_sample > newer_sample;

EXPECT_FALSE(result);
}

TEST_F(SamplePtrTest, SortByTimestampOrdersSamplesFromNewestToOldest)
{
constexpr EventSlotStatus::EventTimeStamp kOldestTimestamp{10U};
constexpr EventSlotStatus::EventTimeStamp kMiddleTimestamp{42U};
constexpr EventSlotStatus::EventTimeStamp kNewestTimestamp{43U};

std::vector<SamplePtr<std::uint8_t>> samples{};
samples.emplace_back(CreateSamplePtr(kOldestTimestamp, 0U));
samples.emplace_back(CreateSamplePtr(kMiddleTimestamp, 1U));
samples.emplace_back(CreateSamplePtr(kNewestTimestamp, 2U));

std::sort(samples.begin(), samples.end(), [](const auto& lhs, const auto& rhs) {
return lhs > rhs;
});

EXPECT_TRUE(samples[0] > samples[1]);
EXPECT_TRUE(samples[0] > samples[2]);
EXPECT_TRUE(samples[1] > samples[2]);
EXPECT_FALSE(samples[2] > samples[0]);
EXPECT_FALSE(samples[2] > samples[1]);
}

TEST_F(SamplePtrTest, LessThanReturnsTrueWhenLeftSampleHasOlderTimestamp)
{
constexpr EventSlotStatus::EventTimeStamp kOlderTimestamp{10U};
constexpr EventSlotStatus::EventTimeStamp kNewerTimestamp{42U};

auto older_sample = CreateSamplePtr(kOlderTimestamp, 0U);
auto newer_sample = CreateSamplePtr(kNewerTimestamp, 1U);

const bool result = older_sample < newer_sample;

EXPECT_TRUE(result);
}

TEST_F(SamplePtrTest, LessThanReturnsFalseWhenLeftSampleHasNewerTimestamp)
{
constexpr EventSlotStatus::EventTimeStamp kOlderTimestamp{10U};
constexpr EventSlotStatus::EventTimeStamp kNewerTimestamp{42U};

auto older_sample = CreateSamplePtr(kOlderTimestamp, 0U);
auto newer_sample = CreateSamplePtr(kNewerTimestamp, 1U);

const bool result = newer_sample < older_sample;

EXPECT_FALSE(result);
}

TEST_F(SamplePtrTest, SortByTimestampOrdersSamplesFromOldestToNewest)
{
constexpr EventSlotStatus::EventTimeStamp kOldestTimestamp{10U};
constexpr EventSlotStatus::EventTimeStamp kMiddleTimestamp{42U};
constexpr EventSlotStatus::EventTimeStamp kNewestTimestamp{43U};

std::vector<SamplePtr<std::uint8_t>> samples{};
samples.emplace_back(CreateSamplePtr(kOldestTimestamp, 0U));
samples.emplace_back(CreateSamplePtr(kMiddleTimestamp, 1U));
samples.emplace_back(CreateSamplePtr(kNewestTimestamp, 2U));

std::sort(samples.begin(), samples.end(), [](const auto& lhs, const auto& rhs) {
return lhs < rhs;
});

EXPECT_TRUE(samples[0] < samples[1]);
EXPECT_TRUE(samples[0] < samples[2]);
EXPECT_TRUE(samples[1] < samples[2]);
EXPECT_FALSE(samples[2] < samples[0]);
EXPECT_FALSE(samples[2] < samples[1]);
}

TEST_F(SamplePtrTest, GreaterThanReturnsFalseWhenLeftSampleIsInvalid)
{
constexpr EventSlotStatus::EventTimeStamp kTimestamp{42U};

SamplePtr<std::uint8_t> invalid_sample{};
auto valid_sample = CreateSamplePtr(kTimestamp, 0U);

const bool result = invalid_sample > valid_sample;

EXPECT_FALSE(result);
}

TEST_F(SamplePtrTest, GreaterThanReturnsFalseWhenRightSampleIsInvalid)
{
constexpr EventSlotStatus::EventTimeStamp kTimestamp{42U};

auto valid_sample = CreateSamplePtr(kTimestamp, 0U);
SamplePtr<std::uint8_t> invalid_sample{};

const bool result = valid_sample > invalid_sample;

EXPECT_FALSE(result);
}

TEST_F(SamplePtrTest, LessThanReturnsFalseWhenLeftSampleIsInvalid)
{
constexpr EventSlotStatus::EventTimeStamp kTimestamp{42U};

SamplePtr<std::uint8_t> invalid_sample{};
auto valid_sample = CreateSamplePtr(kTimestamp, 0U);

const bool result = invalid_sample < valid_sample;

EXPECT_FALSE(result);
}

TEST_F(SamplePtrTest, LessThanReturnsFalseWhenRightSampleIsInvalid)
{
constexpr EventSlotStatus::EventTimeStamp kTimestamp{42U};

auto valid_sample = CreateSamplePtr(kTimestamp, 0U);
SamplePtr<std::uint8_t> invalid_sample{};

const bool result = valid_sample < invalid_sample;

EXPECT_FALSE(result);
}
} // namespace
} // namespace score::mw::com::impl::lola
1 change: 1 addition & 0 deletions score/mw/com/impl/plumbing/rust/sample_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ struct SlotDecrementer {
struct LolaBinding<T> {
_managed_object: *const T,
_slot_decrementer: CxxOptional<SlotDecrementer>,
_timestamp: u32,
}

#[repr(C)]
Expand Down
37 changes: 37 additions & 0 deletions score/mw/com/impl/plumbing/sample_ptr.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,43 @@ class SamplePtr final
return get();
}

bool operator<(const SamplePtr& other) const noexcept
{
if (!(*this) || !other)
{
return false;
}

return std::visit(
score::cpp::overload(
[](const lola::SamplePtr<SampleType>& lhs, const lola::SamplePtr<SampleType>& rhs) noexcept -> bool {
return lhs < rhs;
},
[](const auto&, const auto&) noexcept -> bool {
return false;
}),
binding_sample_ptr_,
other.binding_sample_ptr_);
}

bool operator>(const SamplePtr& other) const noexcept
{
if (!(*this) || !other)
{
return false;
}

return std::visit(
score::cpp::overload(
[](const lola::SamplePtr<SampleType>& lhs, const lola::SamplePtr<SampleType>& rhs) noexcept -> bool {
return lhs > rhs;
},
[](const auto&, const auto&) noexcept -> bool {
return false;
}),
binding_sample_ptr_,
other.binding_sample_ptr_);
}
explicit operator bool() const noexcept
{
return std::holds_alternative<score::cpp::blank>(binding_sample_ptr_) == false;
Expand Down