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.
Fork of mbed-dev by
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 _tail %= BufferSize; 00096 } 00097 _pool[_head++] = data; 00098 _head %= BufferSize; 00099 if (_head == _tail) { 00100 _full = true; 00101 } 00102 core_util_critical_section_exit(); 00103 } 00104 00105 /** Pop the transaction from the buffer 00106 * 00107 * @param data Data to be popped from the buffer 00108 * @return True if the buffer is not empty and data contains a transaction, false otherwise 00109 */ 00110 bool pop(T &data) 00111 { 00112 bool data_popped = false; 00113 core_util_critical_section_enter(); 00114 if (!empty()) { 00115 data = _pool[_tail++]; 00116 _tail %= BufferSize; 00117 _full = false; 00118 data_popped = true; 00119 } 00120 core_util_critical_section_exit(); 00121 return data_popped; 00122 } 00123 00124 /** Check if the buffer is empty 00125 * 00126 * @return True if the buffer is empty, false if not 00127 */ 00128 bool empty() const 00129 { 00130 core_util_critical_section_enter(); 00131 bool is_empty = (_head == _tail) && !_full; 00132 core_util_critical_section_exit(); 00133 return is_empty; 00134 } 00135 00136 /** Check if the buffer is full 00137 * 00138 * @return True if the buffer is full, false if not 00139 */ 00140 bool full() const 00141 { 00142 core_util_critical_section_enter(); 00143 bool full = _full; 00144 core_util_critical_section_exit(); 00145 return full; 00146 } 00147 00148 /** Reset the buffer 00149 * 00150 */ 00151 void reset() 00152 { 00153 core_util_critical_section_enter(); 00154 _head = 0; 00155 _tail = 0; 00156 _full = false; 00157 core_util_critical_section_exit(); 00158 } 00159 00160 /** Get the number of elements currently stored in the circular_buffer */ 00161 CounterType size() const 00162 { 00163 core_util_critical_section_enter(); 00164 CounterType elements; 00165 if (!_full) { 00166 if (_head < _tail) { 00167 elements = BufferSize + _head - _tail; 00168 } else { 00169 elements = _head - _tail; 00170 } 00171 } else { 00172 elements = BufferSize; 00173 } 00174 core_util_critical_section_exit(); 00175 return elements; 00176 } 00177 00178 /** Peek into circular buffer without popping 00179 * 00180 * @param data Data to be peeked from the buffer 00181 * @return True if the buffer is not empty and data contains a transaction, false otherwise 00182 */ 00183 bool peek(T &data) const 00184 { 00185 bool data_updated = false; 00186 core_util_critical_section_enter(); 00187 if (!empty()) { 00188 data = _pool[_tail]; 00189 data_updated = true; 00190 } 00191 core_util_critical_section_exit(); 00192 return data_updated; 00193 } 00194 00195 private: 00196 T _pool[BufferSize]; 00197 volatile CounterType _head; 00198 volatile CounterType _tail; 00199 volatile bool _full; 00200 }; 00201 00202 /**@}*/ 00203 00204 /**@}*/ 00205 00206 } 00207 00208 #endif
Generated on Tue Jul 12 2022 19:10:20 by
 1.7.2 
    