Skip to content

iceoryx_utils/internal/concurrent/lockfree_queue/index_queue.hpp🔗

Namespaces🔗

Name
iox
building block to easily create free function for logging in a library context
iox::concurrent

Classes🔗

Name
class iox::concurrent::LockFreeQueue
implements a lock free queue (i.e. container with FIFO order) of elements of type T with a fixed Capacity
class iox::concurrent::ResizeableLockFreeQueue
implements a lock free queue (i.e. container with FIFO order) of elements of type T with a maximum capacity MaxCapacity. The capacity can be defined to be anything between 0 and MaxCapacity at construction time or later at runtime using setCapacity. This is even possible while concurrent push and pop operations are executed, i.e. the queue does not have to be empty. Only one thread will succeed setting its desired capacity if there are more threads trying to change the capacity at the same time (it is unpredictable which thread).
class iox::concurrent::IndexQueue
lockfree queue capable of storing indices 0,1,... Capacity-1
struct iox::concurrent::IndexQueue::ConstructFull_t
struct iox::concurrent::IndexQueue::ConstructEmpty_t

Source code🔗

// Copyright (c) 2019, 2020 by Robert Bosch GmbH, Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

#ifndef IOX_UTILS_LOCKFREE_QUEUE_INDEX_QUEUE_HPP
#define IOX_UTILS_LOCKFREE_QUEUE_INDEX_QUEUE_HPP

#include "iceoryx_utils/cxx/optional.hpp"
#include "iceoryx_utils/internal/concurrent/lockfree_queue/buffer.hpp"
#include "iceoryx_utils/internal/concurrent/lockfree_queue/cyclic_index.hpp"

#include <atomic>
#include <type_traits>

namespace iox
{
namespace concurrent
{
template <typename ElementType, uint64_t Capacity>
class LockFreeQueue;

template <typename ElementType, uint64_t Capacity>
class ResizeableLockFreeQueue;

template <uint64_t Capacity, typename ValueType = uint64_t>
class IndexQueue
{
  public:
    static_assert(std::is_unsigned<ValueType>::value, "ValueType must be an unsigned integral type");

    using value_t = ValueType;

    struct ConstructFull_t
    {
    };

    struct ConstructEmpty_t
    {
    };

    static constexpr ConstructFull_t ConstructFull{};
    static constexpr ConstructEmpty_t ConstructEmpty{};

    ~IndexQueue() = default;
    IndexQueue(const IndexQueue&) = delete;
    IndexQueue(IndexQueue&&) = delete;
    IndexQueue& operator=(const IndexQueue&) = delete;
    IndexQueue& operator=(IndexQueue&&) = delete;

    IndexQueue(ConstructEmpty_t = ConstructEmpty) noexcept;

    IndexQueue(ConstructFull_t) noexcept;

    constexpr uint64_t capacity() const noexcept;

    bool empty() const noexcept;

    void push(const ValueType index) noexcept;

    cxx::optional<ValueType> pop() noexcept;

    cxx::optional<ValueType> popIfFull() noexcept;

    cxx::optional<ValueType> popIfSizeIsAtLeast(uint64_t size) noexcept;

  private:
    template <typename ElementType, uint64_t Cap>
    friend class LockFreeQueue;

    template <typename ElementType, uint64_t Cap>
    friend class ResizeableLockFreeQueue;

    // remark: a compile time check whether Index is actually lock free would be nice
    // note: there is a way  with is_always_lock_free in c++17 (which we cannot use here)
    using Index = CyclicIndex<Capacity>;
    using Cell = std::atomic<Index>;

    Cell m_cells[Capacity];

    std::atomic<Index> m_readPosition;
    std::atomic<Index> m_writePosition;

    Index loadvalueAt(const Index& position, std::memory_order memoryOrder = std::memory_order_relaxed) const;

    bool pop(ValueType& index) noexcept;

    bool popIfSizeIsAtLeast(uint64_t minSize, ValueType& index) noexcept;

    bool popIfFull(ValueType& index) noexcept;
};
} // namespace concurrent
} // namespace iox

#include "index_queue.inl"

#endif // IOX_UTILS_LOCKFREE_QUEUE_INDEX_QUEUE_HPP

Updated on 17 June 2021 at 11:15:26 CEST