Bidirectional linked list
1. Data Structure Analysis
In litLib.h, the base class for manipulating bidirectional linked list is defined.
typedef struct _Vx_node /* Node of a linked list. */ { struct _Vx_node *next; /* Points at the next node in the list */ struct _Vx_node *previous; /* Points at the previous node in the list */ } _Vx_NODE;
There is only one pointer to the previous one and one to the next, and the data content inherits this class.
typedef struct /* Header for a linked list. */ { _Vx_NODE node; /* Header list node */ int count; /* Number of nodes in list */ } _Vx_LIST;
LIST is a pointer to the data header of the current operation, containing a counter member.
The following are API s for manipulating linked lists:
extern void lstLibInit (void); extern NODE * lstFirst (LIST *pList); extern NODE * lstGet (LIST *pList); extern NODE * lstLast (LIST *pList); extern NODE * lstNStep (NODE *pNode, int nStep); extern NODE * lstNext (NODE *pNode); extern NODE * lstNth (LIST *pList, int nodenum); extern NODE * lstPrevious (NODE *pNode); extern int lstCount (LIST *pList); extern int lstFind (LIST *pList, NODE *pNode); extern void lstAdd (LIST *pList, NODE *pNode);that will do extern void lstConcat (LIST *pDstList, LIST *pAddList); extern void lstDelete (LIST *pList, NODE *pNode); extern void lstExtract (LIST *pSrcList, NODE *pStartNode, NODE *pEndNode, LIST *pDstList); extern void lstFree (LIST *pList); extern void lstInit (LIST *pList); extern void lstInsert (LIST *pList, NODE *pPrev, NODE *pNode);
2. Examples of Two-way Link List
- Firstly, user data needs to be defined. Each user data is a node and needs to be inherited from the node class.
struct USER_DATA{ _Vx_NODE LIST; user_data; //user data }
- After defining the user data, we need to initialize the linked list and use the void lstInit (LIST *pList) provided by Vxworks. This function needs to pass in a header node and directly into the user data we defined.
- Next, you can use API to add and delete data. The following are concrete examples:
#include<stdio.h> #include "vxWorks.h" #include "taskLib.h" #include "sysLib.h" #include "stdlib.h" #include "string.h" #include "lstLib.h" typedef struct buf_D{ NODE node; int buf[2]; }BUF_D; typedef BUF_D BUF; LIST *mylist() { LIST *buf_drps = (LIST*)malloc(sizeof(LIST*)); //Initialization list lstInit(buf_drps); BUF *buf=(BUF *)malloc(sizeof(BUF)); //Add a node to the list buf->buf[0]=1; buf->buf[1]=2; lstAdd(buf_drps,buf); BUF *buf2=(BUF *)malloc(sizeof(BUF)); //Add a node to the list buf2->buf[0]=3; buf2->buf[1]=4; lstAdd(buf_drps,buf2); BUF *buf3=(BUF *)malloc(sizeof(BUF)); //Add a node to the list buf3->buf[0]=5; buf3->buf[1]=6; lstAdd(buf_drps,buf3); return buf_drps; } #define TASK_PR 90 int taskid; int buf[10]; void test_task(void) //new task { BUF *buf_drps=mylist(); printf("%d",lstCount(buf_drps)); while(buf_drps->node.next) printf("%d",((BUF *)lstGet(buf_drps))->buf[1]); taskDelay(sysClkRateGet()/2); printf("%d",lstCount(buf_drps)); } int main() { taskid = taskSpawn("tDemo",TASK_PR,VX_NO_STACK_FILL,4000,(FUNCPTR)test_task,0,0,0,0,0,0,0,0,0,0); taskDelay(sysClkRateGet()); return 0; }
Ring Buffer
data structure
The data structure of ring buffer is defined in rngLib.h.
typedef struct /* RING - ring buffer */ { size_t pToBuf; /* offset from start of buffer where to write next */ size_t pFromBuf; /* offset from start of buffer where to read next */ size_t bufSize; /* size of ring in bytes */ char *buf; /* pointer to start of buffer */ } RING;
As can be seen from the above code, the use of ring buffer needs to directly define the size of the buffer, which stores data in bytes. The current data state is determined by two position pointers.
The following steps are done in RING_ID rngCreate (size_t nbytes):
-
RING_ID ringId = (RING_ID) malloc (sizeof (RING); // Data space allocated for ring buffer
-
Buffer = char *) malloc (+ + nbytes); // Allocate space for data (note that buffer is defined as a pointer, so memory space needs to be allocated for it. It looks a bit like C++ copy construction.
ringId->bufSize = nbytes;
ringId->buf = buffer;
rngFlush (ringId); // This function is to zero the buffer data, we know that when fear P - > read = P - > write = 0, the ring buffer is empty condition. That is to empty the buffer.
return (ringId); // Return an operation handle
VXworks provides us with some common API functions for buffers:
extern BOOL rngIsEmpty (RING_ID ringId); extern BOOL rngIsFull (RING_ID ringId); extern RING_ID rngCreate (size_t nbytes); extern size_t rngBufGet (RING_ID rngId, char *buffer, size_t maxbytes); extern size_t rngBufPut (RING_ID rngId, char *buffer, size_t nbytes); extern size_t rngFreeBytes (RING_ID ringId); extern size_t rngNBytes (RING_ID ringId); extern void rngDelete (RING_ID ringId); extern void rngFlush (RING_ID ringId); extern void rngMoveAhead (RING_ID ringId, size_t n); extern void rngPutAhead (RING_ID ringId, char byte, size_t offset);
With these functions, we can easily manipulate the ring buffer.
An Example of Ring Buffer Operation
void ring_test() { RING_ID *buf_id; size_t num=0; char read_buf[3]; buf_id = rngCreate(64); //Allocate 64 byte space const char *const str = "hello ring"; rngBufPut(buf_id,str,(strlen(str)+1)); //Write buffer num = rngNBytes(buf_id); printf("%d\n",num); rngBufGet(buf_id,read_buf,2); //Read two characters read_buf[2]='\0'; printf("%s\n",read_buf); num = rngNBytes(buf_id); printf("%d\n",num); }
As you can see, put 11 characters in the buffer, "after reading two", there are nine left.