Skip to content

Commit b7cb4a8

Browse files
authored
Merge pull request #258 from Gfilinic/add_timestamp_accessor_to_sample_ptr
Expose SamplePtr age in C++ API
2 parents c639a51 + 2d26aa1 commit b7cb4a8

5 files changed

Lines changed: 285 additions & 0 deletions

File tree

score/mw/com/impl/bindings/lola/sample_ptr.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class SamplePtr final
4949
const SlotIndexType slot_index) noexcept
5050
: SamplePtr{ptr, std::make_optional<SlotDecrementer>(event_data_ctrl_local, slot_index)}
5151
{
52+
timestamp_ = (event_data_ctrl_local)[slot_index].GetTimeStamp();
5253
}
5354

5455
~SamplePtr() noexcept = default;
@@ -101,6 +102,31 @@ class SamplePtr final
101102
return managed_object_;
102103
}
103104

105+
/// \brief Compares two SamplePtr instances based on their timestamp
106+
/// \param other SamplePtr to compare against
107+
/// \return true if this instance is older than \p other, false otherwise or if any of the SamplePtr are invalid
108+
bool operator<(const SamplePtr& other) const noexcept
109+
{
110+
if (!(*this) || !other)
111+
{
112+
return false;
113+
}
114+
115+
return timestamp_ < other.timestamp_;
116+
}
117+
118+
/// \brief Compares two SamplePtr instances based on their timestamp
119+
/// \param other SamplePtr to compare against
120+
/// \return true if this instance is newer than \p other, false otherwise or if any of the SamplePtr are invalid
121+
bool operator>(const SamplePtr& other) const noexcept
122+
{
123+
if (!(*this) || !other)
124+
{
125+
return false;
126+
}
127+
return timestamp_ > other.timestamp_;
128+
}
129+
104130
private:
105131
explicit SamplePtr(pointer managed_object, std::optional<SlotDecrementer>&& slog_decrementer) noexcept
106132
: managed_object_{managed_object}, slot_decrementer_{std::move(slog_decrementer)}
@@ -109,6 +135,7 @@ class SamplePtr final
109135

110136
pointer managed_object_;
111137
std::optional<SlotDecrementer> slot_decrementer_;
138+
EventSlotStatus::EventTimeStamp timestamp_;
112139
};
113140

114141
} // namespace score::mw::com::impl::lola

score/mw/com/impl/bindings/lola/sample_ptr_test.cpp

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,19 @@ class SamplePtrTest : public ::testing::Test
5151
provider_event_data_control_local_.EventReady(slot.value(), timestamp);
5252
return slot.value();
5353
}
54+
55+
SamplePtr<std::uint8_t> CreateSamplePtr(const EventSlotStatus::EventTimeStamp timestamp,
56+
const EventSlotStatus::EventTimeStamp last_search_time)
57+
{
58+
AllocateSlot(timestamp);
59+
auto slot_index = consumer_event_data_control_local_.ReferenceNextEvent(last_search_time);
60+
EXPECT_TRUE(slot_index.has_value());
61+
62+
dummy_storage_.push_back(std::make_unique<std::uint8_t>(0U));
63+
return SamplePtr<std::uint8_t>{
64+
dummy_storage_.back().get(), consumer_event_data_control_local_, slot_index.value()};
65+
}
66+
std::vector<std::unique_ptr<std::uint8_t>> dummy_storage_;
5467
};
5568

5669
/// \brief Templated test fixture for SamplePtr functionality that works for both void and non-void types
@@ -179,5 +192,148 @@ TEST_F(SamplePtrTest, StarOp)
179192
EXPECT_EQ(val1.member2_, 44);
180193
}
181194

