Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

221 lines
4.8KB

  1. /*
  2. * High-level, real-time safe, templated C++ doubly linked list
  3. * Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the COPYING file
  16. */
  17. #ifndef __RT_LIST_HPP__
  18. #define __RT_LIST_HPP__
  19. extern "C" {
  20. #include "rtmempool/list.h"
  21. #include "rtmempool/rtmempool.h"
  22. }
  23. #include <cassert>
  24. #include <cstring>
  25. typedef struct list_head k_list_head;
  26. template<typename T>
  27. class RtList
  28. {
  29. public:
  30. RtList(const size_t minPreallocated, const size_t maxPreallocated)
  31. {
  32. qcount = 0;
  33. ::INIT_LIST_HEAD(&queue);
  34. ::rtsafe_memory_pool_create(&mempool, nullptr, sizeof(RtListData), minPreallocated, maxPreallocated);
  35. assert(mempool);
  36. }
  37. ~RtList()
  38. {
  39. clear();
  40. ::rtsafe_memory_pool_destroy(mempool);
  41. }
  42. void resize(const size_t minPreallocated, const size_t maxPreallocated)
  43. {
  44. clear();
  45. ::rtsafe_memory_pool_destroy(mempool);
  46. ::rtsafe_memory_pool_create(&mempool, nullptr, sizeof(RtListData), minPreallocated, maxPreallocated);
  47. assert(mempool);
  48. }
  49. void clear()
  50. {
  51. if (! isEmpty())
  52. {
  53. RtListData* data;
  54. k_list_head* entry;
  55. list_for_each(entry, &queue)
  56. {
  57. data = list_entry(entry, RtListData, siblings);
  58. ::rtsafe_memory_pool_deallocate(mempool, data);
  59. }
  60. }
  61. qcount = 0;
  62. ::INIT_LIST_HEAD(&queue);
  63. }
  64. size_t count() const
  65. {
  66. return qcount;
  67. }
  68. bool isEmpty() const
  69. {
  70. return (qcount == 0);
  71. //return (list_empty(&queue) != 0);
  72. }
  73. void append(const T& value, const bool sleepy = false)
  74. {
  75. RtListData* data;
  76. if (sleepy)
  77. data = (RtListData*)::rtsafe_memory_pool_allocate_sleepy(mempool);
  78. else
  79. data = (RtListData*)::rtsafe_memory_pool_allocate_atomic(mempool);
  80. if (data)
  81. {
  82. ::memcpy(&data->value, &value, sizeof(T));
  83. ::list_add_tail(&data->siblings, &queue);
  84. qcount++;
  85. }
  86. }
  87. T& getFirst()
  88. {
  89. return __get(true, false);
  90. }
  91. T& getFirstAndRemove()
  92. {
  93. return __get(true, true);
  94. }
  95. T& getLast()
  96. {
  97. return __get(false, false);
  98. }
  99. T& getLastAndRemove()
  100. {
  101. return __get(false, true);
  102. }
  103. bool removeOne(const T& value)
  104. {
  105. RtListData* data;
  106. k_list_head* entry;
  107. list_for_each(entry, &queue)
  108. {
  109. data = list_entry(entry, RtListData, siblings);
  110. if (data->value == value)
  111. {
  112. qcount--;
  113. ::list_del(entry);
  114. ::rtsafe_memory_pool_deallocate(mempool, data);
  115. return true;
  116. }
  117. }
  118. return false;
  119. }
  120. void removeAll(const T& value)
  121. {
  122. RtListData* data;
  123. k_list_head* entry;
  124. k_list_head* tmp;
  125. list_for_each_safe(entry, tmp, &queue)
  126. {
  127. data = list_entry(entry, RtListData, siblings);
  128. if (data->value == value)
  129. {
  130. qcount--;
  131. ::list_del(entry);
  132. ::rtsafe_memory_pool_deallocate(mempool, data);
  133. }
  134. }
  135. }
  136. private:
  137. size_t qcount;
  138. k_list_head queue;
  139. RtMemPool_Handle mempool;
  140. struct RtListData {
  141. T value;
  142. k_list_head siblings;
  143. };
  144. T& __get(const bool first, const bool doDelete)
  145. {
  146. if (isEmpty())
  147. {
  148. // FIXME ?
  149. static T value;
  150. static bool reset = true;
  151. if (reset)
  152. {
  153. reset = false;
  154. ::memset(&value, 0, sizeof(T));
  155. }
  156. return value;
  157. }
  158. k_list_head* entry = first ? queue.next : queue.prev;
  159. RtListData* data = list_entry(entry, RtListData, siblings);
  160. T& ret = data->value;
  161. if (data && doDelete)
  162. {
  163. qcount--;
  164. ::list_del(entry);
  165. ::rtsafe_memory_pool_deallocate(mempool, data);
  166. }
  167. return ret;
  168. }
  169. // Non-copyable
  170. RtList(const RtList&);
  171. RtList& operator= (const RtList&);
  172. // Prevent heap allocation
  173. static void* operator new (size_t);
  174. static void operator delete (void*);
  175. };
  176. #endif // __RT_LIST_HPP__