File indexing completed on 2025-01-30 09:35:34
0001
0002
0003
0004
0005
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