/* ---------------------------------------------------------------------------- * Copyright (c) Huawei Technologies Co., Ltd. 2013-2019. All rights reserved. * Description: Doubly linked list * Author: Huawei LiteOS Team * Create: 2013-01-01 * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * 3. Neither the name of the copyright holder nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior written * permission. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ /** * @defgroup los_list Doubly linked list * @ingroup kernel */ #ifndef _LOS_LIST_H #define _LOS_LIST_H #include "los_typedef.h" #ifdef __cplusplus #if __cplusplus extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ /** * @ingroup los_list * Structure of a node in a doubly linked list. */ typedef struct LOS_DL_LIST { struct LOS_DL_LIST *pstPrev; /**< Current node's pointer to the previous node */ struct LOS_DL_LIST *pstNext; /**< Current node's pointer to the next node */ } LOS_DL_LIST; /*这种结构体通常用于实现双向链表数据结构。 通过在每个节点中嵌入LOS_DL_LIST结构体, 可以将多个节点连接起来形成链表。 */ /** * @ingroup los_list * @brief Initialize the input node to a doubly linked list. * * @par Description: * This API is used to initialize the input node (the first parameter list) to * a doubly linked list. * @attention * The parameter passed in should be a legal pointer. * * @param list [IN] A node in a doubly linked list. * * @retval None. * @par Dependency: * * @see LOS_DL_LIST_HEAD * @since Huawei LiteOS V100R001C00 */ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list) { list->pstNext = list; list->pstPrev = list; } /*这段代码定义了一个静态内联函数LOS_ListInit, 该函数接受一个指向LOS_DL_LIST结构体的指针list作为参数,没有返回值。 函数的作用是将传入的链表初始化为空,即将链表头节点的pstNext和pstPrev指 针都指向头节点本身,表示链表中没有其他节点。*/ /** * @ingroup los_list * @brief Point to the next node of the current node. * * @par Description: * This API is used to point to the next node of the current node. * @attention * None. * * @param object [IN] Type #LOS_DL_LIST * The node in the doubly linked list. * * @retval None. * @par Dependency: * * @see LOS_DL_LIST_LAST * @since Huawei LiteOS V100R001C00 */ #define LOS_DL_LIST_FIRST(object) ((object)->pstNext) /*这段代码定义了一个宏LOS_DL_LIST_FIRST(object), 它接受一个指向LOS_DL_LIST结构体的指针object作为参数, 并返回object指向的节点的下一个节点的指针,即链表中的第一个节点。 这个宏的作用是方便地获取链表中的第一个节点,通过宏展开后, 可以直接访问链表头节点的下一个节点。*/ /** * @ingroup los_list * @brief Point to the previous node of the current node. * * @par Description: * This API is used to point to the previous node of the current node. * @attention * None. * * @param object [IN] Type #LOS_DL_LIST * The node in the doubly linked list. * * @retval None. * @par Dependency: * * @see LOS_DL_LIST_FIRST * @since Huawei LiteOS V100R001C00 */ #define LOS_DL_LIST_LAST(object) ((object)->pstPrev) /*这段代码是一个宏定义,用于获取双向链表中指定节点的前一个节点。 在这里,传入的参数 object 是一个指向双向链表节点的指针, pstPrev 是该节点中指向前一个节点的指针。 该宏的功能是返回指定节点的前一个节点的指针。*/ /** * @ingroup los_list * @brief Insert a new node to a doubly linked list. * * @par Description: * This API is used to insert a new node after the list node to a doubly linked list. * @attention * The parameters passed in should be legal pointers. * * @param list [IN] Doubly linked list which the new node will be inserted in. * @param node [IN] The new node to be inserted. * * @retval None * @par Dependency: * * @see LOS_ListDelete | LOS_ListTailInsert | LOS_ListHeadInsert * @since Huawei LiteOS V100R001C00 */ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListAdd(LOS_DL_LIST *list, LOS_DL_LIST *node) { node->pstNext = list->pstNext; node->pstPrev = list; list->pstNext->pstPrev = node; list->pstNext = node; } /*该函数将新节点插入到链表头部,具体步骤如下: 把新节点的 next 指针指向链表头部的下一个节点。 把新节点的 prev 指针指向链表头部。 把原链表头部的下一个节点的 prev 指针指向新节点。 把链表头部的 next 指针指向新节点。 通过这些步骤,新节点就被成功地添加到了链表头部。*/ /** * @ingroup los_list * @brief Insert a node to a doubly linked list. * * @par Description: * This API is used to insert a new node before the list node to a doubly linked list. * @attention * The parameters passed in should be legal pointers. * * @param list [IN] Doubly linked list which the new node will be inserted in. * @param node [IN] The new node to be inserted. * * @retval None. * @par Dependency: * * @see LOS_ListAdd | LOS_ListHeadInsert * @since Huawei LiteOS V100R001C00 */ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListTailInsert(LOS_DL_LIST *list, LOS_DL_LIST *node) { LOS_ListAdd(list->pstPrev, node); } /*在该函数中,使用了宏定义 LOS_DL_LIST 来表示链表节点, 使用了 STATIC INLINE 关键字来定义内联函数,以提高代码执行效率。 函数的实现非常简单,只需调用双向链表的插入操作 LOS_ListAdd, 将新节点添加到链表头部的前一个节点即可。*/ /** * @ingroup los_list * @brief Insert a node to a doubly linked list. * * @par Description: * This API is used to insert a new node after the list node to a doubly linked list. * It is same with #LOS_ListAdd. * @attention * The parameters passed in should be legal pointers. * * @param list [IN] Doubly linked list which the new node will be inserted in. * @param node [IN] The new node to be inserted. * * @retval None. * @par Dependency: * * @see LOS_ListAdd | LOS_ListTailInsert * @since Huawei LiteOS V100R001C00 */ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListHeadInsert(LOS_DL_LIST *list, LOS_DL_LIST *node) { LOS_ListAdd(list, node); } /** * @ingroup los_list * @brief Delete a specified node from a doubly linked list. * * @par Description: * This API is used to delete a specified node from a doubly linked list. * @attention * The parameter passed in should be a legal pointer. * * @param node [IN] Node to be deleted. * * @retval None. * @par Dependency: * * @see LOS_ListAdd * @since Huawei LiteOS V100R001C00 */ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelete(LOS_DL_LIST *node) { node->pstNext->pstPrev = node->pstPrev; node->pstPrev->pstNext = node->pstNext; node->pstNext = NULL; node->pstPrev = NULL; } /*该函数的实现非常简单,具体步骤如下: 把被删除节点的 next 节点的 prev 指针指向被删除节点的 prev 节点。 把被删除节点的 prev 节点的 next 指针指向被删除节点的 next 节点。 清空被删除节点的 next 指针和 prev 指针。 通过这些步骤,被指定的节点就从链表中被成功地删除了。*/ /** * @ingroup los_list * @brief Identify whether a specified doubly linked list is empty or not. * * @par Description: * This API is used to judge whether a doubly linked list is empty or not. It * returns a Boolean value. * @attention * The parameter passed in should be a legal pointer. * * @param list [IN] Doubly linked list. * * @retval #TRUE The doubly linked list is empty. * @retval #FALSE The doubly linked list is not empty. * @par Dependency: * * @since Huawei LiteOS V100R001C00 */ LITE_OS_SEC_ALW_INLINE STATIC INLINE BOOL LOS_ListEmpty(LOS_DL_LIST *list) { return (BOOL)(list->pstNext == list); } /*具体步骤如下: 判断链表头部的 pstNext 指针是否等于链表头部本身。 如果相等,返回 TRUE(表示链表为空)。 如果不相等,返回 FALSE(表示链表不为空)。 通过这些步骤,可以判断链表是否为空。*/ /** * @ingroup los_list * @brief Obtain the offset of a structure member relative to the structure start address. * * @par Description: * This API is used to obtain the offset of the structure member (member) relative to * the start address of the structure (type). And return the offset of #UINTPTR type. * @attention * None. * * @param type [IN] Structure name. * @param member [IN] The structure member name which needs to measure the offset. * * @retval #UINTPTR Offset of the member relative to the structure start address. * @par Dependency: * * @since Huawei LiteOS V100R001C00 */ #define LOS_OFF_SET_OF(type, member) ((UINTPTR)&((type *)0)->member) /* Obsolete API, please use LOS_OFF_SET_OF instead */ #define OFFSET_OF_FIELD(type, field) LOS_OFF_SET_OF(type, field) /*这些宏的作用是帮助程序员在编写代码时可以方便地获取结构体成员的偏移量。 通常情况下,结构体成员的偏移量用于在程序中进行内存操作, 比如根据结构体的指针和成员的偏移量, 可以获取到该成员的地址或修改该成员的值。*/ /** * @ingroup los_list * @brief Obtain the pointer to a structure that contains a doubly linked list. * * @par Description: * This API is used to obtain the pointer to a structure that contains the doubly * linked list which the first parameter item specified. * @attention * None. * * @param item [IN] Type #LOS_DL_LIST * The node of the doubly linked list. * @param type [IN] Structure name. * @param member [IN] The doubly linked list name in the structure. * * @retval The pointer to the structure that contains the doubly linked list. And * the doubly linked list has the node of the first parameter item. * @par Dependency: * * @see LOS_DL_LIST_FOR_EACH_ENTRY | LOS_DL_LIST_FOR_EACH_ENTRY_SAFE * @since Huawei LiteOS V100R001C00 */ #define LOS_DL_LIST_ENTRY(item, type, member) \ ((type *)(VOID *)((CHAR *)(item) - LOS_OFF_SET_OF(type, member))) /** * @ingroup los_list * @brief Traverse a doubly linked list which is included in a given type structure. * * @par Description: * This API is used to traverse a doubly linked list which is included in a given type * structure. The API is a loop. The start node of the doubly linked list is the second * parameter list. And in each loop, the obtained pointer to a structure that contains * the list is outputted in the first parameter item. * @attention * None. * * @param item [IN/OUT] The pointer to the structure that contains the doubly linked list. * @param list [IN] Type #LOS_DL_LIST * The start node of the doubly linked list to * be traversed. * @param type [IN] Structure name. * @param member [IN] The doubly linked list name in the structure. * * @retval None. * @par Dependency: * * @see LOS_DL_LIST_ENTRY | LOS_DL_LIST_FOR_EACH_ENTRY_SAFE | LOS_DL_LIST_FOR_EACH * @since Huawei LiteOS V100R001C00 */ #define LOS_DL_LIST_FOR_EACH_ENTRY(item, list, type, member) \ for (item = LOS_DL_LIST_ENTRY((list)->pstNext, type, member); \ &(item)->member != (list); \ item = LOS_DL_LIST_ENTRY((item)->member.pstNext, type, member)) /*宏的实现通过 for 循环来实现链表的遍历,具体步骤如下: 首先使用 LOS_DL_LIST_ENTRY 宏获取链表头部节点的指针,并将其赋值给 item 变量,从而初始化遍历的起始位置。 接着判断条件 &(item)->member != (list),当遍历到链表末尾时,即链表头部时结束遍历,否则继续循环。 在循环体内,执行对当前节点的操作,并使用 LOS_DL_LIST_ENTRY 宏获取下一个节点的指针,从而实现链表的顺序遍历。 通过这些步骤,可以方便地遍历双向链表中的每个节点,并对每个节点执行相应的操作。*/ /** * @ingroup los_list * @brief Traverse a doubly linked list which is included in a given type structure. And * it is safe against removal of list entry. * * @par Description: * This API is used to traverse a doubly linked list which is included in a given type * structure. The API is a loop. The start node of the doubly linked list is the third * parameter list. And in each loop, the obtained pointer to a structure that contains * the list is outputted in the first parameter item. And the next node is outputted in * the second parameter next. * @attention * None. * * @param item [IN/OUT] The pointer to the structure that contains the doubly linked list. * @param next [IN/OUT] The pointer to the structure that contains the next node of the * doubly linked list. * @param list [IN] Type #LOS_DL_LIST * The start node of the doubly linked list to * be traversed. * @param type [IN] Structure name. * @param member [IN] The doubly linked list name in the structure. * * @retval None. * @par Dependency: * * @see LOS_DL_LIST_ENTRY | LOS_DL_LIST_FOR_EACH_ENTRY | LOS_DL_LIST_FOR_EACH_SAFE * @since Huawei LiteOS V100R001C00 */ #define LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, next, list, type, member) \ for (item = LOS_DL_LIST_ENTRY((list)->pstNext, type, member), \ next = LOS_DL_LIST_ENTRY((item)->member.pstNext, type, member); \ &(item)->member != (list); \ item = next, next = LOS_DL_LIST_ENTRY((item)->member.pstNext, type, member)) /*该宏的功能是按顺序遍历链表中的每个节点,并对每个节点执行指定的操作。其参数包括: item:表示当前遍历到的节点 next:表示下一个节点的指针 list:表示链表的头部 type:表示链表节点所在的结构体类型 member:表示链表节点在结构体中的成员名*/ /** * @ingroup los_list * @brief Iterate over a doubly linked list of given type, and call hook for any extra procedures every time. * * @par Description: * This API is used to iterate over a doubly linked list of given type, * and call hook for any extra procedures every time. * @attention * None. * * @param item [IN/OUT] Pointer to the structure that contains the doubly linked list that is to be traversed. * @param list [IN] Pointer to the doubly linked list to be traversed. * @param type [IN] Structure name. * @param member [IN] Member name of the doubly linked list in the structure. * @param hook [IN] Hook for extra procedures which will be called every time when dev is fetched. * * @retval None. * @par Dependency: * * @see LOS_DL_LIST_ENTRY | LOS_DL_LIST_FOR_EACH_ENTRY * @since Huawei LiteOS V200R005C10 */ #define LOS_DL_LIST_FOR_EACH_ENTRY_HOOK(item, list, type, member, hook) \ for (item = LOS_DL_LIST_ENTRY((list)->pstNext, type, member), hook; \ &(item)->member != (list); \ item = LOS_DL_LIST_ENTRY((item)->member.pstNext, type, member), hook) /*该宏的功能是按顺序遍历链表中的每个节点,并在每个节点遍历之前执行指定的钩子函数。其参数包括: item:表示当前遍历到的节点 list:表示链表的头部 type:表示链表节点所在的结构体类型 member:表示链表节点在结构体中的成员名 hook:表示要执行的钩子函数*/ /** * @ingroup los_list * @brief Delete a specified node from a doubly linked list and reinitialize the node. * * @par Description: * This API is used to delete a specified node (the first parameter list) from the doubly * linked list. And reinitialize the deleted node to a doubly linked list. * * @attention * The parameter passed in should be a legal pointer. * * @param list [IN] Node to be deleted and reinitialize to a doubly linked list. * * @retval None. * @par Dependency: * * @see LOS_ListInit | LOS_ListDelete * @since Huawei LiteOS V100R001C00 */ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelInit(LOS_DL_LIST *list) { list->pstNext->pstPrev = list->pstPrev; list->pstPrev->pstNext = list->pstNext; LOS_ListInit(list); } /**/ /** * @ingroup los_list * @brief Traverse a doubly linked list. * * @par Description: * This API is used to traverse a doubly linked list. The API is a loop. The start node of the * doubly linked list is the second parameter list. And in each loop, the obtained pointer to * the next node of the doubly linked list is outputted in the first parameter item. * @attention * None. * * @param item [IN/OUT] Type #LOS_DL_LIST * The pointer to the next node in the doubly * linked list. * @param list [IN] Type #LOS_DL_LIST * The pointer to the node of the doubly linked * list to be traversed. * * @retval None. * @par Dependency: * * @see LOS_DL_LIST_FOR_EACH_SAFE | LOS_DL_LIST_FOR_EACH_ENTRY * @since Huawei LiteOS V100R001C00 */ #define LOS_DL_LIST_FOR_EACH(item, list) \ for (item = (list)->pstNext; \ (item) != (list); \ item = (item)->pstNext) /*宏的实现通过 for 循环来实现链表的遍历,具体步骤如下: 在循环初始化部分,将 item 初始化为链表头部节点的下一个节点,即 (list)->pstNext。 在循环条件中,判断条件 (item) != (list),当 item 等于链表头部时,即遍历到链表末尾时结束遍历,否则继续循环。 在每次循环结束之后,将 item 更新为下一个节点的指针,即 (item)->pstNext。 通过这些步骤,可以方便地遍历双向链表中的每个节点,并在循环体内对每个节点执行指定的操作。*/ /** * @ingroup los_list * @brief Traverse a doubly linked list safe against removal of list entry. * * @par Description: * This API is used to traverse a doubly linked list safe against removal of list entry. The * API is a loop. The start node of the doubly linked list is the third parameter list. And * in each loop, the obtained pointer to the next node of the doubly linked list is outputted * in the first parameter item. And the next node of the the node specified by first parameter * item is outputted in the second parameter next. * @attention * None. * * @param item [IN/OUT] Type #LOS_DL_LIST * The pointer to the next node in the doubly * linked list. * @param next [IN/OUT] Type #LOS_DL_LIST * The pointer to the next node of the the node * specified by first parameter item. * @param list [IN] Type #LOS_DL_LIST * The pointer to the node of the doubly linked * list to be traversed. * * @retval None. * @par Dependency: * * @see LOS_DL_LIST_FOR_EACH | LOS_DL_LIST_FOR_EACH_ENTRY_SAFE * @since Huawei LiteOS V100R001C00 */ #define LOS_DL_LIST_FOR_EACH_SAFE(item, next, list) \ for (item = (list)->pstNext, next = (item)->pstNext; \ (item) != (list); \ item = next, next = (item)->pstNext) /** * @ingroup los_list * @brief Initialize a double linked list. * * @par Description: * This API is used to initialize the input node (the parameter list) to a double linked * list. The difference with LOS_ListInit is that the parameter list is not a pointer while * in LOS_ListInit it is a pointer. * @attention * None. * * @param list [IN] Type #LOS_DL_LIST A node to be initialized to a doubly linked list. * * @retval None. * @par Dependency: * * @see LOS_ListInit * @since Huawei LiteOS V100R001C00 */ #define LOS_DL_LIST_HEAD(list) LOS_DL_LIST list = { &(list), &(list) } /*通过这个宏,可以方便地定义和初始化一个双向链表的头部节点,为链表的后续操作提供了便利。*/ #ifdef __cplusplus #if __cplusplus } #endif /* __cplusplus */ #endif /* __cplusplus */ #endif /* _LOS_LIST_H */