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.

215 lines
4.6KB

  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. typedef struct list_head k_list_head;
  25. template<typename T>
  26. class RtList
  27. {
  28. public:
  29. RtList(const size_t minPreallocated, const size_t maxPreallocated)
  30. {
  31. qcount = 0;
  32. INIT_LIST_HEAD(&queue);
  33. rtsafe_memory_pool_create(&mempool, nullptr, sizeof(ListHeadData), minPreallocated, maxPreallocated);
  34. assert(mempool);
  35. }
  36. ~RtList()
  37. {
  38. clear();
  39. rtsafe_memory_pool_destroy(mempool);
  40. }
  41. void resize(const size_t minPreallocated, const size_t maxPreallocated)
  42. {
  43. clear();
  44. rtsafe_memory_pool_destroy(mempool);
  45. rtsafe_memory_pool_create(&mempool, nullptr, sizeof(ListHeadData), minPreallocated, maxPreallocated);
  46. assert(mempool);
  47. }
  48. void clear()
  49. {
  50. if (! isEmpty())
  51. {
  52. ListHeadData* data;
  53. k_list_head* entry;
  54. list_for_each(entry, &queue)
  55. {
  56. data = list_entry(entry, ListHeadData, siblings);
  57. rtsafe_memory_pool_deallocate(mempool, data);
  58. }
  59. }
  60. qcount = 0;
  61. INIT_LIST_HEAD(&queue);
  62. }
  63. size_t count() const
  64. {
  65. return qcount;
  66. }
  67. bool isEmpty() const
  68. {
  69. return (list_empty(&queue) != 0);
  70. }
  71. void append(const T& value, const bool sleepy = false)
  72. {
  73. ListHeadData* data;
  74. if (sleepy)
  75. data = (ListHeadData*)rtsafe_memory_pool_allocate_sleepy(mempool);
  76. else
  77. data = (ListHeadData*)rtsafe_memory_pool_allocate_atomic(mempool);
  78. if (data)
  79. {
  80. memcpy(&data->value, &value, sizeof(T));
  81. list_add_tail(&data->siblings, &queue);
  82. qcount++;
  83. }
  84. }
  85. T& getFirst()
  86. {
  87. return __get(true, false);
  88. }
  89. T& getFirstAndRemove()
  90. {
  91. return __get(true, true);
  92. }
  93. T& getLast()
  94. {
  95. return __get(false, false);
  96. }
  97. T& getLastAndRemove()
  98. {
  99. return __get(false, true);
  100. }
  101. bool removeOne(const T& value)
  102. {
  103. ListHeadData* data;
  104. k_list_head* entry;
  105. list_for_each(entry, &queue)
  106. {
  107. data = list_entry(entry, ListHeadData, siblings);
  108. if (data->value == value)
  109. {
  110. qcount--;
  111. list_del(entry);
  112. rtsafe_memory_pool_deallocate(mempool, data);
  113. return true;
  114. }
  115. }
  116. return false;
  117. }
  118. void removeAll(const T& value)
  119. {
  120. ListHeadData* data;
  121. k_list_head* entry;
  122. k_list_head* tmp;
  123. list_for_each_safe(entry, tmp, &queue)
  124. {
  125. data = list_entry(entry, ListHeadData, siblings);
  126. if (data->value == value)
  127. {
  128. qcount--;
  129. list_del(entry);
  130. rtsafe_memory_pool_deallocate(mempool, data);
  131. }
  132. }
  133. }
  134. private:
  135. size_t qcount;
  136. k_list_head queue;
  137. RtMemPool_Handle mempool;
  138. struct ListHeadData {
  139. T value;
  140. k_list_head siblings;
  141. };
  142. T& __get(const bool first, const bool doDelete)
  143. {
  144. if (isEmpty())
  145. {
  146. // FIXME ?
  147. static T value;
  148. static bool reset = true;
  149. if (reset)
  150. {
  151. reset = false;
  152. memset(&value, 0, sizeof(T));
  153. }
  154. return value;
  155. }
  156. k_list_head* entry = first ? queue.next : queue.prev;
  157. ListHeadData* data = list_entry(entry, ListHeadData, siblings);
  158. T& ret = data->value;
  159. if (data && doDelete)
  160. {
  161. qcount--;
  162. list_del(entry);
  163. rtsafe_memory_pool_deallocate(mempool, data);
  164. }
  165. return ret;
  166. }
  167. // Non-copyable
  168. RtList(const RtList&);
  169. RtList& operator= (const RtList&);
  170. };
  171. #endif // __RT_LIST_HPP__