Blynk library for embedded hardware. Works with Arduino, ESP8266, Raspberry Pi, Intel Edison/Galileo, LinkIt ONE, Particle Core/Photon, Energia, ARM mbed, etc. http://www.blynk.cc/
Dependents: Blynk_RBL_BLE_Nano Blynk_MicroBit Blynk_Serial Blynk_RBL_BLE_Nano
Diff: utility/BlynkFifo.h
- Revision:
- 19:bae78e167b11
- Parent:
- 0:58b20b438383
diff -r c328c1a97f90 -r bae78e167b11 utility/BlynkFifo.h --- a/utility/BlynkFifo.h Wed Nov 29 14:05:41 2017 +0200 +++ b/utility/BlynkFifo.h Fri Dec 15 00:17:41 2017 +0200 @@ -13,83 +13,146 @@ #include <utility/BlynkUtility.h> -template<typename T, unsigned SIZE> -class BlynkFifo { +template <class T, unsigned N> +class BlynkFifo +{ +public: + BlynkFifo() + { + clear(); + } - BlynkFifo(const BlynkFifo<T, SIZE> & rb); + void clear() + { + _r = 0; + _w = 0; + } -public: + ~BlynkFifo(void) + {} + + // writing thread/context API + //------------------------------------------------------------- - BlynkFifo() : fst(0), lst(0), flag(0) {} - ~BlynkFifo() {} + bool writeable(void) + { + return free() > 0; + } - void clear() { - fst = 0; - lst = 0; - flag = 0; + int free(void) + { + int s = _r - _w; + if (s <= 0) + s += N; + return s - 1; + } + + T put(const T& c) + { + int i = _w; + int j = i; + i = _inc(i); + while (i == _r) // = !writeable() + /* nothing / just wait */; + _b[j] = c; + _w = i; + return c; } - size_t write(const T* data, size_t n) + int put(const T* p, int n, bool blocking = false) { - if ((n = BlynkMin(n, getFree()))) { - const size_t ch1 = BlynkMin(n, SIZE - lst); - memcpy(buffer + lst, data, ch1 * sizeof(T)); - lst = (lst + ch1) % SIZE; + int c = n; + while (c) + { + int f; + while ((f = free()) == 0) // wait for space + { + if (!blocking) return n - c; // no more space and not blocking + /* nothing / just wait */; + } + // check free space + if (c < f) f = c; + int w = _w; + int m = N - w; + // check wrap + if (f > m) f = m; + memcpy(&_b[w], p, f); + _w = _inc(w, f); + c -= f; + p += f; + } + return n - c; + } - if (ch1 < n) { - const size_t ch2 = n - ch1; - memcpy(buffer + lst, data + ch1, ch2 * sizeof(T)); - lst = (lst + ch2) % SIZE; - } + // reading thread/context API + // -------------------------------------------------------- - if (fst == lst) { - flag = 1; - } - } - return n; + bool readable(void) + { + return (_r != _w); + } + + size_t size(void) + { + int s = _w - _r; + if (s < 0) + s += N; + return s; } - size_t read(T* dest, size_t n) + T get(void) { - if ((n = BlynkMin(n, getOccupied()))) { - flag = 0; + int r = _r; + while (r == _w) // = !readable() + /* nothing / just wait */; + T t = _b[r]; + _r = _inc(r); + return t; + } - const size_t ch1 = BlynkMin(n, SIZE - fst); - memcpy(dest, buffer + fst, ch1 * sizeof(T)); - fst = (fst + ch1) % SIZE; - - if (ch1 < n) { - const size_t ch2 = n - ch1; - memcpy(dest + ch1, buffer + fst, ch2 * sizeof(T)); - fst = (fst + ch2) % SIZE; - } - } - return n; + T peek(void) + { + int r = _r; + while (r == _w); + return _b[r]; } - bool push(const T& data) { - return write(&data, 1) == 1; - } - - size_t getOccupied() const { - if (lst == fst) { - return flag ? SIZE : 0; - } else if (lst > fst) { - return lst - fst; - } else { - return SIZE + lst - fst; + int get(T* p, int n, bool blocking = false) + { + int c = n; + while (c) + { + int f; + for (;;) // wait for data + { + f = size(); + if (f) break; // free space + if (!blocking) return n - c; // no space and not blocking + /* nothing / just wait */; + } + // check available data + if (c < f) f = c; + int r = _r; + int m = N - r; + // check wrap + if (f > m) f = m; + memcpy(p, &_b[r], f); + _r = _inc(r, f); + c -= f; + p += f; } - } - - size_t getFree() const { - return SIZE - getOccupied(); + return n - c; } private: - T buffer[SIZE]; - size_t fst; - size_t lst; - uint8_t flag; + int _inc(int i, int n = 1) + { + return (i + n) % N; + } + + T _b[N]; + volatile int _w; + volatile int _r; }; #endif