Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the RX pipeline #43

Merged
merged 38 commits into from
Aug 9, 2023
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
b84a93b
Partially complete reassembler; does not build yet
pavel-kirienko Jul 25, 2023
5dda226
The first rough approximation of the reassembler is done; now we need…
pavel-kirienko Jul 25, 2023
aa8a417
Should build now I suppose
pavel-kirienko Jul 25, 2023
1137a42
Remove special case for empty transfers
pavel-kirienko Jul 25, 2023
98c0f53
Add tests for rxSlotRestart
pavel-kirienko Jul 26, 2023
77fdca1
Finish the slot ejection tests
pavel-kirienko Jul 26, 2023
f9fe930
nit
pavel-kirienko Jul 26, 2023
da7c3c1
Slight internal refactoring to uphold orthogonality
pavel-kirienko Jul 27, 2023
deb6426
Add tests for rxSlotAccept()
pavel-kirienko Jul 27, 2023
8fe690c
Iface acceptance test WIP
pavel-kirienko Jul 27, 2023
84ec9b5
Partial tests for rxIfaceAccept
pavel-kirienko Jul 27, 2023
3151ff5
Refactor the iface acceptor and add more tests
pavel-kirienko Jul 28, 2023
3aa6385
Increase test coverage
pavel-kirienko Jul 28, 2023
6c439de
Add tests for rxIfaceFindMatchingSlot
pavel-kirienko Jul 31, 2023
0b40de0
Add session-level frame acceptance logic and transfer deduplication; …
pavel-kirienko Jul 31, 2023
8e29b91
Add test for rxSessionDeduplicate
pavel-kirienko Jul 31, 2023
c12c1d4
Add session acceptance test with deduplication
pavel-kirienko Jul 31, 2023
b6443d9
Add sections for clarity
pavel-kirienko Jul 31, 2023
102bbbe
Add rxPort implementation
pavel-kirienko Aug 1, 2023
ea5d94c
Add port test
pavel-kirienko Aug 1, 2023
8605051
Add destructors & tests; the coverage should be at 100%
pavel-kirienko Aug 2, 2023
bc9b93f
Rename prio -> priority as requested
pavel-kirienko Aug 2, 2023
81378f0
Suppress a bogus alignment warning
pavel-kirienko Aug 2, 2023
b286340
SONAR
pavel-kirienko Aug 2, 2023
f3e35ae
Extract compare32
pavel-kirienko Aug 2, 2023
1d25274
Remove the dependency on fixed-size 8-bit types to avoid portability …
pavel-kirienko Aug 2, 2023
11b7b97
SONAR
pavel-kirienko Aug 2, 2023
75dfe91
Fix a minor naming consistency issue: udpardFragmentFree -> udpardRxF…
pavel-kirienko Aug 3, 2023
1d87ac8
Implement UdpardMemoryDeleter; switch MemoryResource and MemoryDelete…
pavel-kirienko Aug 8, 2023
89563f5
Add clarifying comments
pavel-kirienko Aug 8, 2023
92044da
Remove typedef struct UdpardInternalRxSession
pavel-kirienko Aug 8, 2023
87e49bc
Rename free --> deallocate because Sonar detected a compliance issue
pavel-kirienko Aug 8, 2023
6e4a207
Add comments
pavel-kirienko Aug 8, 2023
8fa5a4b
Split rxPortAccept into two cases: general case and anonymous case #s…
pavel-kirienko Aug 8, 2023
306acf6
Comment
pavel-kirienko Aug 8, 2023
23358bd
Document the maximum recursion depth explicitly
pavel-kirienko Aug 9, 2023
74b30b6
Split rxSlotAccept into thre functions and remove goto
pavel-kirienko Aug 9, 2023
fd7f930
SONAR
pavel-kirienko Aug 9, 2023
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
22 changes: 11 additions & 11 deletions libudpard/_udpard_cavl.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ typedef struct UdpardTreeNode Cavl;

/// Returns POSITIVE if the search target is GREATER than the provided node, negative if smaller, zero on match (found).
/// Values other than {-1, 0, +1} are not recommended to avoid overflow during the narrowing conversion of the result.
typedef int8_t (*CavlPredicate)(void* user_reference, const Cavl* node);
typedef int_fast8_t (*CavlPredicate)(void* user_reference, const Cavl* node);