195+
TEST_F(SamplePtrTest, GreaterThanReturnsTrueWhenLeftSampleHasNewerTimestamp)
196+
{
197+
constexpr EventSlotStatus::EventTimeStamp kOlderTimestamp{10U};
198+
constexpr EventSlotStatus::EventTimeStamp kNewerTimestamp{42U};
199+
200+
auto older_sample = CreateSamplePtr(kOlderTimestamp, 0U);
201+
auto newer_sample = CreateSamplePtr(kNewerTimestamp, 1U);
202+
203+
const bool result = newer_sample > older_sample;
204+
205+
EXPECT_TRUE(result);
206+
}
207+
208+
TEST_F(SamplePtrTest, GreaterThanReturnsFalseWhenLeftSampleHasOlderTimestamp)
209+
{
210+
constexpr EventSlotStatus::EventTimeStamp kOlderTimestamp{10U};
211+
constexpr EventSlotStatus::EventTimeStamp kNewerTimestamp{42U};
212+
213+
auto older_sample = CreateSamplePtr(kOlderTimestamp, 0U);
214+
auto newer_sample = CreateSamplePtr(kNewerTimestamp, 1U);
215+
216+
const bool result = older_sample > newer_sample;
217+
218+
EXPECT_FALSE(result);
219+
}
220+
221+
TEST_F(SamplePtrTest, SortByTimestampOrdersSamplesFromNewestToOldest)
222+
{
223+
constexpr EventSlotStatus::EventTimeStamp kOldestTimestamp{10U};
224+
constexpr EventSlotStatus::EventTimeStamp kMiddleTimestamp{42U};
225+
constexpr EventSlotStatus::EventTimeStamp kNewestTimestamp{43U};
226+
227+
std::vector<SamplePtr<std::uint8_t>> samples{};
228+
samples.emplace_back(CreateSamplePtr(kOldestTimestamp, 0U));
229+
samples.emplace_back(CreateSamplePtr(kMiddleTimestamp, 1U));
230+
samples.emplace_back(CreateSamplePtr(kNewestTimestamp, 2U));
231+
232+
std::sort(samples.begin(), samples.end(), [](const auto& lhs, const auto& rhs) {
233+
return lhs > rhs;
234+
});
235+
236+
EXPECT_TRUE(samples[0] > samples[1]);
237+
EXPECT_TRUE(samples[0] > samples[2]);
238+
EXPECT_TRUE(samples[1] > samples[2]);
239+
EXPECT_FALSE(samples[2] > samples[0]);
240+
EXPECT_FALSE(samples[2] > samples[1]);
241+
}
242+
243+
TEST_F(SamplePtrTest, LessThanReturnsTrueWhenLeftSampleHasOlderTimestamp)
244+
{
245+
constexpr EventSlotStatus::EventTimeStamp kOlderTimestamp{10U};
246+
constexpr EventSlotStatus::EventTimeStamp kNewerTimestamp{42U};
247+
248+
auto older_sample = CreateSamplePtr(kOlderTimestamp, 0U);
249+
auto newer_sample = CreateSamplePtr(kNewerTimestamp, 1U);
250+
251+
const bool result = older_sample < newer_sample;
252+
253+
EXPECT_TRUE(result);
254+
}
255+
256+
TEST_F(SamplePtrTest, LessThanReturnsFalseWhenLeftSampleHasNewerTimestamp)
257+
{
258+
constexpr EventSlotStatus::EventTimeStamp kOlderTimestamp{10U};
259+
constexpr EventSlotStatus::EventTimeStamp kNewerTimestamp{42U};
260+
261+
auto older_sample = CreateSamplePtr(kOlderTimestamp, 0U);
262+
auto newer_sample = CreateSamplePtr(kNewerTimestamp, 1U);
263+
264+
const bool result = newer_sample < older_sample;
265+
266+
EXPECT_FALSE(result);
267+
}
268+
269+
TEST_F(SamplePtrTest, SortByTimestampOrdersSamplesFromOldestToNewest)
270+
{
271+
constexpr EventSlotStatus::EventTimeStamp kOldestTimestamp{10U};
272+
constexpr EventSlotStatus::EventTimeStamp kMiddleTimestamp{42U};
273+
constexpr EventSlotStatus::EventTimeStamp kNewestTimestamp{43U};
274+
275+
std::vector<SamplePtr<std::uint8_t>> samples{};
276+
samples.emplace_back(CreateSamplePtr(kOldestTimestamp, 0U));
277+
samples.emplace_back(CreateSamplePtr(kMiddleTimestamp, 1U));
278+
samples.emplace_back(CreateSamplePtr(kNewestTimestamp, 2U));
279+
280+
std::sort(samples.begin(), samples.end(), [](const auto& lhs, const auto& rhs) {
281+
return lhs < rhs;
282+
});
283+
284+
EXPECT_TRUE(samples[0] < samples[1]);
285+
EXPECT_TRUE(samples[0] < samples[2]);
286+
EXPECT_TRUE(samples[1] < samples[2]);
287+
EXPECT_FALSE(samples[2] < samples[0]);
288+
EXPECT_FALSE(samples[2] < samples[1]);
289+
}
290+
291+
TEST_F(SamplePtrTest, GreaterThanReturnsFalseWhenLeftSampleIsInvalid)
292+
{
293+
constexpr EventSlotStatus::EventTimeStamp kTimestamp{42U};
294+
295+
SamplePtr<std::uint8_t> invalid_sample{};
296+
auto valid_sample = CreateSamplePtr(kTimestamp, 0U);
297+
298+
const bool result = invalid_sample > valid_sample;
299+
300+
EXPECT_FALSE(result);
301+
}
302+
303+
TEST_F(SamplePtrTest, GreaterThanReturnsFalseWhenRightSampleIsInvalid)
304+
{
305+
constexpr EventSlotStatus::EventTimeStamp kTimestamp{42U};
306+
307+
auto valid_sample = CreateSamplePtr(kTimestamp, 0U);
308+
SamplePtr<std::uint8_t> invalid_sample{};
309+
310+
const bool result = valid_sample > invalid_sample;
311+
312+
EXPECT_FALSE(result);
313+
}
314+
315+
TEST_F(SamplePtrTest, LessThanReturnsFalseWhenLeftSampleIsInvalid)
316+
{
317+
constexpr EventSlotStatus::EventTimeStamp kTimestamp{42U};
318+
319+
SamplePtr<std::uint8_t> invalid_sample{};
320+
auto valid_sample = CreateSamplePtr(kTimestamp, 0U);
321+
322+
const bool result = invalid_sample < valid_sample;
323+
324+
EXPECT_FALSE(result);
325+
}
326+
327+
TEST_F(SamplePtrTest, LessThanReturnsFalseWhenRightSampleIsInvalid)
328+
{
329+
constexpr EventSlotStatus::EventTimeStamp kTimestamp{42U};
330+
331+
auto valid_sample = CreateSamplePtr(kTimestamp, 0U);
332+
SamplePtr<std::uint8_t> invalid_sample{};
333+
334+
const bool result = valid_sample < invalid_sample;
335+
336+
EXPECT_FALSE(result);
337+
}
182338
} // namespace
183339
} // namespace score::mw::com::impl::lola

