Nugget
fixed_list.h
1 // Copyright (c) Electronic Arts Inc. All rights reserved.
4 
6 // This file implements a list which uses a fixed size memory pool for its nodes.
8 
9 
10 #ifndef EASTL_FIXED_LIST_H
11 #define EASTL_FIXED_LIST_H
12 
13 
14 #include <EASTL/list.h>
15 #include <EASTL/internal/fixed_pool.h>
16 
17 #if defined(EA_PRAGMA_ONCE_SUPPORTED)
18  #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.
19 #endif
20 
21 
22 
23 namespace eastl
24 {
31  #ifndef EASTL_FIXED_LIST_DEFAULT_NAME
32  #define EASTL_FIXED_LIST_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " fixed_list" // Unless the user overrides something, this is "EASTL fixed_list".
33  #endif
34 
35 
38  #ifndef EASTL_FIXED_LIST_DEFAULT_ALLOCATOR
39  #define EASTL_FIXED_LIST_DEFAULT_ALLOCATOR overflow_allocator_type(EASTL_FIXED_LIST_DEFAULT_NAME)
40  #endif
41 
42 
43 
65  template <typename T, size_t nodeCount, bool bEnableOverflow = true, typename OverflowAllocator = EASTLAllocatorType>
66  class fixed_list : public list<T, fixed_node_allocator<sizeof(typename list<T>::node_type),
67  nodeCount, EASTL_ALIGN_OF(typename list<T>::node_type), 0, bEnableOverflow, OverflowAllocator> >
68  {
69  public:
70  typedef fixed_node_allocator<sizeof(typename list<T>::node_type), nodeCount,
71  EASTL_ALIGN_OF(typename list<T>::node_type), 0, bEnableOverflow, OverflowAllocator> fixed_allocator_type;
72  typedef OverflowAllocator overflow_allocator_type;
75  typedef typename base_type::size_type size_type;
76  typedef typename base_type::value_type value_type;
77  typedef typename base_type::node_type node_type;
78  typedef typename base_type::iterator iterator;
79 
80  enum { kMaxSize = nodeCount };
81 
82  using base_type::assign;
83  using base_type::resize;
84  using base_type::insert;
85  using base_type::size;
86  using base_type::get_allocator;
87 
88  protected:
89  char mBuffer[fixed_allocator_type::kBufferSize]; // kBufferSize will take into account alignment requirements.
90 
91  using base_type::internalAllocator;
92 
93  public:
94  fixed_list();
95  explicit fixed_list(const overflow_allocator_type& overflowAllocator); // Only applicable if bEnableOverflow is true.
96  explicit fixed_list(size_type n); // Currently we don't support overflowAllocator specification for other constructors, for simplicity.
97  fixed_list(size_type n, const value_type& value);
98  fixed_list(const this_type& x);
99  fixed_list(this_type&& x);
100  fixed_list(this_type&&, const overflow_allocator_type& overflowAllocator);
101  fixed_list(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator = EASTL_FIXED_LIST_DEFAULT_ALLOCATOR);
102 
103  template <typename InputIterator>
104  fixed_list(InputIterator first, InputIterator last);
105 
106  this_type& operator=(const this_type& x);
108  this_type& operator=(this_type&& x);
109 
110  void swap(this_type& x);
111  void reset_lose_memory(); // This is a unilateral reset to an initially empty state. No destructors are called, no deallocation occurs.
112  size_type max_size() const; // Returns the max fixed size, which is the user-supplied nodeCount parameter.
113  bool full() const; // Returns true if the fixed space has been fully allocated. Note that if overflow is enabled, the container size can be greater than nodeCount but full() could return true because the fixed space may have a recently freed slot.
114  bool has_overflowed() const; // Returns true if the allocations spilled over into the overflow allocator. Meaningful only if overflow is enabled.
115  bool can_overflow() const; // Returns the value of the bEnableOverflow template parameter.
116 
117  // OverflowAllocator
118  const overflow_allocator_type& get_overflow_allocator() const EA_NOEXCEPT;
119  overflow_allocator_type& get_overflow_allocator() EA_NOEXCEPT;
120  void set_overflow_allocator(const overflow_allocator_type& allocator);
121  }; // fixed_list
122 
123 
124 
126  // fixed_list
128 
129  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
131  : base_type(fixed_allocator_type(mBuffer))
132  {
133  #if EASTL_NAME_ENABLED
134  internalAllocator().set_name(EASTL_FIXED_LIST_DEFAULT_NAME);
135  #endif
136  }
137 
138 
139  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
140  inline fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_list(const overflow_allocator_type& overflowAllocator)
141  : base_type(fixed_allocator_type(mBuffer, overflowAllocator))
142  {
143  #if EASTL_NAME_ENABLED
144  internalAllocator().set_name(EASTL_FIXED_LIST_DEFAULT_NAME);
145  #endif
146  }
147 
148 
149  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
150  inline fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_list(size_type n)
151  : base_type(fixed_allocator_type(mBuffer))
152  {
153  #if EASTL_NAME_ENABLED
154  internalAllocator().set_name(EASTL_FIXED_LIST_DEFAULT_NAME);
155  #endif
156 
157  resize(n);
158  }
159 
160 
161  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
162  inline fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_list(size_type n, const value_type& value)
163  : base_type(fixed_allocator_type(mBuffer))
164  {
165  #if EASTL_NAME_ENABLED
166  internalAllocator().set_name(EASTL_FIXED_LIST_DEFAULT_NAME);
167  #endif
168 
169  resize(n, value);
170  }
171 
172 
173  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
174  inline fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_list(const this_type& x)
175  : base_type(fixed_allocator_type(mBuffer))
176  {
177  internalAllocator().copy_overflow_allocator(x.internalAllocator());
178 
179  #if EASTL_NAME_ENABLED
180  internalAllocator().set_name(x.internalAllocator().get_name());
181  #endif
182 
183  assign(x.begin(), x.end());
184  }
185 
186 
187  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
188  inline fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_list(this_type&& x)
189  : base_type(fixed_allocator_type(mBuffer))
190  {
191  // Since we are a fixed_list, we can't normally swap pointers unless both this and
192  // x are using using overflow and the overflow allocators are equal. To do:
193  //if(has_overflowed() && x.has_overflowed() && (get_overflow_allocator() == x.get_overflow_allocator()))
194  //{
195  // We can swap contents and may need to swap the allocators as well.
196  //}
197 
198  // The following is currently identical to the fixed_vector(const this_type& x) code above. If it stays that
199  // way then we may want to make a shared implementation.
200  internalAllocator().copy_overflow_allocator(x.internalAllocator());
201 
202  #if EASTL_NAME_ENABLED
203  internalAllocator().set_name(x.internalAllocator().get_name());
204  #endif
205 
206  assign(x.begin(), x.end());
207  }
208 
209 
210  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
211  inline fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_list(this_type&& x, const overflow_allocator_type& overflowAllocator)
212  : base_type(fixed_allocator_type(mBuffer, overflowAllocator))
213  {
214  // See comments above.
215  internalAllocator().copy_overflow_allocator(x.internalAllocator());
216 
217  #if EASTL_NAME_ENABLED
218  internalAllocator().set_name(x.internalAllocator().get_name());
219  #endif
220 
221  assign(x.begin(), x.end());
222  }
223 
224 
225  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
226  inline fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_list(std::initializer_list<value_type> ilist, const overflow_allocator_type& overflowAllocator)
227  : base_type(fixed_allocator_type(mBuffer, overflowAllocator))
228  {
229  assign(ilist.begin(), ilist.end());
230  }
231 
232 
233  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
234  template <typename InputIterator>
235  fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::fixed_list(InputIterator first, InputIterator last)
236  : base_type(fixed_allocator_type(mBuffer))
237  {
238  #if EASTL_NAME_ENABLED
239  internalAllocator().set_name(EASTL_FIXED_LIST_DEFAULT_NAME);
240  #endif
241 
242  assign(first, last);
243  }
244 
245 
246  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
247  inline typename fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::this_type&
248  fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::operator=(const this_type& x)
249  {
250  if(this != &x)
251  {
252  base_type::clear();
253 
254  #if EASTL_ALLOCATOR_COPY_ENABLED
255  internalAllocator() = x.internalAllocator(); // The primary effect of this is to copy the overflow allocator.
256  #endif
257 
258  base_type::assign(x.begin(), x.end()); // It would probably be better to implement this like list::operator=.
259  }
260  return *this;
261  }
262 
263 
264  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
265  inline typename fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::this_type&
266  fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::operator=(this_type&& x)
267  {
268  return operator=(x);
269  }
270 
271 
272  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
273  inline typename fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::this_type&
274  fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::operator=(std::initializer_list<value_type> ilist)
275  {
276  base_type::clear();
277  base_type::assign(ilist.begin(), ilist.end());
278  return *this;
279  }
280 
281 
282  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
283  inline void fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::swap(this_type& x)
284  {
285  // Fixed containers use a special swap that can deal with excessively large buffers.
286  eastl::fixed_swap(*this, x);
287  }
288 
289 
290  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
291  inline void fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::reset_lose_memory()
292  {
293  base_type::reset_lose_memory();
294  get_allocator().reset(mBuffer);
295  }
296 
297 
298  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
299  inline typename fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::size_type
300  fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::max_size() const
301  {
302  return kMaxSize;
303  }
304 
305 
306  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
307  inline bool fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::full() const
308  {
309  // Note: This implementation isn't right in the case of bEnableOverflow = true because it will return
310  // false for the case that there are free nodes from the buffer but also nodes from the dynamic heap.
311  // This can happen if the container exceeds the fixed size and then frees some of the nodes from the fixed buffer.
312  // The only simple fix for this is to take on another member variable which tracks whether this overflow
313  // has occurred at some point in the past.
314  return !internalAllocator().can_allocate(); // This is the quickest way of detecting this. has_overflowed uses a different method because it can't use this quick method.
315  }
316 
317 
318  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
319  inline bool fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::has_overflowed() const
320  {
321  #if EASTL_FIXED_SIZE_TRACKING_ENABLED // If we can use this faster pathway (as size() may be slow)...
322  return (internalAllocator().mPool.mnPeakSize > kMaxSize);
323  #else
324  return (size() > kMaxSize);
325  #endif
326  }
327 
328 
329  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
330  inline bool fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::can_overflow() const
331  {
332  return bEnableOverflow;
333  }
334 
335 
336  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
337  inline const typename fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::overflow_allocator_type&
338  fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::get_overflow_allocator() const EA_NOEXCEPT
339  {
340  return internalAllocator().get_overflow_allocator();
341  }
342 
343 
344  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
345  inline typename fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::overflow_allocator_type&
346  fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::get_overflow_allocator() EA_NOEXCEPT
347  {
348  return internalAllocator().get_overflow_allocator();
349  }
350 
351 
352  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
353  inline void
354  fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>::set_overflow_allocator(const overflow_allocator_type& allocator)
355  {
356  internalAllocator().set_overflow_allocator(allocator);
357  }
358 
359 
361  // global operators
363 
364  template <typename T, size_t nodeCount, bool bEnableOverflow, typename OverflowAllocator>
365  inline void swap(fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>& a,
366  fixed_list<T, nodeCount, bEnableOverflow, OverflowAllocator>& b)
367  {
368  // Fixed containers use a special swap that can deal with excessively large buffers.
369  eastl::fixed_swap(a, b);
370  }
371 
372 
373 } // namespace eastl
374 
375 
376 #endif // Header include guard
377 
378 
379 
380 
381 
382 
383 
384 
385 
386 
387 
388 
Definition: allocator.h:52
Definition: fixed_list.h:68
Definition: fixed_pool.h:607
Definition: list.h:277
Definition: initializer_list.h:38
EA Standard Template Library.
Definition: algorithm.h:288
Definition: list.h:161
Definition: list.h:147