]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Labs/Demo/FreeRTOS_Plus_POSIX_with_actor_Windows_Simulator/lib/include/private/iot_doubly_linked_list.h
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Demo / FreeRTOS_Plus_POSIX_with_actor_Windows_Simulator / lib / include / private / iot_doubly_linked_list.h
diff --git a/FreeRTOS-Labs/Demo/FreeRTOS_Plus_POSIX_with_actor_Windows_Simulator/lib/include/private/iot_doubly_linked_list.h b/FreeRTOS-Labs/Demo/FreeRTOS_Plus_POSIX_with_actor_Windows_Simulator/lib/include/private/iot_doubly_linked_list.h
new file mode 100644 (file)
index 0000000..734dd8f
--- /dev/null
@@ -0,0 +1,242 @@
+/*\r
+ * Amazon FreeRTOS Common V1.0.0\r
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+/**\r
+ * @file iot_doubly_linked_list.h\r
+ * @brief Doubly Linked List implementation.\r
+ *\r
+ * A generic implementation of circular Doubly Linked List which consists of a\r
+ * list head and some list entries (zero in case of an empty list).\r
+ *\r
+ * To start with, a structure of type Link_t should be embedded in the structure\r
+ * which is to be organized as doubly linked list.\r
+ * @code\r
+ * typedef struct UserStruct\r
+ * {\r
+ *     uint32_t ulField1;\r
+ *     uint32_t ulField2;\r
+ *     Link_t xLink;\r
+ * } UserStruct_t;\r
+ * @endcode\r
+ *\r
+ * A List head should then be defined and initialized.\r
+ * @code\r
+ * Link_t xListHead;\r
+ * listINIT_HEAD( &xListHead );\r
+ * @endcode\r
+ *\r
+ * listADD can then be used to add nodes to the list.\r
+ * @code\r
+ * listADD( &( xListHead ), &( pxUserStruct->xLink ) );\r
+ * @endcode\r
+ *\r
+ * listFOR_EACH can be used for traversing the list.\r
+ * @code\r
+ * Link_t *pxLink;\r
+ * UserStruct_t *pxUserStruct;\r
+ * listFOR_EACH( pxLink, &( xListHead ) )\r
+ * {\r
+ *      pxUserStruct = listCONTAINER( pxLink, UserStruct_t, xLink );\r
+ * }\r
+ * @endcode\r
+ *\r
+ * listFOR_EACH_SAFE should be used if you want to perform destructive operations\r
+ * (like free) on nodes while traversing the list.\r
+ * @code\r
+ * Link_t *pxLink, *pxTempLink;\r
+ * UserStruct_t *pxUserStruct;\r
+ * listFOR_EACH( pxLink, pxTempLink, &( xListHead ) )\r
+ * {\r
+ *      pxUserStruct = listCONTAINER( pxLink, UserStruct_t, xLink );\r
+ *      free( pxUserStruct );\r
+ * }\r
+ * @endcode\r
+ */\r
+\r
+#ifndef _AWS_DOUBLY_LINKED_LIST_H_\r
+#define _AWS_DOUBLY_LINKED_LIST_H_\r
+\r
+#include <stddef.h>\r
+#include <stdint.h>\r
+\r
+/**\r
+ * @brief Struct embedded in any struct to make it a doubly linked\r
+ * list.\r
+ *\r
+ * pxNext in the head points to the first node in the list and pxPrev\r
+ * in the head points to the last node in the list. In case of empty\r
+ * list, both pxPrev and pxNext in the head point to the head node itself.\r
+ */\r
+typedef struct Link\r
+{\r
+    struct Link * pxPrev; /**< Pointer to the previous node. */\r
+    struct Link * pxNext; /**< Pointer to the next node. */\r
+} Link_t;\r
+\r
+/**\r
+ * @brief Initializes the given list head to an empty list.\r
+ *\r
+ * @param[in] pxHead The given list head to initialize.\r
+ */\r
+#define listINIT_HEAD( pxHead )          \\r
+    {                                    \\r
+        ( pxHead )->pxPrev = ( pxHead ); \\r
+        ( pxHead )->pxNext = ( pxHead ); \\r
+    }\r
+\r
+/**\r
+ * @brief Adds the given new node to the given list.\r
+ *\r
+ * @param[in] pxHead The head of the given list.\r
+ * @param[in] pxLink The given new node to be added to the given\r
+ * list.\r
+ */\r
+#define listADD( pxHead, pxLink )                     \\r
+    {                                                 \\r
+        Link_t * pxPrevLink = ( pxHead );             \\r
+        Link_t * pxNextLink = ( ( pxHead )->pxNext ); \\r
+                                                      \\r
+        ( pxLink )->pxNext = pxNextLink;              \\r
+        pxNextLink->pxPrev = ( pxLink );              \\r
+        pxPrevLink->pxNext = ( pxLink );              \\r
+        ( pxLink )->pxPrev = ( pxPrevLink );          \\r
+    }\r
+\r
+/**\r
+ * @brief Removes the given node from the list it is part of.\r
+ *\r
+ * If the given node is not a part of any list (i.e. next and previous\r
+ * nodes are NULL), nothing happens.\r
+ *\r
+ * @param[in] pxLink The given node to remove from the list.\r
+ */\r
+#define listREMOVE( pxLink )                                            \\r
+    {                                                                   \\r
+        /* If the link is part of a list, remove it from the list. */   \\r
+        if( ( pxLink )->pxNext != NULL && ( pxLink )->pxPrev != NULL )  \\r
+        {                                                               \\r
+            ( pxLink )->pxPrev->pxNext = ( pxLink )->pxNext;            \\r
+            ( pxLink )->pxNext->pxPrev = ( pxLink )->pxPrev;            \\r
+        }                                                               \\r
+                                                                        \\r
+        /* Make sure that this link is not part of any list anymore. */ \\r
+        ( pxLink )->pxPrev = NULL;                                      \\r
+        ( pxLink )->pxNext = NULL;                                      \\r
+    }\r
+\r
+/**\r
+ * @brief Given the head of a list, checks if the list is empty.\r
+ *\r
+ * @param[in] pxHead The head of the given list.\r
+ */\r
+#define listIS_EMPTY( pxHead )    ( ( ( pxHead ) == NULL ) || ( ( pxHead )->pxNext == ( pxHead ) ) )\r
+\r
+/**\r
+ * @brief Removes the first node from the given list and returns it.\r
+ *\r
+ * Removes the first node from the given list and assigns it to the\r
+ * pxLink parameter. If the list is empty, it assigns NULL to the\r
+ * pxLink.\r
+ *\r
+ * @param[in] pxHead The head of the list from which to remove the\r
+ * first node.\r
+ * @param[out] pxLink The output parameter to receive the removed\r
+ * node.\r
+ */\r
+#define listPOP( pxHead, pxLink )                                           \\r
+    {                                                                       \\r
+        if( listIS_EMPTY( ( pxHead ) ) )                                    \\r
+        {                                                                   \\r
+            ( pxLink ) = NULL;                                              \\r
+        }                                                                   \\r
+        else                                                                \\r
+        {                                                                   \\r
+            ( pxLink ) = ( pxHead )->pxNext;                                \\r
+            /* If the link is part of a list, remove it from the list. */   \\r
+            if( ( pxLink )->pxNext != NULL && ( pxLink )->pxPrev != NULL )  \\r
+            {                                                               \\r
+                ( pxLink )->pxPrev->pxNext = ( pxLink )->pxNext;            \\r
+                ( pxLink )->pxNext->pxPrev = ( pxLink )->pxPrev;            \\r
+            }                                                               \\r
+                                                                            \\r
+            /* Make sure that this link is not part of any list anymore. */ \\r
+            ( pxLink )->pxPrev = NULL;                                      \\r
+            ( pxLink )->pxNext = NULL;                                      \\r
+        }                                                                   \\r
+    }\r
+\r
+/**\r
+ * @brief Merges a list into a given list.\r
+ *\r
+ * @param[in] pxHeadResultList The head of the given list into which the\r
+ * other list should be merged.\r
+ * @param[in] pxHeadListToMerge The head of the list to be merged into the\r
+ * given list.\r
+ */\r
+#define listMERGE( pxHeadResultList, pxHeadListToMerge )                                     \\r
+    {                                                                                        \\r
+        if( !listIS_EMPTY( ( pxHeadListToMerge ) ) )                                         \\r
+        {                                                                                    \\r
+            /* Setup links between last node of listToMerge and first node of resultList. */ \\r
+            ( pxHeadListToMerge )->pxPrev->pxNext = ( pxHeadResultList )->pxNext;            \\r
+            ( pxHeadResultList )->pxNext->pxPrev = ( pxHeadListToMerge )->pxPrev;            \\r
+                                                                                             \\r
+            /* Setup links between first node of listToMerge and the head of resultList. */  \\r
+            ( pxHeadListToMerge )->pxNext->pxPrev = ( pxHeadResultList );                    \\r
+            ( pxHeadResultList )->pxNext = ( pxHeadListToMerge )->pxNext;                    \\r
+            /* Empty the merged list. */                                                     \\r
+            listINIT_HEAD( ( pxHeadListToMerge ) );                                          \\r
+        }                                                                                    \\r
+    }\r
+\r
+/**\r
+ * @brief Helper macro to iterate over a list. pxLink contains the link node\r
+ * in each iteration.\r
+ */\r
+#define listFOR_EACH( pxLink, pxHead )    \\r
+    for( ( pxLink ) = ( pxHead )->pxNext; \\r
+         ( pxLink ) != ( pxHead );        \\r
+         ( pxLink ) = ( pxLink )->pxNext )\r
+\r
+/**\r
+ * @brief Helper macro to iterate over a list. It is safe to destroy/free the\r
+ * nodes while iterating. pxLink contains the link node in each iteration.\r
+ */\r
+#define listFOR_EACH_SAFE( pxLink, pxTempLink, pxHead )                        \\r
+    for( ( pxLink ) = ( pxHead )->pxNext, ( pxTempLink ) = ( pxLink )->pxNext; \\r
+         ( pxLink ) != ( pxHead );                                             \\r
+         ( pxLink ) = ( pxTempLink ), ( pxTempLink ) = ( pxLink )->pxNext )\r
+\r
+/**\r
+ * @brief Given the pointer to the link member (of type Link_t) in a struct,\r
+ * extracts the pointer to the containing struct.\r
+ *\r
+ * @param[in] pxLink The pointer to the link member.\r
+ * @param[in] type The type of the containing struct.\r
+ * @param[in] member Name of the link member in the containing struct.\r
+ */\r
+#define listCONTAINER( pxLink, type, member )    ( ( type * ) ( ( uint8_t * ) ( pxLink ) - ( uint8_t * ) ( &( ( type * ) 0 )->member ) ) )\r
+\r
+#endif /* _AWS_DOUBLY_LINKED_LIST_H_ */\r