#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2023 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License #ifndef NUCLEX_SUPPORT_COLLECTIONS_CONCURRENTQUEUE_H #define NUCLEX_SUPPORT_COLLECTIONS_CONCURRENTQUEUE_H #include "Nuclex/Support/Collections/ConcurrentCollection.h" // We delegate this implementation to the Boost-Licensed MoodyCamel library #include "Nuclex/Support/Collections/MoodyCamel/concurrentqueue.h" namespace Nuclex { namespace Support { namespace Collections { // ------------------------------------------------------------------------------------------- // /// /// Lock-free unbounded queue for 1:1, 1:n and n:n producer/consumer threads /// /// /// Type of elements that will be stored in the queue /// /// /// How the queue will be accessed from different threads /// /// /// /// Currently, this implementation is just an adapter around MoodyCamel's lock-free /// queue. Its performance is very good (if you build with NUCLEX_SUPPORT_BENCHMARKS, /// this adapter will be included in the benchmarks, too), but its memory footprint /// is probably an order of magnitude higher than you expect. /// /// /// Container type: unbounded segmented array queue /// /// /// Thread safety: any number of readers, any number of writers /// /// /// Exception guarantee: unknown, probably strong /// /// /// Footprint (stack): 348 bytes. /// Footprint (heap): ? /// template< typename TElement, ConcurrentAccessBehavior accessBehavior = ( ConcurrentAccessBehavior::MultipleProducersMultipleConsumers ) > class MoodyCamelQueue : public ConcurrentCollection { /// Initializes a new lock-free queue public: MoodyCamelQueue() : wrappedQueue() {} /// Initializes a new lock-free queue /// Capacity in items to reserve up-front public: explicit MoodyCamelQueue(std::size_t initialCapacity) : wrappedQueue(initialCapacity) {} /// Destroys the lock-free queue and all items still in it public: ~MoodyCamelQueue() override = default; /// Tries to append an element to the collection in a thread-safe manner /// Element that will be appended to the collection /// True if the element was appended, false if there was no space left public: bool TryAppend(const TElement &newItem) override { this->wrappedQueue.enqueue(newItem); return true; } /// Tries to append an element to the collection in a thread-safe manner /// Element that will be appended to the collection /// True if the element was appended, false if there was no space left public: bool TryAppend(TElement &&newItem) override { this->wrappedQueue.enqueue(std::move(newItem)); return true; } /// Tries to take an element from the queue /// Will receive the element taken from the queue /// /// True if an element was taken from the collection, false if the collection was empty /// public: bool TryTake(TElement &result) override { return this->wrappedQueue.try_dequeue(result); } /// Counts the numebr of elements current in the collection /// /// The approximate number of elements that have been in the collection during the call /// public: std::size_t Count() const override { return this->wrappedQueue.size_approx(); } /// Checks if the collection is empty /// True if the collection was probably empty during the call public: bool IsEmpty() const override { return (this->wrappedQueue.size_approx() == 0); } /// Lock-free queue from the MoodyCamel library we're wrapping private: moodycamel::MoodyCamelQueue wrappedQueue; }; // ------------------------------------------------------------------------------------------- // /* /// /// Multi-producer, multi-consumer version of the lock-free, unbounded queue /// /// Type of elements the queue will store template class MoodyCamelQueue< TElement, ConcurrentAccessBehavior::MultipleProducersMultipleConsumers > : ConcurrentCollection {}; */ }}} // namespace Nuclex::Support::Collections #endif // NUCLEX_SUPPORT_COLLECTIONS_CONCURRENTQUEUE_H