takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CircularBuffer.h Source File

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