/// If provided, the factory will be invoked when the sought node does not exist in the tree.
/// It is expected to return a new node that will be inserted immediately (without the need to traverse the tree again).
Expand Down Expand Up @@ -117,13 +117,13 @@ static inline void cavlPrivateRotate(Cavl* const x, const bool r)
static inline Cavl* cavlPrivateAdjustBalance(Cavl* const x, const bool increment)
{
CAVL_ASSERT((x != NULL) && ((x->bf >= -1) && (x->bf <= +1)));
Cavl* out = x;
const int8_t new_bf = (int8_t) (x->bf + (increment ? +1 : -1));
Cavl* out = x;
const int_fast8_t new_bf = (int_fast8_t) (x->bf + (increment ? +1 : -1));
if ((new_bf < -1) || (new_bf > 1))
{
const bool r = new_bf < 0; // bf<0 if left-heavy --> right rotation is needed.
const int8_t sign = r ? +1 : -1; // Positive if we are rotating right.
Cavl* const z = x->lr[!r];
const bool r = new_bf < 0; // bf<0 if left-heavy --> right rotation is needed.
const int_fast8_t sign = r ? +1 : -1; // Positive if we are rotating right.
Cavl* const z = x->lr[!r];
CAVL_ASSERT(z != NULL); // Heavy side cannot be empty.
// NOLINTNEXTLINE(clang-analyzer-core.NullDereference)
if ((z->bf * sign) <= 0) // Parent and child are heavy on the same side or the child is balanced.
Expand All @@ -132,8 +132,8 @@ static inline Cavl* cavlPrivateAdjustBalance(Cavl* const x, const bool increment
cavlPrivateRotate(x, r);
if (0 == z->bf)
{
x->bf = (int8_t) (-sign);
z->bf = (int8_t) (+sign);
x->bf = (int_fast8_t) (-sign);
z->bf = (int_fast8_t) (+sign);
}
else
{
Expand All @@ -150,15 +150,15 @@ static inline Cavl* cavlPrivateAdjustBalance(Cavl* const x, const bool increment
cavlPrivateRotate(x, r);
if ((y->bf * sign) < 0)
{
x->bf = (int8_t) (+sign);
x->bf = (int_fast8_t) (+sign);
y->bf = 0;
z->bf = 0;
}
else if ((y->bf * sign) > 0)
{
x->bf = 0;
y->bf = 0;
z->bf = (int8_t) (-sign);
z->bf = (int_fast8_t) (-sign);
}
else
{
Expand Down Expand Up @@ -209,7 +209,7 @@ static inline Cavl* cavlSearch(Cavl** const root,
Cavl** n = root;
while (*n != NULL)
{
const int8_t cmp = predicate(user_reference, *n);
const int_fast8_t cmp = predicate(user_reference, *n);
if (0 == cmp)
{
out = *n;
Expand Down
994 changes: 913 additions & 81 deletions libudpard/udpard.c

Large diffs are not rendered by default.

184 changes: 98 additions & 86 deletions libudpard/udpard.h

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion tests/.idea/dictionaries/pavel.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion tests/src/helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ typedef struct
uint_least8_t canary[INSTRUMENTED_ALLOCATOR_CANARY_SIZE];
/// The limit can be changed at any moment to control the maximum amount of memory that can be allocated.
/// It may be set to a value less than the currently allocated amount.
size_t limit_fragments;
size_t limit_bytes;
/// The current state of the allocator.
size_t allocated_fragments;
Expand All @@ -72,7 +73,9 @@ static inline void* instrumentedAllocatorAllocate(struct UdpardMemoryResource* c
InstrumentedAllocator* const self = (InstrumentedAllocator*) base;
TEST_PANIC_UNLESS(self->base.allocate == &instrumentedAllocatorAllocate);
void* result = NULL;
if ((size > 0U) && ((self->allocated_bytes + size) <= self->limit_bytes))
if ((size > 0U) && //
((self->allocated_bytes + size) <= self->limit_bytes) && //
((self->allocated_fragments + 1U) <= self->limit_fragments))
{
const size_t size_with_canaries = size + ((size_t) INSTRUMENTED_ALLOCATOR_CANARY_SIZE * 2U);
void* origin = malloc(size_with_canaries);
Expand Down Expand Up @@ -142,6 +145,7 @@ static inline void instrumentedAllocatorNew(InstrumentedAllocator* const self)
{
self->canary[i] = (uint_least8_t) (rand() % (UINT_LEAST8_MAX + 1));
}
self->limit_fragments = SIZE_MAX;
self->limit_bytes = SIZE_MAX;
self->allocated_fragments = 0U;
self->allocated_bytes = 0U;
Expand Down
18 changes: 10 additions & 8 deletions tests/src/hexdump.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@

namespace hexdump
{
template <std::uint8_t BytesPerRow = 16, typename InputIterator>
using Byte = std::uint_least8_t;

template <Byte BytesPerRow = 16, typename InputIterator>
[[nodiscard]] std::string hexdump(InputIterator begin, const InputIterator end)
{
static_assert(BytesPerRow > 0);
static constexpr std::pair<std::uint8_t, std::uint8_t> PrintableASCIIRange{32, 126};
std::uint32_t offset = 0;
std::ostringstream output;
bool first = true;
static constexpr std::pair<Byte, Byte> PrintableASCIIRange{32, 126};
std::uint32_t offset = 0;
std::ostringstream output;
bool first = true;
output << std::hex << std::setfill('0');
do
{
Expand All @@ -33,7 +35,7 @@ template <std::uint8_t BytesPerRow = 16, typename InputIterator>
output << std::setw(8) << offset << " ";
offset += BytesPerRow;
auto it = begin;
for (std::uint8_t i = 0; i < BytesPerRow; ++i)
for (Byte i = 0; i < BytesPerRow; ++i)
{
if (i == 8)
{
Expand All @@ -50,7 +52,7 @@ template <std::uint8_t BytesPerRow = 16, typename InputIterator>
}
}
output << " ";
for (std::uint8_t i = 0; i < BytesPerRow; ++i)
for (Byte i = 0; i < BytesPerRow; ++i)
{
if (begin != end)
{
Expand All @@ -76,6 +78,6 @@ template <std::uint8_t BytesPerRow = 16, typename InputIterator>

[[nodiscard]] inline auto hexdump(const void* const data, const std::size_t size)
{
return hexdump(static_cast<const std::uint8_t*>(data), static_cast<const std::uint8_t*>(data) + size);
return hexdump(static_cast<const Byte*>(data), static_cast<const Byte*>(data) + size);
}
} // namespace hexdump
58 changes: 29 additions & 29 deletions tests/src/test_cavl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ struct Node final : Cavl

T value{};

auto checkLinkageUpLeftRightBF(const Cavl* const check_up,
const Cavl* const check_le,
const Cavl* const check_ri,
const std::int8_t check_bf) const -> bool
auto checkLinkageUpLeftRightBF(const Cavl* const check_up,
const Cavl* const check_le,
const Cavl* const check_ri,
const std::int_fast8_t check_bf) const -> bool
{
return (up == check_up) && //
(lr[0] == check_le) && (lr[1] == check_ri) && //
Expand Down Expand Up @@ -64,7 +64,7 @@ auto search(Node<T>** const root, const Predicate& predicate, const Factory& fac
Predicate predicate;
Factory factory;

static auto callPredicate(void* const user_reference, const Cavl* const node) -> std::int8_t
static auto callPredicate(void* const user_reference, const Cavl* const node) -> std::int_fast8_t
{
const auto ret = static_cast<Refs*>(user_reference)->predicate(static_cast<const Node<T>&>(*node));
if (ret > 0)
Expand Down Expand Up @@ -101,20 +101,20 @@ void remove(Node<T>** const root, const Node<T>* const n)
}

template <typename T>
auto getHeight(const Node<T>* const n) -> std::uint8_t // NOLINT recursion
auto getHeight(const Node<T>* const n) -> std::uint_fast8_t // NOLINT recursion
{
return (n != nullptr) ? static_cast<std::uint8_t>(1U + std::max(getHeight(static_cast<Node<T>*>(n->lr[0])),
getHeight(static_cast<Node<T>*>(n->lr[1]))))
return (n != nullptr) ? static_cast<std::uint_fast8_t>(1U + std::max(getHeight(static_cast<Node<T>*>(n->lr[0])),
getHeight(static_cast<Node<T>*>(n->lr[1]))))
: 0;
}

template <typename T>
void print(const Node<T>* const nd, const std::uint8_t depth = 0, const char marker = 'T') // NOLINT recursion
void print(const Node<T>* const nd, const std::uint_fast8_t depth = 0, const char marker = 'T') // NOLINT recursion
{
TEST_ASSERT(10 > getHeight(nd)); // Fail early for malformed cyclic trees, do not overwhelm stdout.
if (nd != nullptr)
{
print<T>(static_cast<const Node<T>*>(nd->lr[0]), static_cast<std::uint8_t>(depth + 1U), 'L');
print<T>(static_cast<const Node<T>*>(nd->lr[0]), static_cast<std::uint_fast8_t>(depth + 1U), 'L');
for (std::uint16_t i = 1U; i < depth; i++)
{
std::cout << " ";
Expand All @@ -133,7 +133,7 @@ void print(const Node<T>* const nd, const std::uint8_t depth = 0, const char mar
}
std::cout << marker << "=" << static_cast<std::int64_t>(nd->value) //
<< " [" << static_cast<std::int16_t>(nd->bf) << "]" << std::endl;
print<T>(static_cast<const Node<T>*>(nd->lr[1]), static_cast<std::uint8_t>(depth + 1U), 'R');
print<T>(static_cast<const Node<T>*>(nd->lr[1]), static_cast<std::uint_fast8_t>(depth + 1U), 'R');
}
}

Expand Down Expand Up @@ -211,7 +211,7 @@ auto findBrokenBalanceFactor(const Node<T>* const n) -> const Cavl* // NOLINT r

void testCheckAscension()
{
using N = Node<std::uint8_t>;
using N = Node<std::uint_fast8_t>;
N t{2};
N l{1};
N r{3};
Expand All @@ -238,7 +238,7 @@ void testCheckAscension()

void testRotation()
{
using N = Node<std::uint8_t>;
using N = Node<std::uint_fast8_t>;
// Original state:
// x.left = a
// x.right = z
Expand Down Expand Up @@ -284,7 +284,7 @@ void testRotation()

void testBalancingA()
{
using N = Node<std::uint8_t>;
using N = Node<std::uint_fast8_t>;
// Double left-right rotation.
// X X Y
// / ` / ` / `
Expand Down Expand Up @@ -334,7 +334,7 @@ void testBalancingA()

void testBalancingB()
{
using N = Node<std::uint8_t>;
using N = Node<std::uint_fast8_t>;
// Without F the handling of Z and Y is more complex; Z flips the sign of its balance factor:
// X X Y
// / ` / ` / `
Expand Down Expand Up @@ -383,7 +383,7 @@ void testBalancingB()

void testBalancingC()
{
using N = Node<std::uint8_t>;
using N = Node<std::uint_fast8_t>;
// Both X and Z are heavy on the same side.
// X Z
// / ` / `
Expand Down Expand Up @@ -434,9 +434,9 @@ void testBalancingC()

void testRetracingOnGrowth()
{
using N = Node<std::uint8_t>;
using N = Node<std::uint_fast8_t>;
std::array<N, 100> t{};
for (std::uint8_t i = 0; i < 100; i++)
for (std::uint_fast8_t i = 0; i < 100; i++)
{
t[i].value = i;
}
Expand Down Expand Up @@ -640,7 +640,7 @@ void testRetracingOnGrowth()

void testSearchTrivial()
{
using N = Node<std::uint8_t>;
using N = Node<std::uint_fast8_t>;
// A
// B C
// D E F G
Expand Down Expand Up @@ -684,7 +684,7 @@ void testSearchTrivial()

void testRemovalA()
{
using N = Node<std::uint8_t>;
using N = Node<std::uint_fast8_t>;
// 4
// / `
// 2 6
Expand All @@ -693,7 +693,7 @@ void testRemovalA()
// / `
// 7 9
std::array<N, 10> t{};
for (std::uint8_t i = 0; i < 10; i++)
for (std::uint_fast8_t i = 0; i < 10; i++)
{
t[i].value = i;
}
Expand Down Expand Up @@ -1005,7 +1005,7 @@ void testRemovalA()

void testMutationManual()
{
using N = Node<std::uint8_t>;
using N = Node<std::uint_fast8_t>;
// Build a tree with 31 elements from 1 to 31 inclusive by adding new elements successively:
// 16
// / `
Expand All @@ -1017,13 +1017,13 @@ void testMutationManual()
// / ` / ` / ` / ` / ` / ` / ` / `
// 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31
std::array<N, 32> t{};
for (std::uint8_t i = 0; i < 32; i++)
for (std::uint_fast8_t i = 0; i < 32; i++)
{
t[i].value = i;
}
// Build the actual tree.
N* root = nullptr;
for (std::uint8_t i = 1; i < 32; i++)
for (std::uint_fast8_t i = 1; i < 32; i++)
{
const auto pred = [&](const N& v) { return t.at(i).value - v.value; };
TEST_ASSERT(nullptr == search(&root, pred));
Expand Down Expand Up @@ -1276,16 +1276,16 @@ void testMutationManual()

auto getRandomByte()
{
return static_cast<std::uint8_t>((0xFFLL * std::rand()) / RAND_MAX);
return static_cast<std::uint_fast8_t>((0xFFLL * std::rand()) / RAND_MAX);
}

void testMutationRandomized()
{
using N = Node<std::uint8_t>;
using N = Node<std::uint_fast8_t>;
std::array<N, 256> t{};
for (auto i = 0U; i < 256U; i++)
{
t.at(i).value = static_cast<std::uint8_t>(i);
t.at(i).value = static_cast<std::uint_fast8_t>(i);
}
std::array<bool, 256> mask{};
std::size_t size = 0;
Expand All @@ -1307,7 +1307,7 @@ void testMutationRandomized()
};
validate();

const auto add = [&](const std::uint8_t x) {
const auto add = [&](const std::uint_fast8_t x) {
const auto predicate = [&](const N& v) { return x - v.value; };
if (N* const existing = search(&root, predicate))
{
Expand All @@ -1332,7 +1332,7 @@ void testMutationRandomized()
}
};

const auto drop = [&](const std::uint8_t x) {
const auto drop = [&](const std::uint_fast8_t x) {
const auto predicate = [&](const N& v) { return x - v.value; };
if (N* const existing = search(&root, predicate))
{
Expand Down
Loading