Nvwa  1.1
fc_queue.h
Go to the documentation of this file.
1 // -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
2 // vim:tabstop=4:shiftwidth=4:expandtab:
3 
4 /*
5  * Copyright (C) 2009-2016 Wu Yongwei <adah at users dot sourceforge dot net>
6  *
7  * This software is provided 'as-is', without any express or implied
8  * warranty. In no event will the authors be held liable for any
9  * damages arising from the use of this software.
10  *
11  * Permission is granted to anyone to use this software for any purpose,
12  * including commercial applications, and to alter it and redistribute
13  * it freely, subject to the following restrictions:
14  *
15  * 1. The origin of this software must not be misrepresented; you must
16  * not claim that you wrote the original software. If you use this
17  * software in a product, an acknowledgement in the product
18  * documentation would be appreciated but is not required.
19  * 2. Altered source versions must be plainly marked as such, and must
20  * not be misrepresented as being the original software.
21  * 3. This notice may not be removed or altered from any source
22  * distribution.
23  *
24  * This file is part of Stones of Nvwa:
25  * http://sourceforge.net/projects/nvwa
26  *
27  */
28 
37 #ifndef NVWA_FC_QUEUE_H
38 #define NVWA_FC_QUEUE_H
39 
40 #include <assert.h> // assert
41 #include <stddef.h> // ptrdiff_t/size_t/NULL
42 #include <memory> // std::allocator
43 #include <new> // placement new
44 #include "_nvwa.h" // NVWA_NAMESPACE_*
45 #include "c++11.h" // _NOEXCEPT/_NOEXCEPT_/_NULLPTR
46 #include "type_traits.h" // nvwa::is_trivially_destructible
47 
48 #if NVWA_CXX11_MODE
49 #include <utility> // std::swap/std::declval
50 #else
51 #include <algorithm> // std::swap
52 #endif
53 
54 NVWA_NAMESPACE_BEGIN
55 
68 template <class _Tp, class _Alloc = std::allocator<_Tp> >
69 class fc_queue
70 {
71 public:
72  typedef _Tp value_type;
73  typedef _Alloc allocator_type;
74  typedef size_t size_type;
75  typedef value_type* pointer;
76  typedef const value_type* const_pointer;
77  typedef value_type& reference;
78  typedef const value_type& const_reference;
79 
95  explicit fc_queue(size_type max_size,
96  const allocator_type& alloc = allocator_type())
97  : _M_alloc(alloc)
98  {
99  assert(max_size != 0);
100  if (max_size + 1 == 0)
101  throw std::bad_alloc();
102  _M_begin = _M_alloc.allocate(max_size + 1);
103  _M_end = _M_begin + max_size + 1;
104  _M_head = _M_tail = _M_begin;
105  }
106 
115  fc_queue(const fc_queue& rhs);
116 
121  {
122  while (_M_head != _M_tail)
123  {
124  destroy(_M_head);
125  _M_head = increment(_M_head);
126  }
127  if (_M_begin)
128  _M_alloc.deallocate(_M_begin, _M_end - _M_begin);
129  }
130 
142  {
143  fc_queue temp(rhs);
144  swap(temp);
145  return *this;
146  }
147 
153  bool empty() const _NOEXCEPT
154  {
155  return _M_head == _M_tail;
156  }
157 
164  bool full() const _NOEXCEPT
165  {
166  return _M_head == increment(_M_tail);
167  }
168 
174  size_type capacity() const _NOEXCEPT
175  {
176  return _M_end - _M_begin - 1;
177  }
178 
184  size_type size() const _NOEXCEPT
185  {
186  ptrdiff_t dist = _M_tail - _M_head;
187  if (dist < 0)
188  dist += _M_end - _M_begin;
189  return dist;
190  }
191 
197  reference front()
198  {
199  assert(!empty());
200  return *_M_head;
201  }
202 
208  const_reference front() const
209  {
210  assert(!empty());
211  return *_M_head;
212  }
213 
219  reference back()
220  {
221  assert(!empty());
222  return *decrement(_M_tail);
223  }
224 
230  const_reference back() const
231  {
232  assert(!empty());
233  return *decrement(_M_tail);
234  };
235 
246  void push(const value_type& value)
247  {
248  construct(_M_tail, value);
249  if (full())
250  pop();
251  _M_tail = increment(_M_tail);
252  }
253 
261  void pop()
262  {
263  assert(!empty());
264  destroy(_M_head);
265  _M_head = increment(_M_head);
266  }
267 
275  bool contains(const value_type& value) const
276  {
277  pointer ptr = _M_head;
278  while (ptr != _M_tail)
279  {
280  if (*ptr == value)
281  return true;
282  ptr = increment(ptr);
283  }
284  return false;
285  }
286 
297  void swap(fc_queue& rhs)
298  _NOEXCEPT_(noexcept(std::swap(std::declval<allocator_type&>(),
299  std::declval<allocator_type&>())))
300  {
301  using std::swap;
302  swap(_M_alloc, rhs._M_alloc);
303  swap(_M_head, rhs._M_head);
304  swap(_M_tail, rhs._M_tail);
305  swap(_M_begin, rhs._M_begin);
306  swap(_M_end, rhs._M_end);
307  }
308 
314  allocator_type get_allocator() const
315  {
316  return _M_alloc;
317  }
318 
319 protected:
320  pointer _M_head;
321  pointer _M_tail;
322  pointer _M_begin;
323  pointer _M_end;
324  allocator_type _M_alloc;
325 
326 protected:
327  pointer increment(pointer ptr) const _NOEXCEPT
328  {
329  ++ptr;
330  if (ptr == _M_end)
331  ptr = _M_begin;
332  return ptr;
333  }
334  pointer decrement(pointer ptr) const _NOEXCEPT
335  {
336  if (ptr == _M_begin)
337  ptr = _M_end;
338  return --ptr;
339  }
340  void construct(void* ptr, const _Tp& value)
341  {
342  new (ptr) _Tp(value);
343  }
344  void destroy(void* ptr) _NOEXCEPT_(noexcept(std::declval<_Tp*>()->~_Tp()))
345  {
346  _M_destroy(ptr, is_trivially_destructible<_Tp>());
347  }
348 
349 private:
350  void _M_destroy(void*, true_type)
351  {}
352  void _M_destroy(void* ptr, false_type)
353  {
354  ((_Tp*)ptr)->~_Tp();
355  }
356 };
357 
358 template <class _Tp, class _Alloc>
360  : _M_head(_NULLPTR), _M_tail(_NULLPTR), _M_begin(_NULLPTR)
361 {
362  fc_queue temp(rhs.capacity(), rhs.get_allocator());
363  pointer ptr = rhs._M_head;
364  while (ptr != rhs._M_tail)
365  {
366  temp.push(*ptr);
367  ptr = rhs.increment(ptr);
368  }
369  swap(temp);
370 }
371 
382 template <class _Tp, class _Alloc>
384  _NOEXCEPT_(noexcept(lhs.swap(rhs)))
385 {
386  lhs.swap(rhs);
387 }
388 
389 NVWA_NAMESPACE_END
390 
391 #endif // NVWA_FC_QUEUE_H
void swap(fc_queue &rhs)
Exchanges the elements of two queues.
Definition: fc_queue.h:297
fc_queue(size_type max_size, const allocator_type &alloc=allocator_type())
Constructor that creates the queue with a maximum size (capacity).
Definition: fc_queue.h:95
Class to represent a fixed-capacity queue.
Definition: fc_queue.h:69
bool contains(const value_type &value) const
Checks whether the queue contains a specific element.
Definition: fc_queue.h:275
size_type capacity() const noexcept
Gets the maximum number of allowed elements in the queue.
Definition: fc_queue.h:174
void swap(fc_queue< _Tp, _Alloc > &lhs, fc_queue< _Tp, _Alloc > &rhs)
Exchanges the elements of two queues.
Definition: fc_queue.h:383
~fc_queue()
Destructor.
Definition: fc_queue.h:120
bool full() const noexcept
Checks whether the queue is full (containing the maximum allowed elements).
Definition: fc_queue.h:164
const_reference front() const
Gets the first element in the queue.
Definition: fc_queue.h:208
reference front()
Gets the first element in the queue.
Definition: fc_queue.h:197
bool empty() const noexcept
Checks whether the queue is empty (containing no elements).
Definition: fc_queue.h:153
size_type size() const noexcept
Gets the number of existing elements in the queue.
Definition: fc_queue.h:184
fc_queue & operator=(const fc_queue &rhs)
Assignment operator that copies all elements from another queue.
Definition: fc_queue.h:141
C++11 feature detection macros and workarounds.
void pop()
Discards the first element in the queue.
Definition: fc_queue.h:261
const_reference back() const
Gets the last element in the queue.
Definition: fc_queue.h:230
allocator_type get_allocator() const
Gets the allocator of the queue.
Definition: fc_queue.h:314
reference back()
Gets the last element in the queue.
Definition: fc_queue.h:219
Common definitions for preprocessing.
void push(const value_type &value)
Inserts a new element at the end of the queue.
Definition: fc_queue.h:246