File indexing completed on 2023-10-25 10:05:38
0001 #ifndef CMSUTILS_BEUEUE_H
0002 #define CMSUTILS_BEUEUE_H
0003 #include <boost/intrusive_ptr.hpp>
0004 #include <cassert>
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 namespace cmsutils {
0037
0038 template <class T>
0039 class _bqueue_itr;
0040 template <class T>
0041 class bqueue;
0042 template <class T>
0043 class _bqueue_item;
0044 template <class T>
0045 void intrusive_ptr_add_ref(_bqueue_item<T> *it);
0046 template <class T>
0047 void intrusive_ptr_release(_bqueue_item<T> *it);
0048
0049 template <class T>
0050 class _bqueue_item {
0051 friend class bqueue<T>;
0052 friend class _bqueue_itr<T>;
0053 friend void intrusive_ptr_add_ref<T>(_bqueue_item<T> *it);
0054 friend void intrusive_ptr_release<T>(_bqueue_item<T> *it);
0055 void addRef() { ++refCount; }
0056 void delRef() {
0057 if ((--refCount) == 0)
0058 delete this;
0059 }
0060
0061 private:
0062 _bqueue_item() : back(0), value(), refCount(0) {}
0063 _bqueue_item(boost::intrusive_ptr<_bqueue_item<T> > tail, const T &val) : back(tail), value(val), refCount(0) {}
0064
0065 _bqueue_item(boost::intrusive_ptr<_bqueue_item<T> > tail, T &&val)
0066 : back(tail), value(std::move(val)), refCount(0) {}
0067
0068 template <typename... Args>
0069 _bqueue_item(boost::intrusive_ptr<_bqueue_item<T> > tail, Args &&...args)
0070 : back(tail), value(std::forward<Args>(args)...), refCount(0) {}
0071 boost::intrusive_ptr<_bqueue_item<T> > back;
0072 T const value;
0073 unsigned int refCount;
0074 };
0075
0076 template <class T>
0077 inline void intrusive_ptr_add_ref(_bqueue_item<T> *it) {
0078 it->addRef();
0079 }
0080 template <class T>
0081 inline void intrusive_ptr_release(_bqueue_item<T> *it) {
0082 it->delRef();
0083 }
0084
0085
0086
0087 template <class T>
0088 class _bqueue_itr {
0089 public:
0090
0091
0092 const T *operator->() const { return &it->value; }
0093 const T &operator*() const { return it->value; }
0094 _bqueue_itr<T> &operator--() {
0095 it = it->back.get();
0096 return *this;
0097 }
0098 _bqueue_itr<T> &operator++() {
0099 it = it->back.get();
0100 return *this;
0101 }
0102 const _bqueue_itr<T> &operator--() const {
0103 it = it->back.get();
0104 return *this;
0105 }
0106 bool operator==(const _bqueue_itr<T> &t2) const { return t2.it == it; }
0107 bool operator!=(const _bqueue_itr<T> &t2) const { return t2.it != it; }
0108
0109 const _bqueue_itr<T> &operator=(const _bqueue_itr<T> &t2) {
0110 it = t2.it;
0111 return *this;
0112 }
0113 friend class bqueue<T>;
0114
0115 private:
0116
0117 _bqueue_itr(const _bqueue_item<T> *t) : it(t) {}
0118 _bqueue_item<T> const *it;
0119 };
0120
0121 template <class T>
0122 class bqueue {
0123 public:
0124 typedef T value_type;
0125 typedef unsigned short int size_type;
0126 typedef _bqueue_item<value_type> item;
0127 typedef boost::intrusive_ptr<_bqueue_item<value_type> > itemptr;
0128 typedef _bqueue_itr<value_type> iterator;
0129 typedef _bqueue_itr<value_type> const_iterator;
0130
0131 bqueue() : m_size(0), m_head(), m_tail() {}
0132 ~bqueue() {}
0133
0134 bqueue(const bqueue<T> &cp) : m_size(cp.m_size), m_head(cp.m_head), m_tail(cp.m_tail) {}
0135
0136
0137 bqueue(bqueue<T> &&cp) noexcept : m_size(cp.m_size), m_head(std::move(cp.m_head)), m_tail(std::move(cp.m_tail)) {
0138 cp.m_size = 0;
0139 }
0140
0141 bqueue &operator=(bqueue<T> const &) = default;
0142 bqueue &operator=(bqueue<T> &&cp) noexcept {
0143 using std::swap;
0144 swap(m_size, cp.m_size);
0145 swap(m_head, cp.m_head);
0146 swap(m_tail, cp.m_tail);
0147 return *this;
0148 }
0149
0150 void swap(bqueue<T> &cp) {
0151 using std::swap;
0152 swap(m_size, cp.m_size);
0153 swap(m_head, cp.m_head);
0154 swap(m_tail, cp.m_tail);
0155 }
0156
0157 bqueue<T> fork() const { return *this; }
0158
0159
0160 void push_back(const T &val) {
0161 m_tail = itemptr(new item(this->m_tail, val));
0162 if ((++m_size) == 1) {
0163 m_head = m_tail;
0164 };
0165 }
0166
0167
0168 void push_back(T &&val) {
0169 m_tail = itemptr(new item(this->m_tail, std::forward<T>(val)));
0170 if ((++m_size) == 1) {
0171 m_head = m_tail;
0172 };
0173 }
0174
0175
0176 template <typename... Args>
0177 void emplace_back(Args &&...args) {
0178 m_tail = itemptr(new item(this->m_tail, std::forward<Args>(args)...));
0179 if ((++m_size) == 1) {
0180 m_head = m_tail;
0181 };
0182 }
0183
0184 void pop_back() {
0185 assert(m_size > 0);
0186 --m_size;
0187 m_tail = m_tail->back;
0188 if (m_size == 0)
0189 m_head = nullptr;
0190 }
0191
0192
0193 const T &front() const { return m_head->value; }
0194
0195 const T &back() const { return m_tail->value; }
0196
0197 const_iterator rbegin() const { return m_tail.get(); }
0198 const_iterator rend() const { return nullptr; }
0199 const_iterator begin() const { return m_tail.get(); }
0200 const_iterator end() const { return nullptr; }
0201 size_type size() const { return m_size; }
0202 bool empty() const { return m_size == 0; }
0203 const T &operator[](size_type i) const {
0204 int idx = m_size - i - 1;
0205 const_iterator it = rbegin();
0206 while (idx-- > 0)
0207 --it;
0208 return *it;
0209 }
0210
0211 bool shared() {
0212
0213
0214
0215 return (m_size > 0) && (m_head->refCount > 2);
0216 }
0217
0218
0219
0220 void join(bqueue<T> &other) {
0221 assert(!other.shared());
0222 using std::swap;
0223 if (m_size == 0) {
0224 swap(m_head, other.m_head);
0225 swap(m_tail, other.m_tail);
0226 swap(m_size, other.m_size);
0227 } else {
0228 other.m_head->back = this->m_tail;
0229 m_tail = other.m_tail;
0230 m_size += other.m_size;
0231 other.clear();
0232 }
0233 }
0234
0235 void clear() {
0236 m_head = m_tail = nullptr;
0237 m_size = 0;
0238 }
0239
0240 private:
0241 size_type m_size;
0242 itemptr m_head, m_tail;
0243 };
0244
0245 template <typename T>
0246 void swap(bqueue<T> &rh, bqueue<T> &lh) {
0247 rh.swap(lh);
0248 }
0249
0250 }
0251
0252 #endif