Add custom pm sysmodule
This commit is contained in:
86
sysmodules/pm/source/intrusive_list.h
Normal file
86
sysmodules/pm/source/intrusive_list.h
Normal file
@@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/// Intrusive node structure definition.
|
||||
typedef struct IntrusiveNode {
|
||||
struct IntrusiveNode *prev; ///< Pointer to the previous node.
|
||||
struct IntrusiveNode *next; ///< Pointer to the next node.
|
||||
} IntrusiveNode;
|
||||
|
||||
/// Intrusive list structure definition.
|
||||
typedef union IntrusiveList {
|
||||
IntrusiveNode node;
|
||||
struct {
|
||||
IntrusiveNode *last; ///< Pointer to the last element.
|
||||
IntrusiveNode *first; ///< Pointer to the first element.
|
||||
};
|
||||
} IntrusiveList;
|
||||
|
||||
/**
|
||||
* @brief Initializes the intrusive linked list.
|
||||
*
|
||||
* @param ll The intrusive list to initialize.
|
||||
*/
|
||||
static inline void IntrusiveList_Init(IntrusiveList *ll)
|
||||
{
|
||||
ll->node.prev = &ll->node;
|
||||
ll->node.next = &ll->node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tests if a node is past the end of the list containing it (if any).
|
||||
*
|
||||
* @param nd The node to test.
|
||||
* @return bool true iff node is past the end of the list.
|
||||
*/
|
||||
static inline bool IntrusiveList_TestEnd(const IntrusiveList *ll, const IntrusiveNode *nd)
|
||||
{
|
||||
return nd == &ll->node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts a node after another one list.
|
||||
*
|
||||
* @param pos The node to insert the new node after.
|
||||
* @param nd The new node.
|
||||
*/
|
||||
static inline void IntrusiveList_InsertAfter(IntrusiveNode *pos, IntrusiveNode *nd)
|
||||
{
|
||||
// if pos is last & list is empty, ->next writes to first, etc.
|
||||
pos->next->prev = nd;
|
||||
nd->prev = pos;
|
||||
nd->next = pos->next;
|
||||
pos->next = nd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erases a node.
|
||||
*
|
||||
* @param nd The node to erase.
|
||||
*/
|
||||
static inline void IntrusiveList_Erase(const IntrusiveNode *nd)
|
||||
{
|
||||
nd->prev->next = nd->next;
|
||||
nd->next->prev = nd->prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Makes a list storage from a buffer, using each element's intrusive node field at offset 0.
|
||||
*
|
||||
* @param ll The intrusive list to create.
|
||||
* @param buf The buffer to use.
|
||||
* @param elem_size The size of each element.
|
||||
* @param total_size The total size of the buffer.
|
||||
*
|
||||
* @pre @ref ll has not been initialized yet.
|
||||
* @pre Each element must contain a @ref IntrusiveNode instance at offset 0, which is then used.
|
||||
*/
|
||||
static inline void IntrusiveList_CreateFromBuffer(IntrusiveList *ll, void *buf, size_t elemSize, size_t totalSize)
|
||||
{
|
||||
IntrusiveList_Init(ll);
|
||||
for (size_t pos = 0; pos < totalSize; pos += elemSize) {
|
||||
IntrusiveList_InsertAfter(ll->last, (IntrusiveNode *)((char *)buf + pos));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user