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

Revision:
19:bae78e167b11
Parent:
0:58b20b438383
--- 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