Rename a pipe method, add docs
[carla.git] / source / utils / RtLinkedList.hpp
blob2f45150e83a5072f91582ee7d255cb41e1831a08
1 /*
2 * High-level, real-time safe, templated, C++ doubly-linked list
3 * Copyright (C) 2013-2022 Filipe Coelho <falktx@falktx.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
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.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #ifndef RT_LINKED_LIST_HPP_INCLUDED
19 #define RT_LINKED_LIST_HPP_INCLUDED
21 #include "LinkedList.hpp"
23 extern "C" {
24 /* full path as IDE Helper */
25 #include "../modules/rtmempool/rtmempool.h"
28 // -----------------------------------------------------------------------
29 // Realtime safe linkedlist
31 template<typename T>
32 class RtLinkedList : public AbstractLinkedList<T>
34 public:
35 // -------------------------------------------------------------------
36 // RtMemPool C++ class
38 class Pool
40 public:
41 Pool(const char* const poolName, const std::size_t minPreallocated, const std::size_t maxPreallocated) noexcept
42 : kDataSize(sizeof(typename AbstractLinkedList<T>::Data)),
43 kPoolName(carla_strdup_safe(poolName)),
44 fHandle(nullptr)
46 rtsafe_memory_pool_create(&fHandle, nullptr, kDataSize, minPreallocated, maxPreallocated);
47 CARLA_SAFE_ASSERT(fHandle != nullptr);
50 ~Pool() noexcept
52 if (fHandle != nullptr)
54 carla_debug("Destroying %s", kPoolName);
55 rtsafe_memory_pool_destroy(fHandle);
56 fHandle = nullptr;
58 delete[] kPoolName;
61 void* allocate_atomic() const noexcept
63 return rtsafe_memory_pool_allocate_atomic(fHandle);
66 void* allocate_sleepy() const noexcept
68 return rtsafe_memory_pool_allocate_sleepy(fHandle);
71 void deallocate(void* const dataPtr) const noexcept
73 CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr,);
75 rtsafe_memory_pool_deallocate(fHandle, dataPtr);
78 bool operator==(const Pool& pool) const noexcept
80 return (fHandle == pool.fHandle && kDataSize == pool.kDataSize);
83 bool operator!=(const Pool& pool) const noexcept
85 return (fHandle != pool.fHandle || kDataSize != pool.kDataSize);
88 private:
89 const std::size_t kDataSize;
90 const char* const kPoolName;
92 mutable RtMemPool_Handle fHandle;
94 CARLA_PREVENT_HEAP_ALLOCATION
95 CARLA_DECLARE_NON_COPYABLE(Pool)
98 // -------------------------------------------------------------------
99 // Now the actual rt-linkedlist code
101 RtLinkedList(Pool& memPool) noexcept
102 : fMemPool(memPool) {}
104 #ifdef STOAT_TEST_BUILD
105 // overridden for stoat
106 bool append(const T& value) noexcept
108 if (typename AbstractLinkedList<T>::Data* const data = _allocate())
109 return this->_add_internal(data, value, true, &this->fQueue);
110 return false;
113 void clear() noexcept
115 if (this->fCount == 0)
116 return;
118 for (typename AbstractLinkedList<T>::ListHead *entry = this->fQueue.next, *entry2 = entry->next;
119 entry != &this->fQueue; entry = entry2, entry2 = entry->next)
121 typename AbstractLinkedList<T>::Data* const data = list_entry(entry, typename AbstractLinkedList<T>::Data, siblings);
122 CARLA_SAFE_ASSERT_CONTINUE(data != nullptr);
124 this->_deallocate(data);
127 this->_init();
130 T getFirst(T& fallback, const bool removeObj) noexcept
132 CARLA_SAFE_ASSERT_RETURN(this->fCount > 0, fallback);
134 typename AbstractLinkedList<T>::ListHead* const entry = this->fQueue.next;
136 typename AbstractLinkedList<T>::Data* const data = list_entry(entry, typename AbstractLinkedList<T>::Data, siblings);
137 CARLA_SAFE_ASSERT_RETURN(data != nullptr, fallback);
139 if (! removeObj)
140 return data->value;
142 const T value(data->value);
144 _deleteRT(entry, data);
146 return value;
149 void _deleteRT(typename AbstractLinkedList<T>::ListHead* const entry, typename AbstractLinkedList<T>::Data* const data) noexcept
151 CARLA_SAFE_ASSERT_RETURN(entry != nullptr,);
152 CARLA_SAFE_ASSERT_RETURN(entry->prev != nullptr,);
153 CARLA_SAFE_ASSERT_RETURN(entry->next != nullptr,);
155 --this->fCount;
157 entry->next->prev = entry->prev;
158 entry->prev->next = entry->next;
160 entry->next = nullptr;
161 entry->prev = nullptr;
163 _deallocate(data);
165 #endif
167 bool append_sleepy(const T& value) noexcept
169 return _add_sleepy(value, true);
172 bool insert_sleepy(const T& value) noexcept
174 return _add_sleepy(value, false);
177 bool moveTo(AbstractLinkedList<T>& list, const bool inTail) noexcept override
179 CARLA_SAFE_ASSERT_RETURN(((RtLinkedList&)list).fMemPool == fMemPool, false);
181 return AbstractLinkedList<T>::moveTo(list, inTail);
184 protected:
185 typename AbstractLinkedList<T>::Data* _allocate() noexcept override
187 return (typename AbstractLinkedList<T>::Data*)fMemPool.allocate_atomic();
190 typename AbstractLinkedList<T>::Data* _allocate_sleepy() noexcept
192 return (typename AbstractLinkedList<T>::Data*)fMemPool.allocate_sleepy();
195 void _deallocate(typename AbstractLinkedList<T>::Data* const dataPtr) noexcept override
197 fMemPool.deallocate(dataPtr);
200 private:
201 Pool& fMemPool;
203 bool _add_sleepy(const T& value, const bool inTail) noexcept
205 if (typename AbstractLinkedList<T>::Data* const data = _allocate_sleepy())
206 return this->_add_internal(data, value, inTail, &this->fQueue);
207 return false;
210 CARLA_PREVENT_VIRTUAL_HEAP_ALLOCATION
211 CARLA_DECLARE_NON_COPYABLE(RtLinkedList)
214 // -----------------------------------------------------------------------
216 #endif // RT_LINKED_LIST_HPP_INCLUDED