iceoryx_doc  1.0.1
resizeable_lockfree_queue.hpp
1 // Copyright (c) 2020 by Apex.AI Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // SPDX-License-Identifier: Apache-2.0
16 
17 #ifndef IOX_UTILS_CONCURRENT_RESIZEABLE_LOCKFREE_QUEUE_HPP
18 #define IOX_UTILS_CONCURRENT_RESIZEABLE_LOCKFREE_QUEUE_HPP
19 
20 #include "iceoryx_utils/concurrent/lockfree_queue.hpp"
21 #include "iceoryx_utils/cxx/type_traits.hpp"
22 #include "iceoryx_utils/cxx/vector.hpp"
23 
24 #include <atomic>
25 
26 namespace iox
27 {
28 namespace concurrent
29 {
37 
38 // Remark: We use protected inheritance to make the base class methods inaccessible for the user.
39 // We cannot use virtual functions since we need to use this class in shared memory.
40 // Some of the methods need to be rewritten specifically for this class, others simply redirect
41 // the call to the base class.
42 //
43 // Since supporting the resize (setCapacity) functionality has an impact on the runtime even
44 // if the feature is not used, we provide a queue wihout resize functionality in an additional
45 // base class that can be used separately.
46 template <typename ElementType, uint64_t MaxCapacity>
47 class ResizeableLockFreeQueue : protected LockFreeQueue<ElementType, MaxCapacity>
48 {
49  private:
51 
52  public:
53  using element_t = ElementType;
54  static constexpr uint64_t MAX_CAPACITY = MaxCapacity;
55 
56  ResizeableLockFreeQueue() = default;
57  ~ResizeableLockFreeQueue() = default;
58 
59  // deleted for now, can be implemented later if needed
60  // note: concurrent copying or moving in lockfree fashion is nontrivial
63  ResizeableLockFreeQueue& operator=(const ResizeableLockFreeQueue&) = delete;
64  ResizeableLockFreeQueue& operator=(ResizeableLockFreeQueue&&) = delete;
65 
66  ResizeableLockFreeQueue(const uint64_t initialCapacity) noexcept;
67 
70  static constexpr uint64_t maxCapacity() noexcept;
71 
72  using Base::empty;
73  using Base::pop;
74  using Base::size;
75  using Base::tryPush;
76 
80  uint64_t capacity() const noexcept;
81 
87  iox::cxx::optional<ElementType> push(const ElementType& value) noexcept;
88 
94  iox::cxx::optional<ElementType> push(ElementType&& value) noexcept;
95 
96  // overloads to set the capacity
97  // 1) The most general one allows providing a removeHandler to specify remove behavior.
98  // This could e.g. be to store them in a container.
99  // 2) The second overload discards removed elements.
100 
108 
114  template <typename Function,
115  typename = typename std::enable_if<cxx::is_invocable<Function, ElementType>::value>::type>
116  bool setCapacity(const uint64_t newCapacity, Function&& removeHandler) noexcept;
117 
123  bool setCapacity(const uint64_t newCapacity) noexcept;
124 
125  private:
126  using BufferIndex = typename Base::BufferIndex;
127  std::atomic<uint64_t> m_capacity{MaxCapacity};
128  std::atomic_flag m_resizeInProgress{false};
130 
136  uint64_t increaseCapacity(const uint64_t toIncrease) noexcept;
137 
145  template <typename Function>
146  uint64_t decreaseCapacity(const uint64_t toDecrease, Function&& removeHandler) noexcept;
147 
151  bool tryGetUsedIndex(BufferIndex& index) noexcept;
152 
153  template <typename T>
154  iox::cxx::optional<ElementType> pushImpl(T&& value) noexcept;
155 };
156 
157 } // namespace concurrent
158 } // namespace iox
159 
160 #include "iceoryx_utils/internal/concurrent/lockfree_queue/resizeable_lockfree_queue.inl"
161 
162 #endif // IOX_UTILS_CONCURRENT_RESIZEABLE_LOCKFREE_QUEUE_HPP
implements a lock free queue (i.e. container with FIFO order) of elements of type T with a fixed Capa...
Definition: lockfree_queue.hpp:35
bool tryPush(ElementType &&value) noexcept
tries to insert value in FIFO order, moves the value internally
Definition: lockfree_queue.inl:56
bool empty() const noexcept
check whether the queue is empty
Definition: lockfree_queue.inl:140
uint64_t size() const noexcept
get the number of stored elements in the queue
Definition: lockfree_queue.inl:146
iox::cxx::optional< ElementType > pop() noexcept
tries to remove value in FIFO order
Definition: lockfree_queue.inl:123
implements a lock free queue (i.e. container with FIFO order) of elements of type T with a maximum ca...
Definition: resizeable_lockfree_queue.hpp:48
uint64_t capacity() const noexcept
returns the current capacity of the queue
Definition: resizeable_lockfree_queue.inl:36
iox::cxx::optional< ElementType > push(const ElementType &value) noexcept
inserts value in FIFO order, always succeeds by removing the oldest value when the queue is detected ...
Definition: resizeable_lockfree_queue.inl:180
bool setCapacity(const uint64_t newCapacity, Function &&removeHandler) noexcept
Set the capacity to some value.
Definition: resizeable_lockfree_queue.inl:51
static constexpr uint64_t maxCapacity() noexcept
returns the maximum capacity of the queue
Definition: resizeable_lockfree_queue.inl:30
Optional implementation from the C++17 standard with C++11. The interface is analog to the C++17 stan...
Definition: optional.hpp:63
building block to easily create free function for logging in a library context
Definition: lockfree_queue.hpp:28