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"
24 /* full path as IDE Helper */
25 #include "../modules/rtmempool/rtmempool.h"
28 // -----------------------------------------------------------------------
29 // Realtime safe linkedlist
32 class RtLinkedList
: public AbstractLinkedList
<T
>
35 // -------------------------------------------------------------------
36 // RtMemPool C++ class
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
)),
46 rtsafe_memory_pool_create(&fHandle
, nullptr, kDataSize
, minPreallocated
, maxPreallocated
);
47 CARLA_SAFE_ASSERT(fHandle
!= nullptr);
52 if (fHandle
!= nullptr)
54 carla_debug("Destroying %s", kPoolName
);
55 rtsafe_memory_pool_destroy(fHandle
);
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
);
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
);
113 void clear() noexcept
115 if (this->fCount
== 0)
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
);
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
);
142 const T
value(data
->value
);
144 _deleteRT(entry
, data
);
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,);
157 entry
->next
->prev
= entry
->prev
;
158 entry
->prev
->next
= entry
->next
;
160 entry
->next
= nullptr;
161 entry
->prev
= nullptr;
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
);
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
);
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
);
210 CARLA_PREVENT_VIRTUAL_HEAP_ALLOCATION
211 CARLA_DECLARE_NON_COPYABLE(RtLinkedList
)
214 // -----------------------------------------------------------------------
216 #endif // RT_LINKED_LIST_HPP_INCLUDED