Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
CircularBuffer.h
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2015 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #ifndef MBED_CIRCULARBUFFER_H 00017 #define MBED_CIRCULARBUFFER_H 00018 00019 #include "platform/mbed_critical.h" 00020 #include "platform/mbed_assert.h" 00021 00022 namespace mbed { 00023 00024 namespace internal { 00025 /* Detect if CounterType of the Circular buffer is of unsigned type. */ 00026 template<typename T> 00027 struct is_unsigned { 00028 static const bool value = false; 00029 }; 00030 template<> 00031 struct is_unsigned<unsigned char> { 00032 static const bool value = true; 00033 }; 00034 template<> 00035 struct is_unsigned<unsigned short> { 00036 static const bool value = true; 00037 }; 00038 template<> 00039 struct is_unsigned<unsigned int> { 00040 static const bool value = true; 00041 }; 00042 template<> 00043 struct is_unsigned<unsigned long> { 00044 static const bool value = true; 00045 }; 00046 template<> 00047 struct is_unsigned<unsigned long long> { 00048 static const bool value = true; 00049 }; 00050 }; 00051 00052 /** \addtogroup platform */ 00053 /** @{*/ 00054 /** 00055 * \defgroup platform_CircularBuffer CircularBuffer functions 00056 * @{ 00057 */ 00058 00059 /** Templated Circular buffer class 00060 * 00061 * @note Synchronization level: Interrupt safe 00062 * @note CounterType must be unsigned and consistent with BufferSize 00063 */ 00064 template<typename T, uint32_t BufferSize, typename CounterType = uint32_t> 00065 class CircularBuffer { 00066 public: 00067 CircularBuffer() : _head(0), _tail(0), _full(false) 00068 { 00069 MBED_STATIC_ASSERT( 00070 internal::is_unsigned<CounterType>::value, 00071 "CounterType must be unsigned" 00072 ); 00073 00074 MBED_STATIC_ASSERT( 00075 (sizeof(CounterType) >= sizeof(uint32_t)) || 00076 (BufferSize < (((uint64_t) 1) << (sizeof(CounterType) * 8))), 00077 "Invalid BufferSize for the CounterType" 00078 ); 00079 } 00080 00081 ~CircularBuffer() 00082 { 00083 } 00084 00085 /** Push the transaction to the buffer. This overwrites the buffer if it's 00086 * full 00087 * 00088 * @param data Data to be pushed to the buffer 00089 */ 00090 void push(const T &data) 00091 { 00092 core_util_critical_section_enter(); 00093 if (full()) { 00094 _tail++; 00095 if (_tail == BufferSize) { 00096 _tail = 0; 00097 } 00098 } 00099 _pool[_head++] = data; 00100 if (_head == BufferSize) { 00101 _head = 0; 00102 } 00103 if (_head == _tail) { 00104 _full = true; 00105 } 00106 core_util_critical_section_exit(); 00107 } 00108 00109 /** Pop the transaction from the buffer 00110 * 00111 * @param data Data to be popped from the buffer 00112 * @return True if the buffer is not empty and data contains a transaction, false otherwise 00113 */ 00114 bool pop(T &data) 00115 { 00116 bool data_popped = false; 00117 core_util_critical_section_enter(); 00118 if (!empty()) { 00119 data = _pool[_tail++]; 00120 if (_tail == BufferSize) { 00121 _tail = 0; 00122 } 00123 _full = false; 00124 data_popped = true; 00125 } 00126 core_util_critical_section_exit(); 00127 return data_popped; 00128 } 00129 00130 /** Check if the buffer is empty 00131 * 00132 * @return True if the buffer is empty, false if not 00133 */ 00134 bool empty() const 00135 { 00136 core_util_critical_section_enter(); 00137 bool is_empty = (_head == _tail) && !_full; 00138 core_util_critical_section_exit(); 00139 return is_empty; 00140 } 00141 00142 /** Check if the buffer is full 00143 * 00144 * @return True if the buffer is full, false if not 00145 */ 00146 bool full() const 00147 { 00148 core_util_critical_section_enter(); 00149 bool full = _full; 00150 core_util_critical_section_exit(); 00151 return full; 00152 } 00153 00154 /** Reset the buffer 00155 * 00156 */ 00157 void reset() 00158 { 00159 core_util_critical_section_enter(); 00160 _head = 0; 00161 _tail = 0; 00162 _full = false; 00163 core_util_critical_section_exit(); 00164 } 00165 00166 /** Get the number of elements currently stored in the circular_buffer */ 00167 CounterType size() const 00168 { 00169 core_util_critical_section_enter(); 00170 CounterType elements; 00171 if (!_full) { 00172 if (_head < _tail) { 00173 elements = BufferSize + _head - _tail; 00174 } else { 00175 elements = _head - _tail; 00176 } 00177 } else { 00178 elements = BufferSize; 00179 } 00180 core_util_critical_section_exit(); 00181 return elements; 00182 } 00183 00184 /** Peek into circular buffer without popping 00185 * 00186 * @param data Data to be peeked from the buffer 00187 * @return True if the buffer is not empty and data contains a transaction, false otherwise 00188 */ 00189 bool peek(T &data) const 00190 { 00191 bool data_updated = false; 00192 core_util_critical_section_enter(); 00193 if (!empty()) { 00194 data = _pool[_tail]; 00195 data_updated = true; 00196 } 00197 core_util_critical_section_exit(); 00198 return data_updated; 00199 } 00200 00201 private: 00202 T _pool[BufferSize]; 00203 CounterType _head; 00204 CounterType _tail; 00205 bool _full; 00206 }; 00207 00208 /**@}*/ 00209 00210 /**@}*/ 00211 00212 } 00213 00214 #endif
Generated on Tue Aug 9 2022 00:37:04 by
