Message queue to synchronize and share information between threads. It is a template class, so it can hold elements of different types.
Dependents: Nucleo_modbus_protocol_test F103RB_tcp_rtu_modbus_copy_v1_0
MessageQueue.h@2:5e151e3834db, 2015-01-19 (annotated)
- Committer:
- gabrielrivas
- Date:
- Mon Jan 19 08:09:02 2015 +0000
- Revision:
- 2:5e151e3834db
- Parent:
- 1:c5b6cfae502d
Documentation added.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
gabrielrivas | 2:5e151e3834db | 1 | /** Message Queue Library |
gabrielrivas | 1:c5b6cfae502d | 2 | * Copyright (c) 2015 Gabriel Rivas |
gabrielrivas | 1:c5b6cfae502d | 3 | * |
gabrielrivas | 1:c5b6cfae502d | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
gabrielrivas | 1:c5b6cfae502d | 5 | * you may not use this file except in compliance with the License. |
gabrielrivas | 1:c5b6cfae502d | 6 | * You may obtain a copy of the License at |
gabrielrivas | 1:c5b6cfae502d | 7 | * |
gabrielrivas | 1:c5b6cfae502d | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
gabrielrivas | 1:c5b6cfae502d | 9 | * |
gabrielrivas | 1:c5b6cfae502d | 10 | * Unless required by applicable law or agreed to in writing, software |
gabrielrivas | 1:c5b6cfae502d | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
gabrielrivas | 1:c5b6cfae502d | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
gabrielrivas | 1:c5b6cfae502d | 13 | * See the License for the specific language governing permissions and |
gabrielrivas | 1:c5b6cfae502d | 14 | * limitations under the License. |
gabrielrivas | 1:c5b6cfae502d | 15 | */ |
gabrielrivas | 0:faed68cc9fff | 16 | #ifndef _MESSAGE_QUEUE_H_ |
gabrielrivas | 0:faed68cc9fff | 17 | #define _MESSAGE_QUEUE_H_ |
gabrielrivas | 0:faed68cc9fff | 18 | |
gabrielrivas | 0:faed68cc9fff | 19 | #include "mbed.h" |
gabrielrivas | 0:faed68cc9fff | 20 | #include "rtos.h" |
gabrielrivas | 0:faed68cc9fff | 21 | #include <queue> |
gabrielrivas | 0:faed68cc9fff | 22 | |
gabrielrivas | 0:faed68cc9fff | 23 | #define MESSAGE_QUEUE_MAX_SIZE (256) |
gabrielrivas | 0:faed68cc9fff | 24 | |
gabrielrivas | 1:c5b6cfae502d | 25 | /** |
gabrielrivas | 1:c5b6cfae502d | 26 | * Message queue class that is a wrapper for the STL queue container intended to |
gabrielrivas | 1:c5b6cfae502d | 27 | * be used to share data among threads using the mbed-rtos so the write and read access |
gabrielrivas | 1:c5b6cfae502d | 28 | * to the queue is protected from simultaneous access. |
gabrielrivas | 1:c5b6cfae502d | 29 | */ |
gabrielrivas | 0:faed68cc9fff | 30 | template <class T> |
gabrielrivas | 0:faed68cc9fff | 31 | class MessageQueue |
gabrielrivas | 0:faed68cc9fff | 32 | { |
gabrielrivas | 0:faed68cc9fff | 33 | public: |
gabrielrivas | 1:c5b6cfae502d | 34 | /** |
gabrielrivas | 1:c5b6cfae502d | 35 | * Create a message queue object. |
gabrielrivas | 1:c5b6cfae502d | 36 | * @param size The size for the queue. |
gabrielrivas | 1:c5b6cfae502d | 37 | */ |
gabrielrivas | 0:faed68cc9fff | 38 | MessageQueue(uint32_t size); |
gabrielrivas | 0:faed68cc9fff | 39 | |
gabrielrivas | 0:faed68cc9fff | 40 | public: |
gabrielrivas | 1:c5b6cfae502d | 41 | /** |
gabrielrivas | 1:c5b6cfae502d | 42 | * Write a data element into the back of the queue. |
gabrielrivas | 1:c5b6cfae502d | 43 | * @param data Value or object to be writen into the queue. |
gabrielrivas | 1:c5b6cfae502d | 44 | */ |
gabrielrivas | 0:faed68cc9fff | 45 | void write(T data); |
gabrielrivas | 1:c5b6cfae502d | 46 | |
gabrielrivas | 1:c5b6cfae502d | 47 | /** |
gabrielrivas | 1:c5b6cfae502d | 48 | * Reads a element from the queue. |
gabrielrivas | 1:c5b6cfae502d | 49 | * @return The element in the front of the queue. |
gabrielrivas | 1:c5b6cfae502d | 50 | */ |
gabrielrivas | 0:faed68cc9fff | 51 | T read(); |
gabrielrivas | 1:c5b6cfae502d | 52 | |
gabrielrivas | 1:c5b6cfae502d | 53 | /** |
gabrielrivas | 1:c5b6cfae502d | 54 | * Tells if a number of elements written has reached the size of the queue. |
gabrielrivas | 1:c5b6cfae502d | 55 | * |
gabrielrivas | 1:c5b6cfae502d | 56 | * @return The full status flag. |
gabrielrivas | 1:c5b6cfae502d | 57 | */ |
gabrielrivas | 0:faed68cc9fff | 58 | bool isFull(); |
gabrielrivas | 1:c5b6cfae502d | 59 | |
gabrielrivas | 1:c5b6cfae502d | 60 | /** |
gabrielrivas | 1:c5b6cfae502d | 61 | * Tells if no data elements can be read from the queue. |
gabrielrivas | 1:c5b6cfae502d | 62 | * @return The empty status flag. |
gabrielrivas | 1:c5b6cfae502d | 63 | */ |
gabrielrivas | 0:faed68cc9fff | 64 | bool isEmpty(); |
gabrielrivas | 1:c5b6cfae502d | 65 | |
gabrielrivas | 1:c5b6cfae502d | 66 | /** |
gabrielrivas | 1:c5b6cfae502d | 67 | * Get the number of elements written into the queue. |
gabrielrivas | 1:c5b6cfae502d | 68 | * @return Index of the last element written in the queue. |
gabrielrivas | 1:c5b6cfae502d | 69 | */ |
gabrielrivas | 0:faed68cc9fff | 70 | uint32_t getWriteIndex(); |
gabrielrivas | 1:c5b6cfae502d | 71 | |
gabrielrivas | 1:c5b6cfae502d | 72 | /** |
gabrielrivas | 1:c5b6cfae502d | 73 | * Get the number of elements read from the queue. |
gabrielrivas | 1:c5b6cfae502d | 74 | * @return Index of the last element read from the queue. |
gabrielrivas | 1:c5b6cfae502d | 75 | */ |
gabrielrivas | 0:faed68cc9fff | 76 | uint32_t getReadIndex(); |
gabrielrivas | 1:c5b6cfae502d | 77 | |
gabrielrivas | 1:c5b6cfae502d | 78 | /** |
gabrielrivas | 1:c5b6cfae502d | 79 | * Removes all the elements in the queue and reset all its internal counters and status. |
gabrielrivas | 1:c5b6cfae502d | 80 | */ |
gabrielrivas | 0:faed68cc9fff | 81 | void reset(); |
gabrielrivas | 0:faed68cc9fff | 82 | |
gabrielrivas | 0:faed68cc9fff | 83 | private: |
gabrielrivas | 1:c5b6cfae502d | 84 | /** Internal queue that holds data elements. |
gabrielrivas | 1:c5b6cfae502d | 85 | */ |
gabrielrivas | 0:faed68cc9fff | 86 | std::queue<T> m_queue; |
gabrielrivas | 1:c5b6cfae502d | 87 | |
gabrielrivas | 1:c5b6cfae502d | 88 | /** Mutex to protect the queue from simultaneous access. |
gabrielrivas | 1:c5b6cfae502d | 89 | */ |
gabrielrivas | 0:faed68cc9fff | 90 | Mutex m_mutex; |
gabrielrivas | 1:c5b6cfae502d | 91 | |
gabrielrivas | 1:c5b6cfae502d | 92 | /** Number of elements allowed to be written into the queue. |
gabrielrivas | 1:c5b6cfae502d | 93 | */ |
gabrielrivas | 0:faed68cc9fff | 94 | uint32_t m_size; |
gabrielrivas | 1:c5b6cfae502d | 95 | |
gabrielrivas | 1:c5b6cfae502d | 96 | /** Internal full status flag. |
gabrielrivas | 1:c5b6cfae502d | 97 | */ |
gabrielrivas | 0:faed68cc9fff | 98 | bool m_full; |
gabrielrivas | 1:c5b6cfae502d | 99 | |
gabrielrivas | 1:c5b6cfae502d | 100 | /** Internal empty status flag. |
gabrielrivas | 1:c5b6cfae502d | 101 | */ |
gabrielrivas | 0:faed68cc9fff | 102 | bool m_empty; |
gabrielrivas | 1:c5b6cfae502d | 103 | |
gabrielrivas | 1:c5b6cfae502d | 104 | /** Internal index for elements read from the queue. |
gabrielrivas | 1:c5b6cfae502d | 105 | */ |
gabrielrivas | 0:faed68cc9fff | 106 | uint32_t m_readIndex; |
gabrielrivas | 1:c5b6cfae502d | 107 | |
gabrielrivas | 1:c5b6cfae502d | 108 | /** Internal index for elements written into the queue. |
gabrielrivas | 1:c5b6cfae502d | 109 | */ |
gabrielrivas | 0:faed68cc9fff | 110 | uint32_t m_writeIndex; |
gabrielrivas | 0:faed68cc9fff | 111 | |
gabrielrivas | 0:faed68cc9fff | 112 | }; |
gabrielrivas | 0:faed68cc9fff | 113 | |
gabrielrivas | 0:faed68cc9fff | 114 | |
gabrielrivas | 0:faed68cc9fff | 115 | template <class T> |
gabrielrivas | 0:faed68cc9fff | 116 | MessageQueue<T>::MessageQueue(uint32_t size) |
gabrielrivas | 0:faed68cc9fff | 117 | { |
gabrielrivas | 0:faed68cc9fff | 118 | // assert(size < MESSAGE_QUEUE_MAX_SIZE); |
gabrielrivas | 0:faed68cc9fff | 119 | m_size = size; |
gabrielrivas | 0:faed68cc9fff | 120 | m_full = false; |
gabrielrivas | 0:faed68cc9fff | 121 | m_empty = true; |
gabrielrivas | 0:faed68cc9fff | 122 | m_readIndex = 0; |
gabrielrivas | 0:faed68cc9fff | 123 | m_writeIndex = 0; |
gabrielrivas | 0:faed68cc9fff | 124 | } |
gabrielrivas | 0:faed68cc9fff | 125 | |
gabrielrivas | 0:faed68cc9fff | 126 | template <class T> |
gabrielrivas | 0:faed68cc9fff | 127 | void MessageQueue<T>::write(T data) |
gabrielrivas | 0:faed68cc9fff | 128 | { |
gabrielrivas | 0:faed68cc9fff | 129 | m_mutex.lock(); |
gabrielrivas | 0:faed68cc9fff | 130 | |
gabrielrivas | 0:faed68cc9fff | 131 | if (m_writeIndex == m_size) { |
gabrielrivas | 0:faed68cc9fff | 132 | m_full = true; |
gabrielrivas | 0:faed68cc9fff | 133 | } else { |
gabrielrivas | 0:faed68cc9fff | 134 | m_queue.push(data); |
gabrielrivas | 0:faed68cc9fff | 135 | m_empty = false; |
gabrielrivas | 0:faed68cc9fff | 136 | m_writeIndex++; |
gabrielrivas | 0:faed68cc9fff | 137 | } |
gabrielrivas | 0:faed68cc9fff | 138 | m_mutex.unlock(); |
gabrielrivas | 0:faed68cc9fff | 139 | } |
gabrielrivas | 0:faed68cc9fff | 140 | |
gabrielrivas | 0:faed68cc9fff | 141 | template <class T> |
gabrielrivas | 0:faed68cc9fff | 142 | T MessageQueue<T>::read() |
gabrielrivas | 0:faed68cc9fff | 143 | { |
gabrielrivas | 2:5e151e3834db | 144 | T data = 0; |
gabrielrivas | 0:faed68cc9fff | 145 | |
gabrielrivas | 0:faed68cc9fff | 146 | m_mutex.lock(); |
gabrielrivas | 0:faed68cc9fff | 147 | |
gabrielrivas | 0:faed68cc9fff | 148 | if (m_readIndex == m_writeIndex) { |
gabrielrivas | 0:faed68cc9fff | 149 | m_empty = true; |
gabrielrivas | 0:faed68cc9fff | 150 | } else { |
gabrielrivas | 0:faed68cc9fff | 151 | data = m_queue.front(); |
gabrielrivas | 0:faed68cc9fff | 152 | m_full = false; |
gabrielrivas | 0:faed68cc9fff | 153 | m_queue.pop(); |
gabrielrivas | 0:faed68cc9fff | 154 | m_readIndex++; |
gabrielrivas | 0:faed68cc9fff | 155 | } |
gabrielrivas | 0:faed68cc9fff | 156 | |
gabrielrivas | 0:faed68cc9fff | 157 | m_mutex.unlock(); |
gabrielrivas | 0:faed68cc9fff | 158 | |
gabrielrivas | 0:faed68cc9fff | 159 | return data; |
gabrielrivas | 0:faed68cc9fff | 160 | } |
gabrielrivas | 0:faed68cc9fff | 161 | |
gabrielrivas | 0:faed68cc9fff | 162 | template <class T> |
gabrielrivas | 0:faed68cc9fff | 163 | bool MessageQueue<T>::isFull() |
gabrielrivas | 0:faed68cc9fff | 164 | { |
gabrielrivas | 0:faed68cc9fff | 165 | return m_full; |
gabrielrivas | 0:faed68cc9fff | 166 | } |
gabrielrivas | 0:faed68cc9fff | 167 | |
gabrielrivas | 0:faed68cc9fff | 168 | template <class T> |
gabrielrivas | 0:faed68cc9fff | 169 | bool MessageQueue<T>::isEmpty() |
gabrielrivas | 0:faed68cc9fff | 170 | { |
gabrielrivas | 0:faed68cc9fff | 171 | return m_empty; |
gabrielrivas | 0:faed68cc9fff | 172 | } |
gabrielrivas | 0:faed68cc9fff | 173 | |
gabrielrivas | 0:faed68cc9fff | 174 | template <class T> |
gabrielrivas | 0:faed68cc9fff | 175 | uint32_t MessageQueue<T>::getWriteIndex() |
gabrielrivas | 0:faed68cc9fff | 176 | { |
gabrielrivas | 0:faed68cc9fff | 177 | return m_writeIndex; |
gabrielrivas | 0:faed68cc9fff | 178 | } |
gabrielrivas | 0:faed68cc9fff | 179 | |
gabrielrivas | 0:faed68cc9fff | 180 | template <class T> |
gabrielrivas | 0:faed68cc9fff | 181 | uint32_t MessageQueue<T>::getReadIndex() |
gabrielrivas | 0:faed68cc9fff | 182 | { |
gabrielrivas | 0:faed68cc9fff | 183 | return m_readIndex; |
gabrielrivas | 0:faed68cc9fff | 184 | } |
gabrielrivas | 0:faed68cc9fff | 185 | |
gabrielrivas | 0:faed68cc9fff | 186 | template <class T> |
gabrielrivas | 0:faed68cc9fff | 187 | void MessageQueue<T>::reset() |
gabrielrivas | 0:faed68cc9fff | 188 | { |
gabrielrivas | 0:faed68cc9fff | 189 | m_mutex.lock(); |
gabrielrivas | 0:faed68cc9fff | 190 | |
gabrielrivas | 0:faed68cc9fff | 191 | while(!isEmpty()) read(); |
gabrielrivas | 0:faed68cc9fff | 192 | m_full = false; |
gabrielrivas | 0:faed68cc9fff | 193 | m_empty = true; |
gabrielrivas | 0:faed68cc9fff | 194 | m_readIndex = 0; |
gabrielrivas | 0:faed68cc9fff | 195 | m_writeIndex = 0; |
gabrielrivas | 0:faed68cc9fff | 196 | |
gabrielrivas | 0:faed68cc9fff | 197 | m_mutex.unlock(); |
gabrielrivas | 0:faed68cc9fff | 198 | } |
gabrielrivas | 0:faed68cc9fff | 199 | |
gabrielrivas | 0:faed68cc9fff | 200 | #endif |