Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:35:34

0001 
0002 //          Copyright Oliver Kowalke 2015.
0003 // Distributed under the Boost Software License, Version 1.0.
0004 //    (See accompanying file LICENSE_1_0.txt or copy at
0005 //          http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 
0008 #ifndef BOOST_FIBERS_DETAIL_SPINLOCK_QUEUE_H
0009 #define BOOST_FIBERS_DETAIL_SPINLOCK_QUEUE_H
0010 
0011 #include <cstddef>
0012 #include <cstring>
0013 #include <mutex>
0014 
0015 #include <boost/config.hpp>
0016 
0017 #include <boost/fiber/context.hpp>
0018 #include <boost/fiber/detail/config.hpp>
0019 #include <boost/fiber/detail/spinlock.hpp>
0020 
0021 #ifdef BOOST_HAS_ABI_HEADERS
0022 #  include BOOST_ABI_PREFIX
0023 #endif
0024 
0025 namespace boost {
0026 namespace fibers {
0027 namespace detail {
0028 
0029 class context_spinlock_queue {
0030 private:
0031     typedef context *   slot_type;
0032 
0033     mutable spinlock   splk_{};
0034     std::size_t                                 pidx_{ 0 };
0035     std::size_t                                 cidx_{ 0 };
0036     std::size_t                                 capacity_;
0037     slot_type                               *   slots_;
0038 
0039     void resize_() {
0040         slot_type * old_slots = slots_;
0041         slots_ = new slot_type[2*capacity_];
0042         std::size_t offset = capacity_ - cidx_;
0043         std::memcpy( slots_, old_slots + cidx_, offset * sizeof( slot_type) );
0044         if ( 0 < cidx_) {
0045             std::memcpy( slots_ + offset, old_slots, pidx_ * sizeof( slot_type) );
0046         }
0047         cidx_ = 0;
0048         pidx_ = capacity_ - 1;
0049         capacity_ *= 2;
0050         delete [] old_slots;
0051     }
0052 
0053     bool is_full_() const noexcept {
0054         return cidx_ == ((pidx_ + 1) % capacity_);
0055     }
0056 
0057     bool is_empty_() const noexcept {
0058         return cidx_ == pidx_;
0059     }
0060 
0061 public:
0062     context_spinlock_queue( std::size_t capacity = 4096) :
0063             capacity_{ capacity } {
0064         slots_ = new slot_type[capacity_];
0065     }
0066 
0067     ~context_spinlock_queue() {
0068         delete [] slots_;
0069     }
0070 
0071     context_spinlock_queue( context_spinlock_queue const&) = delete;
0072     context_spinlock_queue & operator=( context_spinlock_queue const&) = delete;
0073 
0074     bool empty() const noexcept {
0075         spinlock_lock lk{ splk_ };
0076         return is_empty_();
0077     }
0078 
0079     void push( context * c) {
0080         spinlock_lock lk{ splk_ };
0081         if ( is_full_() ) {
0082             resize_();
0083         }
0084         slots_[pidx_] = c;
0085         pidx_ = (pidx_ + 1) % capacity_;
0086     }
0087 
0088     context * pop() {
0089         spinlock_lock lk{ splk_ };
0090         context * c = nullptr;
0091         if ( ! is_empty_() ) {
0092             c = slots_[cidx_];
0093             cidx_ = (cidx_ + 1) % capacity_;
0094         }
0095         return c;
0096     }
0097 
0098     context * steal() {
0099         spinlock_lock lk{ splk_ };
0100         context * c = nullptr;
0101         if ( ! is_empty_() ) {
0102             c = slots_[cidx_];
0103             if ( c->is_context( type::pinned_context) ) {
0104                 return nullptr;
0105             }
0106             cidx_ = (cidx_ + 1) % capacity_;
0107         }
0108         return c;
0109     }
0110 };
0111 
0112 }}}
0113 
0114 #ifdef BOOST_HAS_ABI_HEADERS
0115 #  include BOOST_ABI_SUFFIX
0116 #endif
0117 
0118 #endif // BOOST_FIBERS_DETAIL_SPINLOCK_QUEUE_H