2 * Amazon FreeRTOS Common V1.0.0
\r
3 * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 * http://aws.amazon.com/freertos
\r
23 * http://www.FreeRTOS.org
\r
27 * @file iot_doubly_linked_list.h
\r
28 * @brief Doubly Linked List implementation.
\r
30 * A generic implementation of circular Doubly Linked List which consists of a
\r
31 * list head and some list entries (zero in case of an empty list).
\r
33 * To start with, a structure of type Link_t should be embedded in the structure
\r
34 * which is to be organized as doubly linked list.
\r
36 * typedef struct UserStruct
\r
38 * uint32_t ulField1;
\r
39 * uint32_t ulField2;
\r
44 * A List head should then be defined and initialized.
\r
47 * listINIT_HEAD( &xListHead );
\r
50 * listADD can then be used to add nodes to the list.
\r
52 * listADD( &( xListHead ), &( pxUserStruct->xLink ) );
\r
55 * listFOR_EACH can be used for traversing the list.
\r
58 * UserStruct_t *pxUserStruct;
\r
59 * listFOR_EACH( pxLink, &( xListHead ) )
\r
61 * pxUserStruct = listCONTAINER( pxLink, UserStruct_t, xLink );
\r
65 * listFOR_EACH_SAFE should be used if you want to perform destructive operations
\r
66 * (like free) on nodes while traversing the list.
\r
68 * Link_t *pxLink, *pxTempLink;
\r
69 * UserStruct_t *pxUserStruct;
\r
70 * listFOR_EACH( pxLink, pxTempLink, &( xListHead ) )
\r
72 * pxUserStruct = listCONTAINER( pxLink, UserStruct_t, xLink );
\r
73 * free( pxUserStruct );
\r
78 #ifndef _AWS_DOUBLY_LINKED_LIST_H_
\r
79 #define _AWS_DOUBLY_LINKED_LIST_H_
\r
85 * @brief Struct embedded in any struct to make it a doubly linked
\r
88 * pxNext in the head points to the first node in the list and pxPrev
\r
89 * in the head points to the last node in the list. In case of empty
\r
90 * list, both pxPrev and pxNext in the head point to the head node itself.
\r
94 struct Link * pxPrev; /**< Pointer to the previous node. */
\r
95 struct Link * pxNext; /**< Pointer to the next node. */
\r
99 * @brief Initializes the given list head to an empty list.
\r
101 * @param[in] pxHead The given list head to initialize.
\r
103 #define listINIT_HEAD( pxHead ) \
\r
105 ( pxHead )->pxPrev = ( pxHead ); \
\r
106 ( pxHead )->pxNext = ( pxHead ); \
\r
110 * @brief Adds the given new node to the given list.
\r
112 * @param[in] pxHead The head of the given list.
\r
113 * @param[in] pxLink The given new node to be added to the given
\r
116 #define listADD( pxHead, pxLink ) \
\r
118 Link_t * pxPrevLink = ( pxHead ); \
\r
119 Link_t * pxNextLink = ( ( pxHead )->pxNext ); \
\r
121 ( pxLink )->pxNext = pxNextLink; \
\r
122 pxNextLink->pxPrev = ( pxLink ); \
\r
123 pxPrevLink->pxNext = ( pxLink ); \
\r
124 ( pxLink )->pxPrev = ( pxPrevLink ); \
\r
128 * @brief Removes the given node from the list it is part of.
\r
130 * If the given node is not a part of any list (i.e. next and previous
\r
131 * nodes are NULL), nothing happens.
\r
133 * @param[in] pxLink The given node to remove from the list.
\r
135 #define listREMOVE( pxLink ) \
\r
137 /* If the link is part of a list, remove it from the list. */ \
\r
138 if( ( pxLink )->pxNext != NULL && ( pxLink )->pxPrev != NULL ) \
\r
140 ( pxLink )->pxPrev->pxNext = ( pxLink )->pxNext; \
\r
141 ( pxLink )->pxNext->pxPrev = ( pxLink )->pxPrev; \
\r
144 /* Make sure that this link is not part of any list anymore. */ \
\r
145 ( pxLink )->pxPrev = NULL; \
\r
146 ( pxLink )->pxNext = NULL; \
\r
150 * @brief Given the head of a list, checks if the list is empty.
\r
152 * @param[in] pxHead The head of the given list.
\r
154 #define listIS_EMPTY( pxHead ) ( ( ( pxHead ) == NULL ) || ( ( pxHead )->pxNext == ( pxHead ) ) )
\r
157 * @brief Removes the first node from the given list and returns it.
\r
159 * Removes the first node from the given list and assigns it to the
\r
160 * pxLink parameter. If the list is empty, it assigns NULL to the
\r
163 * @param[in] pxHead The head of the list from which to remove the
\r
165 * @param[out] pxLink The output parameter to receive the removed
\r
168 #define listPOP( pxHead, pxLink ) \
\r
170 if( listIS_EMPTY( ( pxHead ) ) ) \
\r
172 ( pxLink ) = NULL; \
\r
176 ( pxLink ) = ( pxHead )->pxNext; \
\r
177 /* If the link is part of a list, remove it from the list. */ \
\r
178 if( ( pxLink )->pxNext != NULL && ( pxLink )->pxPrev != NULL ) \
\r
180 ( pxLink )->pxPrev->pxNext = ( pxLink )->pxNext; \
\r
181 ( pxLink )->pxNext->pxPrev = ( pxLink )->pxPrev; \
\r
184 /* Make sure that this link is not part of any list anymore. */ \
\r
185 ( pxLink )->pxPrev = NULL; \
\r
186 ( pxLink )->pxNext = NULL; \
\r
191 * @brief Merges a list into a given list.
\r
193 * @param[in] pxHeadResultList The head of the given list into which the
\r
194 * other list should be merged.
\r
195 * @param[in] pxHeadListToMerge The head of the list to be merged into the
\r
198 #define listMERGE( pxHeadResultList, pxHeadListToMerge ) \
\r
200 if( !listIS_EMPTY( ( pxHeadListToMerge ) ) ) \
\r
202 /* Setup links between last node of listToMerge and first node of resultList. */ \
\r
203 ( pxHeadListToMerge )->pxPrev->pxNext = ( pxHeadResultList )->pxNext; \
\r
204 ( pxHeadResultList )->pxNext->pxPrev = ( pxHeadListToMerge )->pxPrev; \
\r
206 /* Setup links between first node of listToMerge and the head of resultList. */ \
\r
207 ( pxHeadListToMerge )->pxNext->pxPrev = ( pxHeadResultList ); \
\r
208 ( pxHeadResultList )->pxNext = ( pxHeadListToMerge )->pxNext; \
\r
209 /* Empty the merged list. */ \
\r
210 listINIT_HEAD( ( pxHeadListToMerge ) ); \
\r
215 * @brief Helper macro to iterate over a list. pxLink contains the link node
\r
216 * in each iteration.
\r
218 #define listFOR_EACH( pxLink, pxHead ) \
\r
219 for( ( pxLink ) = ( pxHead )->pxNext; \
\r
220 ( pxLink ) != ( pxHead ); \
\r
221 ( pxLink ) = ( pxLink )->pxNext )
\r
224 * @brief Helper macro to iterate over a list. It is safe to destroy/free the
\r
225 * nodes while iterating. pxLink contains the link node in each iteration.
\r
227 #define listFOR_EACH_SAFE( pxLink, pxTempLink, pxHead ) \
\r
228 for( ( pxLink ) = ( pxHead )->pxNext, ( pxTempLink ) = ( pxLink )->pxNext; \
\r
229 ( pxLink ) != ( pxHead ); \
\r
230 ( pxLink ) = ( pxTempLink ), ( pxTempLink ) = ( pxLink )->pxNext )
\r
233 * @brief Given the pointer to the link member (of type Link_t) in a struct,
\r
234 * extracts the pointer to the containing struct.
\r
236 * @param[in] pxLink The pointer to the link member.
\r
237 * @param[in] type The type of the containing struct.
\r
238 * @param[in] member Name of the link member in the containing struct.
\r
240 #define listCONTAINER( pxLink, type, member ) ( ( type * ) ( ( uint8_t * ) ( pxLink ) - ( uint8_t * ) ( &( ( type * ) 0 )->member ) ) )
\r
242 #endif /* _AWS_DOUBLY_LINKED_LIST_H_ */
\r