00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00037 #ifndef NVWA_FC_QUEUE_H
00038 #define NVWA_FC_QUEUE_H
00039
00040 #include <assert.h>
00041 #include <stddef.h>
00042 #include <memory>
00043 #include <new>
00044 #include "_nvwa.h"
00045 #include "c++11.h"
00046 #include "type_traits.h"
00047
00048 #ifdef NVWA_CXX11_MODE
00049 #include <utility>
00050 #else
00051 #include <algorithm>
00052 #endif
00053
00054 NVWA_NAMESPACE_BEGIN
00055
00068 template <class _Tp, class _Alloc = std::allocator<_Tp> >
00069 class fc_queue
00070 {
00071 public:
00072 typedef _Tp value_type;
00073 typedef _Alloc allocator_type;
00074 typedef size_t size_type;
00075 typedef value_type* pointer;
00076 typedef const value_type* const_pointer;
00077 typedef value_type& reference;
00078 typedef const value_type& const_reference;
00079
00095 explicit fc_queue(size_type max_size,
00096 const allocator_type& alloc = allocator_type())
00097 : _M_alloc(alloc)
00098 {
00099 assert(max_size != 0);
00100 if (max_size + 1 == 0)
00101 throw std::bad_alloc();
00102 _M_begin = _M_alloc.allocate(max_size + 1);
00103 _M_end = _M_begin + max_size + 1;
00104 _M_head = _M_tail = _M_begin;
00105 }
00106
00115 fc_queue(const fc_queue& rhs);
00116
00120 ~fc_queue()
00121 {
00122 while (_M_head != _M_tail)
00123 {
00124 destroy(_M_head);
00125 _M_head = increment(_M_head);
00126 }
00127 if (_M_begin)
00128 _M_alloc.deallocate(_M_begin, _M_end - _M_begin);
00129 }
00130
00141 fc_queue& operator=(const fc_queue& rhs)
00142 {
00143 fc_queue temp(rhs);
00144 swap(temp);
00145 return *this;
00146 }
00147
00153 bool empty() const _NOEXCEPT
00154 {
00155 return _M_head == _M_tail;
00156 }
00157
00164 bool full() const _NOEXCEPT
00165 {
00166 return _M_head == increment(_M_tail);
00167 }
00168
00174 size_type capacity() const _NOEXCEPT
00175 {
00176 return _M_end - _M_begin - 1;
00177 }
00178
00184 size_type size() const _NOEXCEPT
00185 {
00186 ptrdiff_t dist = _M_tail - _M_head;
00187 if (dist < 0)
00188 dist += _M_end - _M_begin;
00189 return dist;
00190 }
00191
00197 reference front()
00198 {
00199 assert(!empty());
00200 return *_M_head;
00201 }
00202
00208 const_reference front() const
00209 {
00210 assert(!empty());
00211 return *_M_head;
00212 }
00213
00219 reference back()
00220 {
00221 assert(!empty());
00222 return *decrement(_M_tail);
00223 }
00224
00230 const_reference back() const
00231 {
00232 assert(!empty());
00233 return *decrement(_M_tail);
00234 };
00235
00246 void push(const value_type& value)
00247 {
00248 construct(_M_tail, value);
00249 if (full())
00250 pop();
00251 _M_tail = increment(_M_tail);
00252 }
00253
00261 void pop()
00262 {
00263 assert(!empty());
00264 destroy(_M_head);
00265 _M_head = increment(_M_head);
00266 }
00267
00275 bool contains(const value_type& value) const
00276 {
00277 pointer ptr = _M_head;
00278 while (ptr != _M_tail)
00279 {
00280 if (*ptr == value)
00281 return true;
00282 ptr = increment(ptr);
00283 }
00284 return false;
00285 }
00286
00297 void swap(fc_queue& rhs)
00298 _NOEXCEPT_(noexcept(swap(std::declval<allocator_type&>(),
00299 std::declval<allocator_type&>())))
00300 {
00301 using std::swap;
00302 swap(_M_alloc, rhs._M_alloc);
00303 swap(_M_head, rhs._M_head);
00304 swap(_M_tail, rhs._M_tail);
00305 swap(_M_begin, rhs._M_begin);
00306 swap(_M_end, rhs._M_end);
00307 }
00308
00314 allocator_type get_allocator() const
00315 {
00316 return _M_alloc;
00317 }
00318
00319 protected:
00320 pointer _M_head;
00321 pointer _M_tail;
00322 pointer _M_begin;
00323 pointer _M_end;
00324 allocator_type _M_alloc;
00325
00326 protected:
00327 pointer increment(pointer ptr) const _NOEXCEPT
00328 {
00329 ++ptr;
00330 if (ptr == _M_end)
00331 ptr = _M_begin;
00332 return ptr;
00333 }
00334 pointer decrement(pointer ptr) const _NOEXCEPT
00335 {
00336 if (ptr == _M_begin)
00337 ptr = _M_end;
00338 return --ptr;
00339 }
00340 void construct(void* ptr, const _Tp& value)
00341 {
00342 new (ptr) _Tp(value);
00343 }
00344 void destroy(void* ptr) _NOEXCEPT_(noexcept(std::declval<_Tp*>()->~_Tp()))
00345 {
00346 _M_destroy(ptr, is_trivially_destructible<_Tp>());
00347 }
00348
00349 private:
00350 void _M_destroy(void*, true_type)
00351 {}
00352 void _M_destroy(void* ptr, false_type)
00353 {
00354 ((_Tp*)ptr)->~_Tp();
00355 }
00356 };
00357
00358 template <class _Tp, class _Alloc>
00359 fc_queue<_Tp, _Alloc>::fc_queue(const fc_queue& rhs)
00360 : _M_head(NULL), _M_tail(NULL), _M_begin(NULL)
00361 {
00362 fc_queue temp(rhs.capacity(), rhs.get_allocator());
00363 pointer ptr = rhs._M_head;
00364 while (ptr != rhs._M_tail)
00365 {
00366 temp.push(*ptr);
00367 ptr = rhs.increment(ptr);
00368 }
00369 swap(temp);
00370 }
00371
00382 template <class _Tp, class _Alloc>
00383 void swap(fc_queue<_Tp, _Alloc>& lhs, fc_queue<_Tp, _Alloc>& rhs)
00384 _NOEXCEPT_(noexcept(lhs.swap(rhs)))
00385 {
00386 lhs.swap(rhs);
00387 }
00388
00389 NVWA_NAMESPACE_END
00390
00391 #endif // NVWA_FC_QUEUE_H