score/mw/com/impl/plumbing/rust/sample_ptr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ struct SlotDecrementer {
4141
struct LolaBinding<T> {
4242
_managed_object: *const T,
4343
_slot_decrementer: CxxOptional<SlotDecrementer>,
44+
_timestamp: u32,
4445
}
4546

4647
#[repr(C)]

score/mw/com/impl/plumbing/sample_ptr.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,33 @@ class SamplePtr final
143143
return get();
144144
}
145145

146+
bool operator<(const SamplePtr& other) const noexcept
147+
{
148+
return std::visit(
149+
score::cpp::overload(
150+
[](const lola::SamplePtr<SampleType>& lhs, const lola::SamplePtr<SampleType>& rhs) noexcept -> bool {
151+
return lhs < rhs;
152+
},
153+
[](const auto&, const auto&) noexcept -> bool {
154+
return false;
155+
}),
156+
binding_sample_ptr_,
157+
other.binding_sample_ptr_);
158+
}
159+
160+
bool operator>(const SamplePtr& other) const noexcept
161+
{
162+
return std::visit(
163+
score::cpp::overload(
164+
[](const lola::SamplePtr<SampleType>& lhs, const lola::SamplePtr<SampleType>& rhs) noexcept -> bool {
165+
return lhs > rhs;
166+
},
167+
[](const auto&, const auto&) noexcept -> bool {
168+
return false;
169+
}),
170+
binding_sample_ptr_,
171+
other.binding_sample_ptr_);
172+
}
146173
explicit operator bool() const noexcept
147174
{
148175
return std::holds_alternative<score::cpp::blank>(binding_sample_ptr_) == false;

score/mw/com/impl/plumbing/sample_ptr_test.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
* SPDX-License-Identifier: Apache-2.0
1212
********************************************************************************/
1313
#include "score/mw/com/impl/plumbing/sample_ptr.h"
14+
#include "score/mw/com/impl/bindings/lola/consumer_event_data_control_local_view.h"
15+
#include "score/mw/com/impl/bindings/lola/event_data_control.h"
16+
#include "score/mw/com/impl/bindings/lola/provider_event_data_control_local_view.h"
17+
#include "score/mw/com/impl/bindings/lola/test_doubles/fake_memory_resource.h"
18+
#include "score/mw/com/impl/bindings/lola/transaction_log.h"
1419

1520
#include <gtest/gtest.h>
1621

@@ -24,6 +29,43 @@ namespace
2429
{
2530

2631
using TestSampleType = std::uint8_t;
32+
constexpr std::size_t kMaxSlots{5U};
33+
34+
class LolaForwardingSamplePtrTest : public ::testing::Test
35+
{
36+
protected:
37+
lola::FakeMemoryResource memory_{};
38+
lola::EventDataControl event_data_control_{kMaxSlots, memory_};
39+
lola::TransactionLog transaction_log_{kMaxSlots, memory_};
40+
lola::ProviderEventDataControlLocalView<> provider_event_data_control_local_{event_data_control_};
41+
lola::ConsumerEventDataControlLocalView<> consumer_event_data_control_local_{event_data_control_, transaction_log_};
42+
43+
lola::SlotIndexType AllocateSlot(lola::EventSlotStatus::EventTimeStamp timestamp)
44+
{
45+
auto slot = provider_event_data_control_local_.AllocateNextSlot();
46+
EXPECT_TRUE(slot.has_value());
47+
provider_event_data_control_local_.EventReady(slot.value(), timestamp);
48+
return slot.value();
49+
}
50+
51+
SamplePtr<std::uint8_t> CreateImplSamplePtr(const lola::EventSlotStatus::EventTimeStamp timestamp,
52+
const lola::EventSlotStatus::EventTimeStamp last_search_time)
53+
{
54+
AllocateSlot(timestamp);
55+
56+
auto slot_result = consumer_event_data_control_local_.ReferenceNextEvent(last_search_time);
57+
EXPECT_TRUE(slot_result.has_value());
58+
59+
dummy_storage_.push_back(std::make_unique<std::uint8_t>(0U));
60+
61+
lola::SamplePtr<std::uint8_t> lola_sample{
62+
dummy_storage_.back().get(), consumer_event_data_control_local_, slot_result.value()};
63+
64+
return SamplePtr<std::uint8_t>{std::move(lola_sample), SampleReferenceGuard{}};
65+
}
66+
67+
std::vector<std::unique_ptr<std::uint8_t>> dummy_storage_{};
68+
};
2769

2870
/// \brief Templated test fixture for SamplePtr functionality that works for both void and non-void types
2971
template <typename T>
@@ -337,5 +379,37 @@ TYPED_TEST(SamplePtrGenericTypeTest, MovingSamplePtrWillMoveSampleReferenceGuard
337379
EXPECT_EQ(tracker.GetNumAvailableSamples(), max_num_samples - 1);
338380
}
339381

382+
TEST_F(LolaForwardingSamplePtrTest, GreaterThanReturnsTrueWhenForwardedLolaSampleIsNewer)
383+
{
384+
auto older_sample = CreateImplSamplePtr(10U, 0U);
385+
auto newer_sample = CreateImplSamplePtr(42U, 1U);
386+
387+
EXPECT_TRUE(newer_sample > older_sample);
388+
}
389+
390+
TEST_F(LolaForwardingSamplePtrTest, GreaterThanReturnsFalseWhenForwardedLolaSampleIsOlder)
391+
{
392+
auto older_sample = CreateImplSamplePtr(10U, 0U);
393+
auto newer_sample = CreateImplSamplePtr(42U, 1U);
394+
395+
EXPECT_FALSE(older_sample > newer_sample);
396+
}
397+
398+
TEST_F(LolaForwardingSamplePtrTest, LessThanReturnsTrueWhenForwardedLolaSampleIsOlder)
399+
{
400+
auto older_sample = CreateImplSamplePtr(10U, 0U);
401+
auto newer_sample = CreateImplSamplePtr(42U, 1U);
402+
403+
EXPECT_TRUE(older_sample < newer_sample);
404+
}
405+
406+
TEST_F(LolaForwardingSamplePtrTest, LessThanReturnsFalseWhenForwardedLolaSampleIsNewer)
407+
{
408+
auto older_sample = CreateImplSamplePtr(10U, 0U);
409+
auto newer_sample = CreateImplSamplePtr(42U, 1U);
410+
411+
EXPECT_FALSE(newer_sample < older_sample);
412+
}
413+
340414
} // namespace
341415
} // namespace score::mw::com::impl

0 commit comments

Comments
 (0)