Skip to content

Commit

Permalink
core/lib/cib: add several new peek functions
Browse files Browse the repository at this point in the history
This patch adds calls to be able to peek at items other than just the
oldest item in a cib based FIFO. It also adds an "unsafe" peek to match
the existing "unsafe" put and get functions.
  • Loading branch information
Enoch247 committed Mar 18, 2024
1 parent 45752a3 commit b648165
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 5 deletions.
65 changes: 60 additions & 5 deletions core/lib/include/cib.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,21 +120,76 @@ static inline int cib_get(cib_t *__restrict cib)
}

/**
* @brief Get the index of the next item in buffer without removing it.
* @brief Get the index of an item in the buffer without removing anything.
*
* Offset 0 is the next item in the buffer that would be returned by
* `cip_get()`, offset 1 would be the following, and so on.
*
* Unsafe version, *must not* pass an offset that is larger than the number of
* items currently in the buffer!
*
* @param[in,out] cib corresponding *cib* to buffer.
* Must not be NULL.
* @return index of next item, -1 if the buffer is empty
* @param[in] offset offset from front of buffer
*
* @return index of item
* @retval -1 if no item at @p offset exists in the buffer
*/
static inline int cib_peek(cib_t *__restrict cib)
static inline int cib_peek_at_unsafe(cib_t *__restrict cib, unsigned offset)
{
if (cib_avail(cib)) {
return (int)(cib->read_count & cib->mask);
return (cib->read_count + offset) & cib->mask;
}

/**
* @brief Get the index of an item in the buffer without removing anything.
*
* Offset 0 is the next item in the buffer that would be returned by
* `cip_get()`, offset 1 would be the following, and so on.
*
* @param[in,out] cib corresponding *cib* to buffer.
* Must not be NULL.
* @param[in] offset offset from front of buffer
*
* @return index of item
* @retval -1 if no item at @p offset exists in the buffer
*/
static inline int cib_peek_at(cib_t *__restrict cib, unsigned offset)
{
if (offset < cib_avail(cib)) {
return cib_peek_at_unsafe(cib, offset);
}

return -1;
}

/**
* @brief Get the index of the next item in buffer without removing it.
*
* Unsafe version, *must not* be called if buffer is empty!
*
* @param[in,out] cib corresponding *cib* to buffer.
* Must not be NULL.
* @return index of next item
* @retval -1 if the buffer is empty
*/
static inline int cib_peek_unsafe(cib_t *__restrict cib)
{
return cib_peek_at_unsafe(cib, 0);
}

/**
* @brief Get the index of the next item in buffer without removing it.
*
* @param[in,out] cib corresponding *cib* to buffer.
* Must not be NULL.
* @return index of next item
* @retval -1 if the buffer is empty
*/
static inline int cib_peek(cib_t *__restrict cib)
{
return cib_peek_at(cib, 0);
}

/**
* @brief Get the index of the next item in buffer.
*
Expand Down
78 changes: 78 additions & 0 deletions tests/unittests/tests-core/tests-core-cib.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,83 @@ static void test_cib_peek__overflow(void)
TEST_ASSERT_EQUAL_INT(TEST_CIB_SIZE-1, cib_peek(&cib));
}

static void test_cib_peek_at(void)
{
/* Peeking an empty cib should give an error */
TEST_ASSERT_EQUAL_INT(-1, cib_peek_at(&cib, 0));

/* Put 1 item in cib and check that we can peek it */
TEST_ASSERT_EQUAL_INT( 0, cib_put(&cib));
TEST_ASSERT_EQUAL_INT( 0, cib_peek(&cib));
TEST_ASSERT_EQUAL_INT( 0, cib_peek_at(&cib, 0));

/* Peek past the end should give an error. */
TEST_ASSERT_EQUAL_INT(-1, cib_peek_at(&cib, 1));

/* Put another item in cib. */
TEST_ASSERT_EQUAL_INT( 1, cib_put(&cib));

/* cib should now hold the indices { 0, 1 }. Test this. */
TEST_ASSERT_EQUAL_INT( 0, cib_peek(&cib));
TEST_ASSERT_EQUAL_INT( 0, cib_peek_at(&cib, 0));
TEST_ASSERT_EQUAL_INT( 1, cib_peek_at(&cib, 1));
TEST_ASSERT_EQUAL_INT(-1, cib_peek_at(&cib, 2));

/* Put another item in cib. */
TEST_ASSERT_EQUAL_INT( 2, cib_put(&cib));

/* cib should now hold the indices { 0, 1, 2 }. Test this. */
TEST_ASSERT_EQUAL_INT( 0, cib_peek(&cib));
TEST_ASSERT_EQUAL_INT( 0, cib_peek_at(&cib, 0));
TEST_ASSERT_EQUAL_INT( 1, cib_peek_at(&cib, 1));
TEST_ASSERT_EQUAL_INT( 2, cib_peek_at(&cib, 2));
TEST_ASSERT_EQUAL_INT(-1, cib_peek_at(&cib, 3));

/* Put another item in cib. */
TEST_ASSERT_EQUAL_INT( 3, cib_put(&cib));

/* cib should now hold the indices { 0, 1, 2, 3 }. Test this. */
TEST_ASSERT_EQUAL_INT( 0, cib_peek(&cib));
TEST_ASSERT_EQUAL_INT( 0, cib_peek_at(&cib, 0));
TEST_ASSERT_EQUAL_INT( 1, cib_peek_at(&cib, 1));
TEST_ASSERT_EQUAL_INT( 2, cib_peek_at(&cib, 2));
TEST_ASSERT_EQUAL_INT( 3, cib_peek_at(&cib, 3));
TEST_ASSERT_EQUAL_INT(-1, cib_peek_at(&cib, 4));

/* Remove an item from cib. */
TEST_ASSERT_EQUAL_INT( 0, cib_get(&cib));

/* cib should now hold the indices { 1, 2, 3 }. Test this. */
TEST_ASSERT_EQUAL_INT( 1, cib_peek(&cib));
TEST_ASSERT_EQUAL_INT( 1, cib_peek_at(&cib, 0));
TEST_ASSERT_EQUAL_INT( 2, cib_peek_at(&cib, 1));
TEST_ASSERT_EQUAL_INT( 3, cib_peek_at(&cib, 2));
TEST_ASSERT_EQUAL_INT(-1, cib_peek_at(&cib, 3));

/* Remove another item from cib. */
TEST_ASSERT_EQUAL_INT( 1, cib_get(&cib));

/* cib should now hold the indices { 2, 3 }. Test this. */
TEST_ASSERT_EQUAL_INT( 2, cib_peek(&cib));
TEST_ASSERT_EQUAL_INT( 2, cib_peek_at(&cib, 0));
TEST_ASSERT_EQUAL_INT( 3, cib_peek_at(&cib, 1));
TEST_ASSERT_EQUAL_INT(-1, cib_peek_at(&cib, 2));

/* Remove another item from cib. */
TEST_ASSERT_EQUAL_INT( 2, cib_get(&cib));

/* cib should now hold the indices { 3 }. Test this. */
TEST_ASSERT_EQUAL_INT( 3, cib_peek(&cib));
TEST_ASSERT_EQUAL_INT( 3, cib_peek_at(&cib, 0));
TEST_ASSERT_EQUAL_INT(-1, cib_peek_at(&cib, 1));

/* Remove last item from cib. */
TEST_ASSERT_EQUAL_INT( 3, cib_get(&cib));

/* Peeking an empty cib should give an error */
TEST_ASSERT_EQUAL_INT(-1, cib_peek_at(&cib, 0));
}

static void test_cib_avail(void)
{
TEST_ASSERT_EQUAL_INT(0, cib_avail(&cib));
Expand Down Expand Up @@ -111,6 +188,7 @@ Test *tests_core_cib_tests(void)
new_TestFixture(test_singleton_cib),
new_TestFixture(test_cib_peek),
new_TestFixture(test_cib_peek__overflow),
new_TestFixture(test_cib_peek_at),
};

EMB_UNIT_TESTCALLER(core_cib_tests, set_up, NULL, fixtures);
Expand Down

0 comments on commit b648165

Please sign in to comment.