nlib
Nqueue.h
Go to the documentation of this file.
1 
2 /*--------------------------------------------------------------------------------*
3  Project: CrossRoad
4  Copyright (C)Nintendo All rights reserved.
5 
6  These coded instructions, statements, and computer programs contain proprietary
7  information of Nintendo and/or its licensed developers and are protected by
8  national and international copyright laws. They may not be disclosed to third
9  parties or copied or duplicated in any form, in whole or in part, without the
10  prior written consent of Nintendo.
11 
12  The content herein is highly confidential and should be handled accordingly.
13  *--------------------------------------------------------------------------------*/
14 
15 #pragma once
16 #ifndef INCLUDE_NN_NLIB_NQUEUE_H_
17 #define INCLUDE_NN_NLIB_NQUEUE_H_
18 
19 #include <memory>
20 #include <utility>
21 #include "nn/nlib/Swap.h"
22 #include "nn/nlib/Nlist.h"
23 #include "nn/nlib/TypeTraits.h"
24 
25 NLIB_NAMESPACE_BEGIN
26 
27 extern void* nqueue_enabler;
28 
29 template <class T, class AL = std::allocator<char> >
31  public:
32  NLIB_CEXPR Nqueue() NLIB_NOEXCEPT : beg1_(0), end1_(0), beg2_(0), end2_(0) {}
34 #ifdef __cpp_rvalue_references
36  : beg1_(rhs.beg1_), end1_(rhs.end1_), beg2_(rhs.beg2_), end2_(rhs.end2_),
37  list_(std::move(rhs.list_)) {
38  beg1_ = end1_ = beg2_ = end2_ = 0;
39  }
41  beg1_ = rhs.beg1_;
42  end1_ = rhs.end1_;
43  beg2_ = rhs.beg2_;
44  end2_ = rhs.end2_;
45  list_ = std::move(rhs.list_);
46  beg1_ = end1_ = beg2_ = end2_ = 0;
47  return *this;
48  }
49 #endif
51  : beg1_(rhs.beg1_), end1_(rhs.end1_), beg2_(rhs.beg2_), end2_(rhs.end2_),
52  list_(rhs.list_, move_tag()) {
53  beg1_ = end1_ = beg2_ = end2_ = 0;
54  }
56  beg1_ = rhs.beg1_;
57  end1_ = rhs.end1_;
58  beg2_ = rhs.beg2_;
59  end2_ = rhs.end2_;
60  list_.assign(rhs.list_, move_tag());
61  beg1_ = end1_ = beg2_ = end2_ = 0;
62  return *this;
63  }
64  size_t size() const NLIB_NOEXCEPT { return (end1_ - beg1_) + (end2_ - beg2_); }
65  size_t capacity() const NLIB_NOEXCEPT { return list_.capacity(); }
66  bool empty() const NLIB_NOEXCEPT { return end1_ - beg1_ == 0 && end2_ - beg2_ == 0; }
67  T* push_back() NLIB_NOEXCEPT;
68 #ifdef __cpp_rvalue_references
69  T* push_back(T&& rhs) NLIB_NOEXCEPT;
70 #endif
71  bool pop_front() NLIB_NOEXCEPT {
72  T tmp;
73  return this->pop_front_swap(&tmp);
74  }
75  bool push_back_swap(T* v) NLIB_NOEXCEPT {
76  T* tmp = this->push_back();
77  if (!tmp || !v) return false;
78  using std::swap;
79  swap(*tmp, *v);
80  return true;
81  }
82  bool pop_front_swap(T* v) NLIB_NOEXCEPT;
83  NLIB_DEPRECATED void swap(Nqueue& rhs) NLIB_NOEXCEPT { // NOLINT
84  using std::swap;
85  swap(beg1_, rhs.beg1_);
86  swap(end1_, rhs.end1_);
87  swap(beg2_, rhs.beg2_);
88  swap(end2_, rhs.end2_);
89  swap(list_, rhs.list_);
90  }
91 
92  private:
93  uint32_t beg1_;
94  uint32_t end1_;
95  uint32_t beg2_;
96  uint32_t end2_;
97  Nlist<T, AL> list_;
99 };
100 
101 template <class T, class AL>
103  if (end1_ != beg2_ && beg2_ != end2_) {
104  using std::swap;
105  swap(list_[end1_++], list_[beg2_++]);
106  if (beg2_ != end2_) {
107  swap(list_[end1_++], list_[beg2_++]);
108  }
109  if (beg2_ == end2_) {
110  beg2_ = beg1_;
111  end2_ = end1_;
112  beg1_ = end1_ = 0;
113  }
114  }
115  if (list_.size() == end2_) {
116  T* tmp = list_.push_back();
117  if (tmp) ++end2_;
118  return tmp;
119  } else {
120  return &list_[end2_++];
121  }
122 }
123 
124 #ifdef __cpp_rvalue_references
125 template <class T, class AL>
127  if (end1_ != beg2_ && beg2_ != end2_) {
128  using std::swap;
129  swap(list_[end1_++], list_[beg2_++]);
130  if (beg2_ != end2_) {
131  swap(list_[end1_++], list_[beg2_++]);
132  }
133  if (beg2_ == end2_) {
134  beg2_ = beg1_;
135  end2_ = end1_;
136  beg1_ = end1_ = 0;
137  }
138  }
139  if (list_.size() == end2_) {
140 #ifdef NLIB_HAS_NATIVE_TYPETRAITS
141  NLIB_STATIC_ASSERT(std::is_nothrow_move_constructible<T>::value);
142 #endif
143  T* tmp = list_.push_back(std::move(rhs));
144  if (tmp) ++end2_;
145  return tmp;
146  } else {
147 #ifdef NLIB_HAS_NATIVE_TYPETRAITS
148  NLIB_STATIC_ASSERT(std::is_nothrow_move_assignable<T>::value);
149 #endif
150  list_[end2_] = std::move(rhs);
151  return &list_[end2_++];
152  }
153 }
154 #endif
155 
156 template <class T, class AL>
158  if (!v) return false;
159  using std::swap;
160  if (beg1_ != end1_) {
161  swap(*v, list_[beg1_++]);
162  if (beg1_ == end1_) {
163  beg1_ = end1_ = 0;
164  } else if ((end1_ - beg1_) * 8 < end1_) {
165  uint32_t cnt = static_cast<uint32_t>(end1_ - beg1_);
166  for (uint32_t i = 0; i < cnt; ++i) {
167  swap(list_[i], list_[beg1_ + i]);
168  }
169  beg1_ = 0;
170  end1_ = cnt;
171  }
172  } else if (beg2_ != end2_) {
173  NLIB_ASSERT(beg1_ + end1_ == 0);
174  swap(*v, list_[beg2_++]);
175  if (beg2_ == end2_) beg2_ = end2_ = 0;
176  } else {
177  return false;
178  }
179  return true;
180 }
181 
182 NLIB_NAMESPACE_END
183 
184 NLIB_DEFINE_STD_SWAP_T_BEGIN2(nn, nlib) // NOLINT
185 NLIB_DEFINE_STD_SWAP_T2(T, AL, NLIB_NS::Nqueue) // NOLINT
186 NLIB_DEFINE_STD_SWAP_T_END2(nn, nlib) // NOLINT
187 
188 #endif // INCLUDE_NN_NLIB_NQUEUE_H_
~Nqueue() noexcept
Destructor.
Definition: Nqueue.h:33
bool push_back_swap(T *v) noexcept
Adds an element to the queue, and then swaps that element with v using std:: swap.
Definition: Nqueue.h:75
Substitute definitions for the C++11 standard header type_traits. These substitute definitions are us...
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
Prohibits use of the copy constructor and assignment operator for the class specified by TypeName...
Definition: Config.h:179
Definition: Base64.h:25
A container-like class similar to std::queue that can store objects that do not have copy constructor...
Definition: Nqueue.h:30
Nqueue & assign(Nqueue &rhs, move_tag) noexcept
Corresponds to a move assignment operator.
Definition: Nqueue.h:55
constexpr Nqueue() noexcept
Instantiates the object with default parameters (default constructor). Creates an empty queue...
Definition: Nqueue.h:32
Nqueue(Nqueue &&rhs) noexcept
Instantiates the object (move constructor). This function is useful when using C++11.
Definition: Nqueue.h:35
void swap(Nqueue &rhs) noexcept
Swaps the container.
Definition: Nqueue.h:83
#define NLIB_DEPRECATED
Indicates that a function or something has been deprecated.
Definition: Config.h:109
Nqueue(Nqueue &rhs, move_tag) noexcept
Corresponds to a move constructor.
Definition: Nqueue.h:50
size_t size() const noexcept
Returns the number of stored elements.
Definition: Nqueue.h:64
Defines the class that resembles std::vector but can store objects that cannot be copied...
An empty structure indicating that an argument to a function needs to be moved.
Definition: Config.h:265
bool pop_front() noexcept
Removes the first element from the front of the queue.
Definition: Nqueue.h:71
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
Definition: Config.h:105
#define NLIB_CEXPR
Defines constexpr if it is available for use. If not, holds an empty string.
Definition: Config.h:107
A container-like class similar to std::vector that can store objects that do not have copy constructo...
Definition: Nlist.h:32
bool empty() const noexcept
Checks whether the container is empty.
Definition: Nqueue.h:66
#define NLIB_FINAL
Defines final if it is available for use. If not, holds an empty string.
Definition: Config.h:245
#define NLIB_STATIC_ASSERT(exp)
Defines a static assertion. Uses static_assert if it is available for use.
Definition: Config.h:170
size_t capacity() const noexcept
Returns the number of allocated elements.
Definition: Nqueue.h:65
Nqueue & operator=(Nqueue &&rhs) noexcept
Move assignment operator. This function is useful when using C++11.
Definition: Nqueue.h:40