/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. // This is free and unencumbered software released into the public domain. // Anyone is free to copy, modify, publish, use, compile, sell, or // distribute this software, either in source code form or as a compiled // binary, for any purpose, commercial or non-commercial, and by any // means. // In jurisdictions that recognize copyright laws, the author or authors // of this software dedicate any and all copyright interest in the // software to the public domain. We make this dedication for the benefit // of the public at large and to the detriment of our heirs and // successors. We intend this dedication to be an overt act of // relinquishment in perpetuity of all present and future rights to this // software under copyright law. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // For more information, please refer to // C++ implementation of Dmitry Vyukov's non-intrusive lock free unbound MPSC queue // http://www.1024cores.net/home/lock-free-algorithms/queues/non-intrusive-mpsc-node-based-queue #ifndef __MPSC_BOUNDED_QUEUE_INCLUDED__ #define __MPSC_BOUNDED_QUEUE_INCLUDED__ #include #include namespace concqueue { template class mpsc_queue_t { public: mpsc_queue_t() : _head(reinterpret_cast(new buffer_node_aligned_t)) , _tail(_head.load(std::memory_order_relaxed)) { buffer_node_t* front = _head.load(std::memory_order_relaxed); front->next.store(NULL, std::memory_order_relaxed); } ~mpsc_queue_t() { T output; while (this->dequeue(output)) { } buffer_node_t* front = _head.load(std::memory_order_relaxed); delete front; } bool enqueue(const T& input) { buffer_node_t* node = reinterpret_cast(new buffer_node_aligned_t); node->data = input; node->next.store(NULL, std::memory_order_relaxed); buffer_node_t* prev_head = _head.exchange(node, std::memory_order_acq_rel); prev_head->next.store(node, std::memory_order_release); return true; } bool dequeue(T& output) { buffer_node_t* tail = _tail.load(std::memory_order_relaxed); buffer_node_t* next = tail->next.load(std::memory_order_acquire); if (next == NULL) { return false; } output = next->data; _tail.store(next, std::memory_order_release); delete tail; return true; } private: struct buffer_node_t { T data; std::atomic next; }; typedef typename std::aligned_storage::value>::type buffer_node_aligned_t; std::atomic _head; std::atomic _tail; mpsc_queue_t(const mpsc_queue_t&) {} void operator=(const mpsc_queue_t&) {} }; } #endif