1e41f4b71Sopenharmony_ci# Queue
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci
4e41f4b71Sopenharmony_ci## Basic Concepts
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ciA queue, also called a message queue, is a data structure used for communication between tasks. The queue receives messages of unfixed length from tasks or interrupts, and determines whether to store the transferred messages in the queue based on different APIs.
7e41f4b71Sopenharmony_ci
8e41f4b71Sopenharmony_ciTasks can read messages from a queue. When the queue has no messages, the tasks are suspended. When the queue has a new message, the suspended tasks are woken up and process the new message. Tasks can also write messages to the queue. When the queue is full, the write task is suspended. When there is an available message node in the queue, the suspended write task is woken up and writes a message.
9e41f4b71Sopenharmony_ci
10e41f4b71Sopenharmony_ciYou can adjust the timeout period of the read queue and write queue to adjust the block mode of the read and write APIs. If the timeout period is set to **0** for the read queue and write queue, tasks will not be suspended and the API directly returns. This is the non-block mode. If the timeout period is greater than **0**, block mode is used.
11e41f4b71Sopenharmony_ci
12e41f4b71Sopenharmony_ciAn asynchronous processing mechanism is provided to allow messages in a queue not to be processed immediately. In addition, queues can be used to buffer messages and implement asynchronous task communication. Queues have the following features:
13e41f4b71Sopenharmony_ci
14e41f4b71Sopenharmony_ci- Messages are queued in first-in-first-out (FIFO) mode and can be read and written asynchronously.
15e41f4b71Sopenharmony_ci
16e41f4b71Sopenharmony_ci- Both the read queue and write queue support the timeout mechanism.
17e41f4b71Sopenharmony_ci
18e41f4b71Sopenharmony_ci- Each time a message is read, the message node becomes available.
19e41f4b71Sopenharmony_ci
20e41f4b71Sopenharmony_ci- The types of messages to be sent are determined by the parties involved in communication. Messages of different lengths (not exceeding the message node size of the queue) are allowed.
21e41f4b71Sopenharmony_ci
22e41f4b71Sopenharmony_ci- A task can receive messages from and send messages to any message queue.
23e41f4b71Sopenharmony_ci
24e41f4b71Sopenharmony_ci- Multiple tasks can receive messages from and send messages to the same queue.
25e41f4b71Sopenharmony_ci
26e41f4b71Sopenharmony_ci- When a queue is created, the required dynamic memory space is automatically allocated in the queue API.
27e41f4b71Sopenharmony_ci
28e41f4b71Sopenharmony_ci
29e41f4b71Sopenharmony_ci## Working Principles
30e41f4b71Sopenharmony_ci
31e41f4b71Sopenharmony_ci
32e41f4b71Sopenharmony_ci### Queue Control Block
33e41f4b71Sopenharmony_ci
34e41f4b71Sopenharmony_ci
35e41f4b71Sopenharmony_ci```
36e41f4b71Sopenharmony_ci/**
37e41f4b71Sopenharmony_ci   * Data structure of the queue control block
38e41f4b71Sopenharmony_ci  */
39e41f4b71Sopenharmony_citypedef struct {
40e41f4b71Sopenharmony_ci    UINT8 *queueHandle; /**< Pointer to a queue handle */
41e41f4b71Sopenharmony_ci    UINT16 queueState;  /**< Queue state */
42e41f4b71Sopenharmony_ci    UINT16 queueLen;    /**< Queue length */
43e41f4b71Sopenharmony_ci    UINT16 queueSize;   /**< Node size */
44e41f4b71Sopenharmony_ci    UINT32 queueID;     /**< queueID */
45e41f4b71Sopenharmony_ci    UINT16 queueHead;   /**< Node head */
46e41f4b71Sopenharmony_ci    UINT16 queueTail;   /**< Node tail */
47e41f4b71Sopenharmony_ci    UINT16 readWriteableCnt[OS_QUEUE_N_RW];   /**< Count of readable or writable resources, 0:readable, 1:writable */
48e41f4b71Sopenharmony_ci    LOS_DL_LIST readWriteList[OS_QUEUE_N_RW]; /**< the linked list to be read or written, 0:readlist, 1:writelist */
49e41f4b71Sopenharmony_ci    LOS_DL_LIST memList;                      /**< Pointer to the memory linked list */
50e41f4b71Sopenharmony_ci} LosQueueCB;
51e41f4b71Sopenharmony_ci```
52e41f4b71Sopenharmony_ci
53e41f4b71Sopenharmony_ciEach queue control block contains information about the queue status.
54e41f4b71Sopenharmony_ci
55e41f4b71Sopenharmony_ci- **OS_QUEUE_UNUSED**: The queue is not in use.
56e41f4b71Sopenharmony_ci
57e41f4b71Sopenharmony_ci- **OS_QUEUE_INUSED**: The queue is in use.
58e41f4b71Sopenharmony_ci
59e41f4b71Sopenharmony_ci
60e41f4b71Sopenharmony_ci### Working Principles
61e41f4b71Sopenharmony_ci
62e41f4b71Sopenharmony_ci- The queue ID is returned when a queue is created successfully.
63e41f4b71Sopenharmony_ci
64e41f4b71Sopenharmony_ci- The queue control block contains **Head** and **Tail**, which indicate the storage status of messages in a queue. **Head** indicates the start position of occupied message nodes in the queue. **Tail** indicates the end position of the occupied message nodes and the start position of idle message nodes. When a queue is created, **Head** and **Tail** point to the start position of the queue.
65e41f4b71Sopenharmony_ci
66e41f4b71Sopenharmony_ci- When data is to be written to a queue, **readWriteableCnt[1]** is used to determine whether data can be written to the queue. If **readWriteableCnt[1]** is **0**, the queue is full and data cannot be written to it. Data can be written to the head node or tail node of a queue. To write data to the tail node, locate the start idle message node based on **Tail** and write data to it. If **Tail** is pointing to the tail of the queue, the rewind mode is used. To write data to the head node, locate previous node based on **Head** and write data to it. If **Head** is pointing to the start position of the queue, the rewind mode is used.
67e41f4b71Sopenharmony_ci
68e41f4b71Sopenharmony_ci- When a queue is to be read, **readWriteableCnt[0]** is used to determine whether the queue has messages to read. Reading an idle queue (**readWriteableCnt[0]** is** 0**) will cause task suspension. If the queue has messages to read, the system locates the first node to which data is written based on **Head** and read the message from the node. If **Head** is pointing to the tail of the queue, the rewind mode is used.
69e41f4b71Sopenharmony_ci
70e41f4b71Sopenharmony_ci- When a queue is to be deleted, the system locates the queue based on the queue ID, sets the queue status to **OS_QUEUE_UNUSED**, sets the queue control block to the initial state, and releases the memory occupied by the queue.
71e41f4b71Sopenharmony_ci
72e41f4b71Sopenharmony_ci  **Figure 1** Reading and writing data in a queue
73e41f4b71Sopenharmony_ci
74e41f4b71Sopenharmony_ci  ![](figures/reading-and-writing-data-in-a-queue-3.png "reading-and-writing-data-in-a-queue-3")
75e41f4b71Sopenharmony_ci
76e41f4b71Sopenharmony_ciThe preceding figure illustrates how to write data to the tail node only. Writing data to the head node is similar.
77e41f4b71Sopenharmony_ci
78e41f4b71Sopenharmony_ci
79e41f4b71Sopenharmony_ci## Development Guidelines
80e41f4b71Sopenharmony_ci
81e41f4b71Sopenharmony_ci
82e41f4b71Sopenharmony_ci### Available APIs
83e41f4b71Sopenharmony_ci
84e41f4b71Sopenharmony_ci| Category| API Description |
85e41f4b71Sopenharmony_ci| -------- | -------- |
86e41f4b71Sopenharmony_ci| Creating or deleting a message queue| - **LOS_QueueCreate**: creates a message queue. The system dynamically allocates the queue space.<br>- **LOS_QueueDelete**: deletes a queue.|
87e41f4b71Sopenharmony_ci| Reading or writing data (address without the content) in a queue| - **LOS_QueueRead**: reads data in the head node of the specified queue. The data in the queue node is an address.<br>- **LOS_QueueWrite**: writes the value of **bufferAddr** (buffer address) to the tail node of a queue.<br>- **LOS_QueueWrite**: writes the value of **bufferAddr** (buffer address) to the head node of a queue.|
88e41f4b71Sopenharmony_ci| Reading or writing data (data and address) in a queue| - **LOS_QueueReadCopy**: reads data from the head node of a queue.<br>- **LOS_QueueWriteCopy**: writes the data saved in **bufferAddr** to the tail node of a queue.<br>- **LOS_QueueWriteHeadCopy**: writes the data saved in **bufferAddr** to the head node of a queue.|
89e41f4b71Sopenharmony_ci| Obtaining queue information| **LOS_QueueInfoGet**: obtains queue information, including the queue ID, queue length, message node size, head node, tail node, number of readable/writable nodes, and tasks waiting for read/write operations.|
90e41f4b71Sopenharmony_ci
91e41f4b71Sopenharmony_ci
92e41f4b71Sopenharmony_ci### How to Develop
93e41f4b71Sopenharmony_ci
94e41f4b71Sopenharmony_ci1. Call **LOS_QueueCreate** to create a queue. The queue ID is returned when the queue is created.
95e41f4b71Sopenharmony_ci
96e41f4b71Sopenharmony_ci2. Call **LOS_QueueWrite** or **LOS_QueueWriteCopy** to write data to the queue.
97e41f4b71Sopenharmony_ci
98e41f4b71Sopenharmony_ci3. Call **LOS_QueueRead** or **LOS_QueueReadCopy** to read data from the queue.
99e41f4b71Sopenharmony_ci
100e41f4b71Sopenharmony_ci4. Call **LOS_QueueInfoGet** to obtain queue information.
101e41f4b71Sopenharmony_ci
102e41f4b71Sopenharmony_ci5. Call **LOS_QueueDelete** to delete a queue.
103e41f4b71Sopenharmony_ci
104e41f4b71Sopenharmony_ci> **NOTE**<br>
105e41f4b71Sopenharmony_ci> - The maximum number of queues supported by the system is the total number of queue resources of the system, not the number of queue resources available to users. For example, if the system software timer occupies one more queue resource, the number of queue resources available to users decreases by one.
106e41f4b71Sopenharmony_ci> 
107e41f4b71Sopenharmony_ci> - The queue name and flags passed in when a queue is created are reserved for future use.
108e41f4b71Sopenharmony_ci> 
109e41f4b71Sopenharmony_ci> - The parameter **timeOut** in the queue function is relative time.
110e41f4b71Sopenharmony_ci> 
111e41f4b71Sopenharmony_ci> - **LOS_QueueReadCopy**, **LOS_QueueWriteCopy**, and **LOS_QueueWriteHeadCopy** are a group of APIs that must be used together. **LOS_QueueRead**, **LOS_QueueWrite**, and **LOS_QueueWriteHead** are a group of APIs that must be used together.
112e41f4b71Sopenharmony_ci> 
113e41f4b71Sopenharmony_ci> - As **LOS_QueueWrite**, **LOS_QueueWriteHead**, and **LOS_QueueRead** are used to manage data addresses, you must ensure that the memory directed by the pointer obtained by calling **LOS_QueueRead** is not modified or released abnormally when the queue is being read. Otherwise, unpredictable results may occur.
114e41f4b71Sopenharmony_ci> 
115e41f4b71Sopenharmony_ci> - If the length of the data to read in **LOS_QueueRead** or **LOS_QueueReadCopy** is less than the actual message length, the message will be truncated.
116e41f4b71Sopenharmony_ci> 
117e41f4b71Sopenharmony_ci> - **LOS_QueueWrite**, **LOS_QueueWriteHead**, and **LOS_QueueRead** are called to manage data addresses, which means that the actual data read or written is pointer data. Therefore, before using these APIs, ensure that the message node size is the pointer length during queue creation, to avoid waste and read failures.
118e41f4b71Sopenharmony_ci
119e41f4b71Sopenharmony_ci
120e41f4b71Sopenharmony_ci## Development Example
121e41f4b71Sopenharmony_ci
122e41f4b71Sopenharmony_ci
123e41f4b71Sopenharmony_ci### Example Description
124e41f4b71Sopenharmony_ci
125e41f4b71Sopenharmony_ciCreate a queue and two tasks. Enable task 1 to write data to the queue, and task 2 to read data from the queue.
126e41f4b71Sopenharmony_ci
127e41f4b71Sopenharmony_ci1. Call **LOS_TaskCreate** to create task 1 and task 2.
128e41f4b71Sopenharmony_ci
129e41f4b71Sopenharmony_ci2. Call **LOS_QueueCreate** to create a message queue.
130e41f4b71Sopenharmony_ci
131e41f4b71Sopenharmony_ci3. Task 1 sends a message in **SendEntry**.
132e41f4b71Sopenharmony_ci
133e41f4b71Sopenharmony_ci4. Task 2 receives message in **RecvEntry**.
134e41f4b71Sopenharmony_ci
135e41f4b71Sopenharmony_ci5. Call **LOS_QueueDelete** to delete the queue.
136e41f4b71Sopenharmony_ci
137e41f4b71Sopenharmony_ci
138e41f4b71Sopenharmony_ci### Sample Code
139e41f4b71Sopenharmony_ci
140e41f4b71Sopenharmony_ciThe sample code can be compiled and verified in **./kernel/liteos_a/testsuites/kernel/src/osTest.c**. The **ExampleQueue** function is called in **TestTaskEntry**.
141e41f4b71Sopenharmony_ci
142e41f4b71Sopenharmony_ciTo avoid excessive printing, call **LOS_Msleep(5000)** to cause a short delay before calling **ExampleQueue**. 
143e41f4b71Sopenharmony_ci
144e41f4b71Sopenharmony_ciThe sample code is as follows:
145e41f4b71Sopenharmony_ci
146e41f4b71Sopenharmony_ci```
147e41f4b71Sopenharmony_ci#include "los_task.h"
148e41f4b71Sopenharmony_ci#include "los_queue.h"
149e41f4b71Sopenharmony_cistatic UINT32 g_queue;
150e41f4b71Sopenharmony_ci#define BUFFER_LEN 50
151e41f4b71Sopenharmony_ci
152e41f4b71Sopenharmony_ciVOID SendEntry(VOID)
153e41f4b71Sopenharmony_ci{
154e41f4b71Sopenharmony_ci    UINT32 ret = 0;
155e41f4b71Sopenharmony_ci    CHAR abuf[] = "test message";
156e41f4b71Sopenharmony_ci    UINT32 len = sizeof(abuf);
157e41f4b71Sopenharmony_ci
158e41f4b71Sopenharmony_ci    ret = LOS_QueueWriteCopy(g_queue, abuf, len, 0);
159e41f4b71Sopenharmony_ci    if(ret != LOS_OK) {
160e41f4b71Sopenharmony_ci        dprintf("send message failure, error: %x\n", ret);
161e41f4b71Sopenharmony_ci    }
162e41f4b71Sopenharmony_ci}
163e41f4b71Sopenharmony_ci
164e41f4b71Sopenharmony_ciVOID RecvEntry(VOID)
165e41f4b71Sopenharmony_ci{
166e41f4b71Sopenharmony_ci    UINT32 ret = 0;
167e41f4b71Sopenharmony_ci    CHAR readBuf[BUFFER_LEN] = {0};
168e41f4b71Sopenharmony_ci    UINT32 readLen = BUFFER_LEN;
169e41f4b71Sopenharmony_ci
170e41f4b71Sopenharmony_ci    LOS_Msleep(1000);
171e41f4b71Sopenharmony_ci    ret = LOS_QueueReadCopy(g_queue, readBuf, &readLen, 0);
172e41f4b71Sopenharmony_ci    if(ret != LOS_OK) {
173e41f4b71Sopenharmony_ci        dprintf("recv message failure, error: %x\n", ret);
174e41f4b71Sopenharmony_ci    }
175e41f4b71Sopenharmony_ci
176e41f4b71Sopenharmony_ci    dprintf("recv message: %s\n", readBuf);
177e41f4b71Sopenharmony_ci
178e41f4b71Sopenharmony_ci    ret = LOS_QueueDelete(g_queue);
179e41f4b71Sopenharmony_ci    if(ret != LOS_OK) {
180e41f4b71Sopenharmony_ci        dprintf("delete the queue failure, error: %x\n", ret);
181e41f4b71Sopenharmony_ci    }
182e41f4b71Sopenharmony_ci
183e41f4b71Sopenharmony_ci    dprintf("delete the queue success!\n");
184e41f4b71Sopenharmony_ci}
185e41f4b71Sopenharmony_ci
186e41f4b71Sopenharmony_ciUINT32 ExampleQueue(VOID)
187e41f4b71Sopenharmony_ci{
188e41f4b71Sopenharmony_ci    dprintf("start queue example\n");
189e41f4b71Sopenharmony_ci    UINT32 ret = 0;
190e41f4b71Sopenharmony_ci    UINT32 task1, task2;
191e41f4b71Sopenharmony_ci    TSK_INIT_PARAM_S initParam = {0};
192e41f4b71Sopenharmony_ci
193e41f4b71Sopenharmony_ci    ret = LOS_QueueCreate("queue", 5, &g_queue, 0, 50);
194e41f4b71Sopenharmony_ci    if(ret != LOS_OK) {
195e41f4b71Sopenharmony_ci        dprintf("create queue failure, error: %x\n", ret);
196e41f4b71Sopenharmony_ci    }
197e41f4b71Sopenharmony_ci
198e41f4b71Sopenharmony_ci    dprintf("create the queue success!\n");
199e41f4b71Sopenharmony_ci
200e41f4b71Sopenharmony_ci    initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)SendEntry;
201e41f4b71Sopenharmony_ci    initParam.usTaskPrio = 9;
202e41f4b71Sopenharmony_ci    initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
203e41f4b71Sopenharmony_ci    initParam.pcName = "SendQueue";
204e41f4b71Sopenharmony_ci
205e41f4b71Sopenharmony_ci    LOS_TaskLock();
206e41f4b71Sopenharmony_ci    ret = LOS_TaskCreate(&task1, &initParam);
207e41f4b71Sopenharmony_ci    if(ret != LOS_OK) {
208e41f4b71Sopenharmony_ci        dprintf("create task1 failed, error: %x\n", ret);
209e41f4b71Sopenharmony_ci        LOS_QueueDelete(g_queue);
210e41f4b71Sopenharmony_ci        return ret;
211e41f4b71Sopenharmony_ci    }
212e41f4b71Sopenharmony_ci
213e41f4b71Sopenharmony_ci    initParam.pcName = "RecvQueue";
214e41f4b71Sopenharmony_ci    initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)RecvEntry;
215e41f4b71Sopenharmony_ci    ret = LOS_TaskCreate(&task2, &initParam);
216e41f4b71Sopenharmony_ci    if(ret != LOS_OK) {
217e41f4b71Sopenharmony_ci        dprintf("create task2 failed, error: %x\n", ret);
218e41f4b71Sopenharmony_ci        LOS_QueueDelete(g_queue);
219e41f4b71Sopenharmony_ci        return ret;
220e41f4b71Sopenharmony_ci    }
221e41f4b71Sopenharmony_ci
222e41f4b71Sopenharmony_ci    LOS_TaskUnlock();
223e41f4b71Sopenharmony_ci    LOS_Msleep(5000);
224e41f4b71Sopenharmony_ci    return ret;
225e41f4b71Sopenharmony_ci}
226e41f4b71Sopenharmony_ci```
227e41f4b71Sopenharmony_ci
228e41f4b71Sopenharmony_ci
229e41f4b71Sopenharmony_ci### Verification
230e41f4b71Sopenharmony_ci
231e41f4b71Sopenharmony_ciThe development is successful if the return result is as follows:
232e41f4b71Sopenharmony_ci
233e41f4b71Sopenharmony_ci
234e41f4b71Sopenharmony_ci```
235e41f4b71Sopenharmony_cistart queue example
236e41f4b71Sopenharmony_cicreate the queue success!
237e41f4b71Sopenharmony_cirecv message: test message
238e41f4b71Sopenharmony_cidelete the queue success!
239e41f4b71Sopenharmony_ci```
240