OSDN Git Service

[FIFO_TEMPLATE][WIP] Modifying FIFO_BASE::FOO class.This still not available to build.
[csp-qt/common_source_project-fm7.git] / source / src / fifo_templates.h
1 /*
2  * Templates of FIFO and RING-BUFFER.
3  * (C) 2022-07-16 K.Ohta <whatisthis.sowhat@gmail.com>
4  * LICENSE: GPLv2
5  *
6  * Description:
7  *  This presents reference FIFO and RING-BUFFER,
8  *  both
9  *    unmutexed (faster; using from same thread)
10  *  and
11  *    mutexed (slower;  using from another threads, i.e: mailbox)
12  *  This aims to be skelton of FIFO:: class and RINGBUFFER:: class.
13
14  * ToDo:
15  *  * Will support alignment for inrernal buffer.
16  */
17
18 #pragma once
19
20 //#include "fileio.h"
21 #include <mutex>
22 #include <limits.h>
23 #include "./common.h"
24
25
26 namespace FIFO_BASE {
27         template <class T >
28         class FIFO_INTERFACE {
29         private:
30                 std::atomic<ssize_t> m_bufSize;
31         protected:
32                 std::shared_ptr<T> m_buf;
33                 std::atomic<ssize_t> m_low_warning;
34                 std::atomic<ssize_t> m_high_warning;
35                 size_t m_rptr;
36                 size_t m_wptr;
37
38                 std::atomic<bool> m_is_ringbuffer;
39                 std::atomic<ssize_t> m_dataCount;
40                 // Use only for LOCKED_FOO, not using for UNLOCKED_FOO .
41                 std::recursive_mutex m_locker;
42
43                 inline bool is_ringbuffer() const {
44                         return m_is_ringbuffer.load();
45                 }
46                 inline ssize_t get_buffer_size() {
47                         return m_bufSize.load();
48                 }
49                 ssize_t realloc_buffer_size(size_t _count, bool force = false) {
50                         __UNLIKELY_IF(_count == 0) {
51                                 if(force) {
52                                         m_buf.reset();
53                                         m_bufSize = 0;
54                                 }
55                         } else {
56                                 __UNLIKELY_IF(_count > SSIZE_MAX) {
57                                         _count = SSIZE_MAX;
58                                 }
59                                 if((_count != m_bufSize.load()) || (force)) {
60                                         T* p = nullptr;
61                                         try {
62                                                 p = new T(_count);
63                                         } catch (std::bad_alloc& e) {
64                                                 _count = 0;
65                                         }
66                                         if((p == nullptr) && (force)) {
67                                                 m_buf.reset();
68                                                 m_bufSize = 0;
69                                         } else if((p != nullptr) && (_count != 0)) {
70                                                 m_buf.reset(p);
71                                                 m_bufSize = _count;
72                                         } else {
73                                                 // DO NOTHING
74                                         }
75                                 }
76                         }
77                         return m_bufSize.load();
78                 }
79                 void reset_buffer() {
80                         m_buf.reset();
81                         m_bufSize = 0;
82                 }
83                 constexpr bool check_data_available(size_t _count = 1) {
84                         __LIKELY_IF(check_buffer_available()) {
85                                 __UNLIKELY_IF((_count > SSIZE_MAX) || (_count == 0)) {
86                                         return false;
87                                 }
88                                 return (m_dataCount.load() >= ((ssize_t)_count)) ? true : false;
89                         }
90                         return false;
91                 }
92                 constexpr bool check_buffer_available() {
93                         bool success = ((m_bufSize.get() <= 0) || (m_buf.get() == nullptr)) ? false : true;
94                         return success;
95                 }
96                 constexpr bool check_data_writable(size_t _count = 1) {
97                         __UNLIKELY_IF((_count == 0) || (_count > SSIZE_MAX)) {
98                                 return false;
99                         }
100                         __LIKELY_IF(check_buffer_available()) {
101                                 ssize_t _dcount = m_dataCount.load();
102                                 __UNLIKELY_IF(_dcount <= 0) {
103                                         m_dataCount = 0;
104                                         _dcount = 0;
105                                 }
106                                 ssize_t _size = m_bufSize.load();
107                                 if(is_ringbuffer()) {
108                                         __UNLIKELY_IF(_size <= 0) {
109                                                 return false;
110                                         }
111                                         return (_count <= (size_t)_size) ? true : false;
112                                 } else {
113                                         return ((_dcount + _count) <= _size) ? true : false;
114                                 }
115                         }
116                         return false;
117                 }
118
119                 inline void check_offset(size_t& offset)
120                 {
121                         __UNLIKELY_IF(m_bufSize <= 0) {
122                                 offset = 0;
123                         } else {
124                                 offset = offset % m_bufSize;
125                         }
126                 }
127                 inline bool check_readable_data_count(T* dst, size_t _count) {
128                         __UNLIKELY_IF(dst == nullptr) {
129                                 return false;
130                         }
131                         return check_data_available(_count);
132                 }
133                 virtual T unlocked_read_base(void) {
134                         return (T)0;
135                 }
136                 virtual T unlocked_read_base(bool& success) {
137                         success = check_data_available();
138                         return unlocked_read_base();
139                 }
140                 virtual T locked_read_base(void) {
141                         std::lock_guard<std::recursive_mutex> locker(m_locker);
142                         return unlocked_read_base();
143                 }
144                 virtual T locked_read_base(bool& success) {
145                         std::lock_guard<std::recursive_mutex> locker(m_locker);
146                         return unlocked_read_base(success);
147                 }
148                 virtual T unlocked_read_not_remove_base(size_t offset) {
149                         check_offset(offset);
150                         return (T)0;
151                 }
152                 virtual T unlocked_read_not_remove_base(size_t offset, bool& success) {
153                         success = check_buffer_available();
154                         return unlocked_read_not_remove_base(offset);
155                 }
156                 virtual T locked_read_not_remove_base(size_t offset) {
157                         std::lock_guard<std::recursive_mutex> locker(m_locker);
158                         return unlocked_read_not_remove_base(offset);
159                 }
160                 virtual T locked_read_not_remove_base(size_t offset, bool& success) {
161
162                         std::lock_guard<std::recursive_mutex> locker(m_locker);
163                         return unlocked_read_not_remove_base(offset, success);
164                 }
165                 virtual size_t unlocked_read_to_buffer_base(T* dst, size_t _count, bool& success) {
166                                 success = check_readable_data_count(dst, _count);
167                                 __UNLIKELY_IF(!(success)) {
168                                         return 0;
169                                 }
170                                 return 0; // ToDo
171                 }
172                 virtual size_t locked_read_to_buffer_base(T* dst, size_t _count, bool& success) {
173                         std::lock_guard<std::recursive_mutex> locker(m_locker);
174                         return unlocked_read_to_buffer_base(dst, _count, success);
175                 }
176                 virtual bool unlocked_write_base(T data) {
177                         bool success = check_data_writable();
178                         return success;
179                 }
180                 virtual bool locked_write_base(T data) {
181                         std::lock_guard<std::recursive_mutex> locker(m_locker);
182                         return unlocked_write_base(data);
183                 }
184                 virtual bool unlocked_write_not_push_base(size_t offset, T data)        {
185                         bool success = check_buffer_available();
186                         check_offset(offset);
187                         return success;
188                 }
189                 virtual bool locked_write_not_push_base(size_t offset, T data)  {
190                         std::lock_guard<std::recursive_mutex> locker(m_locker);
191                         return unlocked_write_not_push_base(offset, data);
192                 }
193                 virtual size_t unlocked_write_from_buffer_base(T* src, size_t _count, bool& success) {
194                         __UNLIKELY_IF(src == nullptr) {
195                                 success = false;
196                                 return 0;
197                         }
198                         success = check_data_writable(_count);
199                         __UNLIKELY_IF(!(success)) {
200                                 return 0;
201                         }
202                         return _count;
203                 }
204                 virtual size_t locked_write_from_buffer_base(T* src, size_t _count, bool& success) {
205                         std::lock_guard<std::recursive_mutex> locker(m_locker);
206                         return unlocked_write_from_buffer_base(src, _count, success);
207                 }
208         public:
209                 FIFO_INTERFACE(size_t _size) :
210                         m_rptr(0), m_wptr(0), m_dataCount(0),
211                         m_high_warning(SSIZE_MAX - 1), m_low_warning(SSIZE_MIN + 1),
212                         m_is_ringbuffer(false)
213                 {
214                         bool is_legal = true;
215                         m_buf.reset();
216                         ssize_t bsize = realloc_buffer_size(_size, true);
217                         if((bsize <= 0) || (bsize != _size) || (m.buf.get() == nullptr)) {
218                                 is_legal = false;
219                         }
220                         if(!(is_legal)) {
221                                 m_high_warning = SSIZE_MIN;
222                                 m_low_warning = SSIZE_MAX;
223                                 reset_buffer();
224                         }
225                         initialize();
226                 }
227                 ~FIFO_INTERFACE()
228                 {
229                         release();
230                 }
231                 virtual void initialize() {}
232                 virtual void release() {}
233                 virtual void clear() {
234                         std::lock_guard<std::recursive_mutex> locker(m_locker);
235                         m_rptr = 0;
236                         m_wptr = 0;
237                         m_dataCount = 0;
238                         __UNLIKELY_IF(!(check_buffer_available())) {
239                                 return;
240                         }
241                         for(int i = 0; i < m_bufSize; i++) {
242                                 m_buf[i] = (T)0;
243                         }
244                 }
245                 virtual T read(bool& success) {
246                         return unlocked_read_base(success);
247                 }
248                 virtual T read(void) {
249                         return unlocked_read_base();
250                 }
251                 virtual T read_not_remove(size_t offset, bool& success) {
252                         return unlocked_read_not_remove_base(offset, success);
253                 }
254                 virtual T read_not_remove(size_t offset) {
255                         return unlocked_read_not_remove_base(offset);
256                 }
257                 virtual size_t read_to_buffer(T* dst, size_t _count, bool& success)
258                 {
259                         return unlocked_read_to_buffer_base(dst, _count, success);
260                 }
261                 virtual size_t read_to_buffer(T* dst, size_t _count) {
262                         bool dummy;
263                         return read_to_buffer(dst, _count, dummy);
264                 }
265
266                 virtual bool write(T data) {
267                         return unlocked_write_base(data);
268                 }
269                 virtual bool write_not_push(int offset, T data) {
270                         return unlocked_write_not_push_base(offset, data);
271                 }
272                 virtual size_t write_from_buffer(T* src, size_t _count, bool& success) {
273                         return unlocked_write_from_buffer_base(src, _count, success);
274
275                 }
276                 virtual size_t write_from_buffer(T* src, size_t _count) {
277                         bool dummy;
278                         return write_from_buffer(src, _count, dummy);
279                 }
280                 bool available()
281                 {
282                         return check_buffer_available();
283                 }
284                 bool empty()
285                 {
286                         return (check_data_available()) ? false : true;
287                 }
288                 bool read_ready(size_t _count = 1)
289                 {
290                         return check_data_available(_count);
291                 }
292                 virtual bool write_ready(size_t _count = 1)
293                 {
294                         return check_data_writable(_count);
295                 }
296                 bool full()
297                 {
298                         bool result = ((is_ringbuffer()) || !(check_data_writable()));
299                         return result;
300                 }
301
302                 size_t count()
303                 {
304                         ssize_t _count = m_dataCount.load();
305                         __UNLIKELY_IF(_count < 0) {
306                                 return 0;
307                         }
308                         return (size_t)_count;
309                 }
310                 size_t fifo_size()
311                 {
312                         ssize_t _size = m_bufSize.load();
313                         __UNLIKELY_IF(_size < 0) {
314                                 return 0;
315                         }
316                         __UNLIKELY_IF(_size > SSIZE_MAX) {
317                                 return SSIZE_MAX;
318                         }
319                         return (size_t)_size;
320                 }
321                 size_t left()
322                 {
323                         __UNLIKELY_IF(!(check_buffer_available())) {
324                                 return 0;
325                         }
326                         ssize_t _size = get_buffer_size();
327                         if(is_ringbuffer()) {
328                                 __UNLIKELY_IF(_size == SSIZE_MAX) {
329                                         return SSIZE_MAX;
330                                 }
331                         } else {
332                                 ssize_t _count = m_dataCount.load();
333                                 _size = _size - _count;
334                         }
335                         __UNLIKELY_IF(_size < 0) {
336                                 return 0;
337                         }
338                         return _size;
339                 }
340                 void set_high_warn_value(ssize_t val = SSIZE_MAX - 1)
341                 {
342                         m_high_warning = val;
343                 }
344                 void set_low_warn_value(ssize_t val = SSIZE_MIN + 1)
345                 {
346                         m_low_warning = val;
347                 }
348                 bool high_warn()
349                 {
350                         return (m_high_warning.load() < m_dataCount.load()) ? true : false;
351                 }
352                 bool low_warn() {
353                         return (m_low_warning.load() > m_dataCount.load()) ? true : false;
354                 }
355                 bool resize(size_t _size, bool force = false, ssize_t _low_warn = SSIZE_MIN + 1, ssize_t _high_warn = SSIZE_MAX - 1) {
356                         std::lock_guard<std::recursive_mutex> locker(m_locker);
357                         ssize_t realsize = realloc_buffer_size(_size, force);
358                         if(realsize <= 0) {
359                                 set_high_warn_value();
360                                 set_low_warn_value();
361                                 return false;
362                         }
363                         if((size_t)realsize != _size) {
364                                 set_high_warn_value();
365                                 set_low_warn_value();
366                                 return false;
367                         }
368                         set_high_warn_value(_high_warn);
369                         set_low_warn_value(_low_warn);
370                         return true;
371                 }
372         };
373
374         template <class T >
375         class UNLOCKED_FIFO : publc FIFO_INTERFACE<T> {
376         protected:
377                 virtual T unlocked_read_base() override
378                 {
379                         bool dummy = false;
380                         return unlocked_read_base(dummy);
381                 }
382                 virtual T unlocked_read_base(bool& success) override
383                 {
384                         T tmpval = (T)0;
385                         success = false;
386                         __LIKELY_IF(check_data_available()) {
387                                 size_t buf_size = (size_t)get_buffer_size();
388                                 __LIKELY_IF(m_rptr.load() < buf_size) {
389                                         tmpval = m_buf[m_rptr++];
390                                         m_dataCount--;
391                                         success = true;
392                                 }
393                         }
394                         return tmpval;
395                 }
396                 virtual T unlocked_read_not_remove_base(size_t offset, bool& success) override
397                 {
398                         check_offset(offset);
399                         T tmpval = (T)0;
400                         success = check_buffer_available();
401                         __LIKELY_IF(success) {
402                                 size_t rptr = m_rptr.load();
403                                 rptr = optr + offset;
404                                 ssize_t bufsize = get_buffer_size();
405                                 __UNLIKELY_IF(bufsize <= 0) {
406                                         success = false;
407                                         return tmpval;
408                                 }
409                                 __UNLIKELY_IF(rptr >= bufsize) {
410                                         rptr = rptr % bufsize;
411                                 }
412                                 T* p = m_buf.get();
413                                 __UNLIKELY_IF(p == nullptr) {
414                                         success = false;
415                                 } else {
416                                         tmpval = p[rptr];
417                                         success = true;
418                                 }
419                         }
420                         return tmpval;
421                 }
422                 virtual T unlocked_read_not_remove_base(size_t offset) override
423                 {
424                         bool dummy;
425                         return unlocked_read_not_remove_base(offset, dummy);
426                 }
427                 virtual size_t unlocked_read_to_buffer_base(T* dst, size_t _count, bool& success) override
428                 {
429                         success = false;
430                         __UNLIKELY_IF(dst == nullptr) {
431                                 return 0;
432                         }
433                         success = check_buffer_available();
434                         __LIKELY_IF(success) {
435                                 T* p = m_buf.get();
436                                 size_t words = 0;
437                                 for(; words < _count; words++) {
438                                         __UNLIKELY_IF((m_rptr.load() >= bufsize) || (m_dataCount.load() <= 0)) {
439                                                 break;
440                                         }
441                                         dst[words] = p[m_rptr++];
442                                         m_dataCount--;
443                                 }
444                                 __UNLIKELY_IF(words <= 0) {
445                                         success = false;
446                                         return 0;
447                                 }
448                                 return words;
449                         }
450                         return 0;
451                 }
452                 virtual size_t unlocked_read_to_buffer_base(T* dst, size_t _count) override
453                 {
454                         bool dummy;
455                         return unlocked_read_to_buffer_base(dst, _count, dummy);
456                 }
457         public:
458                 UNLOCKED_FIFO(size_t _size) : FIFO_INTERFACE<T>
459                 {
460                 }
461                 ~UNLOCKED_FIFO()
462                 {
463                 }
464                 //!< Read one data
465                 virtual bool write(T data)
466                 {
467                         __UNLIKELY_IF((m_buf == nullptr) || (m_dataCount >= (int)m_bufSize)
468                                                   || (m_bufSize == 0)) {
469                                 return false;
470                         }
471                         __UNLIKELY_IF(m_dataCount < 0) {
472                                 m_dataCount = 0; // OK?
473                         }
474                         m_buf[m_wptr++] = data;
475                         m_dataCount++;
476                         __UNLIKELY_IF(m_wptr >= m_bufSize) {
477                                 m_wptr = 0;
478                         }
479                         __UNLIKELY_IF(m_dataCount >= (int)m_bufSize) {
480                                 m_dataCount = (int)m_bufSize;
481                         }
482                         return true;
483                 }
484                 virtual bool write_not_push(int offset, T data)
485                 {
486                         __UNLIKELY_IF((m_buf == nullptr) ||
487                                                   (m_bufSize == 0) || (offset < 0)) {
488                                 return false;
489                         }
490                         unsigned int wp = m_wptr + offset;
491                         __UNLIKELY_IF(wp >= (int)m_bufSize) {
492                                 wp = wp % m_bufSize;
493                         }
494                         m_buf[wp] = data;
495                         return true;
496                 }
497                 virtual int write_from_buffer(T* src, int _count, bool& success)
498                 {
499                         __UNLIKELY_IF((src == nullptr) || (_count <= 0) ||
500                                                   (m_buf == nullptr) || (m_bufSize == 0) ||
501                                                   (m_dataCount >= (int)m_bufSize)) {
502                                 success = false;
503                                 return 0;
504                         }
505                         __UNLIKELY_IF(m_dataCount < 0) {
506                                 m_dataCount = 0; // OK?
507                         }
508                         __UNLIKELY_IF(_count > (int)m_bufSize) {
509                                 _count = (int)m_bufSize;
510                         }
511                         __UNLIKELY_IF((_count + m_dataCount) >= (int)m_bufSize) {
512                                 _count = (int)m_bufSize - m_dataCount;
513                                 if(_count <= 0) {
514                                         success = false;
515                                         return 0;
516                                 }
517                         }
518                         __UNLIKELY_IF(m_wptr >= m_bufSize) {
519                                 m_wptr = m_wptr % m_bufSize;
520                         }
521                         // OK, Transfer
522                         int xptr = m_wptr;
523                         if((xptr + (unsigned int)_count) > m_bufSize) {
524                                 int count1 = (int)(m_bufSize - (xptr % m_bufSize));
525                                 int count2 = _count - count1;
526                                 int rp = 0;
527                                 for(int i = 0; i < count1; i++) {
528                                         m_buf[xptr++] = src[rp++];
529                                 }
530                                 xptr = 0;
531                                 for(int i = 0; i < count2; i++) {
532                                         m_buf[xptr++] = src[rp++];
533                                 }
534                         } else {
535                                 // Inside buffer
536                                 for(int i = 0; i < _count; i++) {
537                                         m_buf[xptr++] = src[i];
538                                 }
539                         }
540                         m_wptr = xptr % m_bufSize;
541                         m_dataCount += _count;
542                         __UNLIKELY_IF(m_dataCount > (int)m_bufSize) {
543                                 m_dataCount = (int)m_bufSize;
544                         }
545                         success = true;
546                         return _count;
547                 }
548
549         };
550
551         template <class T >
552         class LOCKED_FIFO : public UNLOCKED_FIFO<T> {
553         protected:
554         public:
555                 LOCKED_FIFO(int _size) :
556                 UNLOCKED_FIFO<T>(_size)
557                 {
558                 }
559                 ~LOCKED_FIFO()
560                 {
561                 }
562                 virtual void initialize()
563                 {
564                         std::lock_guard<std::recursive_mutex> locker(m_locker);
565                 }
566                 virtual void release()
567                 {
568                         std::lock_guard<std::recursive_mutex> locker(m_locker);
569                         UNLOCKED_FIFO<T>::release();
570                 }
571                 virtual void clear()
572                 {
573                         std::lock_guard<std::recursive_mutex> locker(m_locker);
574                         UNLOCKED_FIFO<T>::clear();
575                 }
576                 virtual T read(bool& success)
577                 {
578                         std::lock_guard<std::recursive_mutex> locker(m_locker);
579                         return UNLOCKED_FIFO<T>::read(success);
580                 }
581                 virtual T read(void)
582                 {
583                         bool success;
584                         std::lock_guard<std::recursive_mutex> locker(m_locker);
585                         return UNLOCKED_FIFO<T>::read(success);
586                 }
587
588                 virtual T read_not_remove(int offset, bool& success)
589                 {
590                         std::lock_guard<std::recursive_mutex> locker(m_locker);
591                         return UNLOCKED_FIFO<T>::read_not_remove(offset, success);
592                 }
593                 virtual T read_not_remove(int offset)
594                 {
595                         bool success;
596                         std::lock_guard<std::recursive_mutex> locker(m_locker);
597                         return UNLOCKED_FIFO<T>::read_not_remove(offset, success);
598                 }
599                 virtual int read_to_buffer(T* dst, int _count, bool& success)
600                 {
601                         std::lock_guard<std::recursive_mutex> locker(m_locker);
602                         return UNLOCKED_FIFO<T>::read_to_buffer(dst, _count, success);
603                 }
604                 virtual bool write(T data)
605                 {
606                         std::lock_guard<std::recursive_mutex> locker(m_locker);
607                         return UNLOCKED_FIFO<T>::write(data);
608                 }
609                 virtual bool write_not_push(int offset, T data)
610                 {
611                         std::lock_guard<std::recursive_mutex> locker(m_locker);
612                         return UNLOCKED_FIFO<T>::write_not_push(offset, data);
613                 }
614                 virtual int write_from_buffer(T* src, int _count, bool& success)
615                 {
616                         std::lock_guard<std::recursive_mutex> locker(m_locker);
617                         return UNLOCKED_FIFO<T>::write_from_buffer(src, _count, success);
618                 }
619                 virtual bool available()
620                 {
621                         std::lock_guard<std::recursive_mutex> locker(m_locker);
622                         return UNLOCKED_FIFO<T>::available();
623                 }
624                 virtual bool empty()
625                 {
626                         std::lock_guard<std::recursive_mutex> locker(m_locker);
627                         return UNLOCKED_FIFO<T>::empty();
628                 }
629                 virtual bool read_ready()
630                 {
631                         std::lock_guard<std::recursive_mutex> locker(m_locker);
632                         return UNLOCKED_FIFO<T>::read_ready();
633                 }
634                 virtual bool write_ready()
635                 {
636                         std::lock_guard<std::recursive_mutex> locker(m_locker);
637                         return UNLOCKED_FIFO<T>::write_ready();
638                 }
639
640                 virtual bool full()
641                 {
642                         std::lock_guard<std::recursive_mutex> locker(m_locker);
643                         return UNLOCKED_FIFO<T>::full();
644                 }
645                 virtual int count()
646                 {
647                         std::lock_guard<std::recursive_mutex> locker(m_locker);
648                         return UNLOCKED_FIFO<T>::count();
649                 }
650                 virtual int fifo_size()
651                 {
652                         std::lock_guard<std::recursive_mutex> locker(m_locker);
653                         return UNLOCKED_FIFO<T>::fifo_size();
654                 }
655                 virtual int left()
656                 {
657                         std::lock_guard<std::recursive_mutex> locker(m_locker);
658                         return UNLOCKED_FIFO<T>::left();
659                 }
660                 virtual void set_high_warn_value(int val = INT_MAX - 1)
661                 {
662                         std::lock_guard<std::recursive_mutex> locker(m_locker);
663                         return UNLOCKED_FIFO<T>::set_high_warn_value(val);
664                 }
665                 virtual void set_low_warn_value(int val = INT_MIN + 1)
666                 {
667                         std::lock_guard<std::recursive_mutex> locker(m_locker);
668                         return UNLOCKED_FIFO<T>::set_low_warn_value(val);
669                 }
670                 virtual bool high_warn()
671                 {
672                         std::lock_guard<std::recursive_mutex> locker(m_locker);
673                         return UNLOCKED_FIFO<T>::high_warn();
674                 }
675                 virtual bool low_warn()
676                 {
677                         std::lock_guard<std::recursive_mutex> locker(m_locker);
678                         return UNLOCKED_FIFO<T>::low_warn();
679                 }
680                 virtual bool resize(int _size, int _low_warn = INT_MIN + 1, int _high_warn = INT_MAX - 1)
681                 {
682                         std::lock_guard<std::recursive_mutex> locker(m_locker);
683                         return UNLOCKED_FIFO<T>::resize(_size, _low_warn, _high_warn);
684                 }
685         };
686
687         template <class T >
688         class UNLOCKED_RINGBUFFER : public UNLOCKED_FIFO<T> {
689         public:
690                 UNLOCKED_RINGBUFFER(int _size) :
691                 UNLOCKED_FIFO<T>(_size)
692                 {
693                 }
694                 ~UNLOCKED_RINGBUFFER()
695                 {
696                 }
697                 virtual void initialize()
698                 {
699                         UNLOCKED_FIFO<T>::initialize();
700                 }
701                 virtual void release()
702                 {
703                         UNLOCKED_FIFO<T>::release();
704                 }
705                 // RINGBUFFER :  Even write to buffer when full.
706                 virtual bool write(T data)
707                 {
708                         __UNLIKELY_IF((UNLOCKED_FIFO<T>::m_buf == nullptr) || (UNLOCKED_FIFO<T>::m_bufSize == 0)) {
709                                 return false;
710                         }
711
712                         __UNLIKELY_IF(UNLOCKED_FIFO<T>::m_dataCount < 0) {
713                                 UNLOCKED_FIFO<T>::m_dataCount = 0; // OK?
714                         }
715                         UNLOCKED_FIFO<T>::m_buf[UNLOCKED_FIFO<T>::m_wptr++] = data;
716                         UNLOCKED_FIFO<T>::m_dataCount++;
717                         __UNLIKELY_IF(UNLOCKED_FIFO<T>::m_wptr >= UNLOCKED_FIFO<T>::m_bufSize) {
718                                 UNLOCKED_FIFO<T>::m_wptr = UNLOCKED_FIFO<T>::m_wptr % UNLOCKED_FIFO<T>::m_bufSize;
719                         }
720                         __UNLIKELY_IF(UNLOCKED_FIFO<T>::m_dataCount > (int)UNLOCKED_FIFO<T>::m_bufSize) {
721                                 UNLOCKED_FIFO<T>::m_dataCount = (int)UNLOCKED_FIFO<T>::m_bufSize;
722                         }
723                         return true;
724                 }
725                 virtual bool write_not_push(int offset, T data)
726                 {
727                         __UNLIKELY_IF((UNLOCKED_FIFO<T>::m_buf == nullptr) ||
728                                                   (UNLOCKED_FIFO<T>::m_bufSize == 0) || (offset < 0)) {
729                                 return false;
730                         }
731                         unsigned int wp = UNLOCKED_FIFO<T>::m_wptr + offset;
732                         __UNLIKELY_IF(wp >= (int)UNLOCKED_FIFO<T>::m_bufSize) {
733                                 wp = wp % UNLOCKED_FIFO<T>::m_bufSize;
734                         }
735                         UNLOCKED_FIFO<T>::m_buf[wp] = data;
736                         return true;
737                 }
738                 virtual int write_from_buffer(T* src, int _count, bool& success)
739                 {
740                         __UNLIKELY_IF((src == nullptr) || (_count <= 0) ||
741                            (UNLOCKED_FIFO<T>::m_buf == nullptr) || (UNLOCKED_FIFO<T>::m_bufSize == 0)) {
742                                 success = false;
743                                 return 0;
744                         }
745                         __UNLIKELY_IF(UNLOCKED_FIFO<T>::m_dataCount < 0) {
746                                 UNLOCKED_FIFO<T>::m_dataCount = 0; // OK?
747                         }
748                         __UNLIKELY_IF(_count > (int)UNLOCKED_FIFO<T>::m_bufSize) {
749                                 _count = (int)UNLOCKED_FIFO<T>::m_bufSize;
750                                 __UNLIKELY_IF(_count <= 0) {
751                                         success = false;
752                                         return 0;
753                                 }
754                         }
755                         __UNLIKELY_IF(UNLOCKED_FIFO<T>::m_wptr >= UNLOCKED_FIFO<T>::m_bufSize) {
756                                 UNLOCKED_FIFO<T>::m_wptr = UNLOCKED_FIFO<T>::m_wptr % UNLOCKED_FIFO<T>::m_bufSize;
757                         }
758                         // OK, Transfer
759                         unsigned int xptr = UNLOCKED_FIFO<T>::m_wptr;
760                         if((xptr + (unsigned int)_count) >= UNLOCKED_FIFO<T>::m_bufSize) {
761                                 int count1 = (int)(UNLOCKED_FIFO<T>::m_bufSize - xptr);
762                                 int count2 = _count - count1;
763                                 int rp = 0;
764                                 for(int i = 0; i < count1; i++) {
765                                         UNLOCKED_FIFO<T>::m_buf[xptr++] = src[rp++];
766                                 }
767                                 xptr = 0;
768                                 for(int i = 0; i < count2; i++) {
769                                         UNLOCKED_FIFO<T>::m_buf[xptr++] = src[rp++];
770                                 }
771                         } else {
772                                 // Inside buffer
773                                 for(int i = 0; i < _count; i++) {
774                                         UNLOCKED_FIFO<T>::m_buf[xptr++] = src[i];
775                                 }
776                         }
777                         UNLOCKED_FIFO<T>::m_dataCount += _count;
778                         UNLOCKED_FIFO<T>::m_wptr = (xptr % UNLOCKED_FIFO<T>::m_bufSize);
779                         __UNLIKELY_IF(UNLOCKED_FIFO<T>::m_dataCount >= (int)UNLOCKED_FIFO<T>::m_bufSize) {
780                                 UNLOCKED_FIFO<T>::m_dataCount = UNLOCKED_FIFO<T>::m_bufSize;
781                         }
782                         success = true;
783                         return _count;
784                 }
785                 virtual bool write_ready()
786                 {
787                         bool f = UNLOCKED_FIFO<T>::available();
788                         return f; // OK?
789                 }
790                 virtual bool full()
791                 {
792                         return false; // OK?
793                 }
794                 virtual int left()
795                 {
796                         __UNLIKELY_IF((UNLOCKED_FIFO<T>::m_bufSize == 0) || (UNLOCKED_FIFO<T>::m_buf == nullptr)) {
797                                 return 0;
798                         }
799                         return (int)UNLOCKED_FIFO<T>::m_bufSize;
800                 }
801         };
802
803         template <class T >
804         class LOCKED_RINGBUFFER : public UNLOCKED_RINGBUFFER<T> {
805         protected:
806                 std::recursive_mutex m_locker;
807         public:
808                 LOCKED_RINGBUFFER(int _size) :
809                 UNLOCKED_RINGBUFFER<T>(_size)
810                 {
811                 }
812                 ~LOCKED_RINGBUFFER()
813                 {
814                 }
815                 virtual void initialize()
816                 {
817                         std::lock_guard<std::recursive_mutex> locker(m_locker);
818                         UNLOCKED_RINGBUFFER<T>::initialize();
819                 }
820                 virtual void release()
821                 {
822                         std::lock_guard<std::recursive_mutex> locker(m_locker);
823                         UNLOCKED_RINGBUFFER<T>::release();
824                 }
825                 virtual void clear()
826                 {
827                         std::lock_guard<std::recursive_mutex> locker(m_locker);
828                         UNLOCKED_RINGBUFFER<T>::clear();
829                 }
830
831                 virtual T read(bool& success)
832                 {
833                         std::lock_guard<std::recursive_mutex> locker(m_locker);
834                         return UNLOCKED_RINGBUFFER<T>::read(success);
835                 }
836                 virtual T read(void)
837                 {
838                         bool success;
839                         std::lock_guard<std::recursive_mutex> locker(m_locker);
840                         return UNLOCKED_RINGBUFFER<T>::read(success);
841                 }
842                 virtual T read_not_remove(int offset, bool& success)
843                 {
844                         std::lock_guard<std::recursive_mutex> locker(m_locker);
845                         return UNLOCKED_RINGBUFFER<T>::read_not_remove(offset, success);
846                 }
847                 virtual T read_not_remove(int offset)
848                 {
849                         bool success;
850                         std::lock_guard<std::recursive_mutex> locker(m_locker);
851                         return UNLOCKED_RINGBUFFER<T>::read_not_remove(offset, success);
852                 }
853
854                 virtual int read_to_buffer(T* dst, int _count, bool& success)
855                 {
856                         std::lock_guard<std::recursive_mutex> locker(m_locker);
857                         return UNLOCKED_RINGBUFFER<T>::read_to_buffer(dst, _count, success);
858                 }
859
860                 virtual bool write(T data)
861                 {
862                         std::lock_guard<std::recursive_mutex> locker(m_locker);
863                         return UNLOCKED_RINGBUFFER<T>::write(data);
864                 }
865                 virtual bool write_not_push(int offset, T data)
866                 {
867                         std::lock_guard<std::recursive_mutex> locker(m_locker);
868                         return UNLOCKED_RINGBUFFER<T>::write_not_push(offset, data);
869                 }
870                 virtual int write_from_buffer(T* src, int _count, bool& success)
871                 {
872                         std::lock_guard<std::recursive_mutex> locker(m_locker);
873                         return UNLOCKED_RINGBUFFER<T>::write_from_buffer(src, _count, success);
874                 }
875                 virtual bool available()
876                 {
877                         std::lock_guard<std::recursive_mutex> locker(m_locker);
878                         return UNLOCKED_RINGBUFFER<T>::available();
879                 }
880                 virtual bool empty()
881                 {
882                         std::lock_guard<std::recursive_mutex> locker(m_locker);
883                         return UNLOCKED_RINGBUFFER<T>::empty();
884                 }
885                 virtual bool read_ready()
886                 {
887                         std::lock_guard<std::recursive_mutex> locker(m_locker);
888                         return UNLOCKED_RINGBUFFER<T>::read_ready();
889                 }
890                 virtual bool write_ready()
891                 {
892                         std::lock_guard<std::recursive_mutex> locker(m_locker);
893                         return UNLOCKED_RINGBUFFER<T>::write_ready();
894                 }
895                 virtual bool full()
896                 {
897                         std::lock_guard<std::recursive_mutex> locker(m_locker);
898                         return UNLOCKED_RINGBUFFER<T>::full();
899                 }
900                 virtual int count()
901                 {
902                         std::lock_guard<std::recursive_mutex> locker(m_locker);
903                         return UNLOCKED_RINGBUFFER<T>::count();
904                 }
905                 virtual int fifo_size()
906                 {
907                         std::lock_guard<std::recursive_mutex> locker(m_locker);
908                         return UNLOCKED_RINGBUFFER<T>::fifo_size();
909                 }
910                 virtual int left()
911                 {
912                         std::lock_guard<std::recursive_mutex> locker(m_locker);
913                         return UNLOCKED_RINGBUFFER<T>::left();
914                 }
915
916                 virtual void set_high_warn_value(int val = INT_MAX - 1)
917                 {
918                         std::lock_guard<std::recursive_mutex> locker(m_locker);
919                         return UNLOCKED_RINGBUFFER<T>::set_high_warn_value(val);
920                 }
921                 virtual void set_low_warn_value(int val = INT_MIN + 1)
922                 {
923                         std::lock_guard<std::recursive_mutex> locker(m_locker);
924                         return UNLOCKED_RINGBUFFER<T>::set_low_warn_value(val);
925                 }
926                 virtual bool high_warn()
927                 {
928                         std::lock_guard<std::recursive_mutex> locker(m_locker);
929                         return UNLOCKED_RINGBUFFER<T>::high_warn();
930                 }
931                 virtual bool low_warn()
932                 {
933                         std::lock_guard<std::recursive_mutex> locker(m_locker);
934                         return UNLOCKED_RINGBUFFER<T>::low_warn();
935                 }
936                 virtual bool resize(int _size, int _low_warn = INT_MIN + 1, int _high_warn = INT_MAX - 1)
937                 {
938                         std::lock_guard<std::recursive_mutex> locker(m_locker);
939                         return UNLOCKED_RINGBUFFER<T>::resize(_size, _low_warn, _high_warn);
940                 }
941         };
942 }