Sierra Toolkit  Version of the Day
memory_eastl.h
1 /*
2 Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7 
8 1. Redistributions of source code must retain the above copyright
9  notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11  notice, this list of conditions and the following disclaimer in the
12  documentation and/or other materials provided with the distribution.
13 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14  its contributors may be used to endorse or promote products derived
15  from this software without specific prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 
30 // EASTL/memory.h
31 //
32 // Copyright (c) 2005, Electronic Arts. All rights reserved.
33 // Written and maintained by Paul Pedriana.
34 // The uninitialized_move function was written by Ryan Ingram.
36 
38 // This file implements the following functions from the C++ standard that
39 // are found in the <memory> header:
40 //
41 // Temporary memory:
42 // get_temporary_buffer
43 // return_temporary_buffer
44 //
45 // Uninitialized operations:
46 // These are the same as the copy, fill, and fill_n algorithms, except that
47 // they *construct* the destination with the source values rather than assign
48 // the destination with the source values.
49 //
50 // uninitialized_copy
51 // uninitialized_fill
52 // uninitialized_fill_n
53 // uninitialized_move - Extention to standard functionality.
54 // uninitialized_copy_ptr - Extention to standard functionality.
55 // uninitialized_fill_ptr - Extention to standard functionality.
56 // uninitialized_fill_n_ptr - Extention to standard functionality.
57 // uninitialized_copy_fill - Extention to standard functionality.
58 // uninitialized_fill_copy - Extention to standard functionality.
59 // uninitialized_copy_copy - Extention to standard functionality.
60 //
61 // In-place destructor helpers:
62 // destruct(T*)
63 // destruct(first, last)
64 //
66 
67 
68 #ifndef EASTL_MEMORY_H
69 #define EASTL_MEMORY_H
70 
71 
72 #include <stk_util/util/config_eastl.h>
73 #include <stk_util/util/generic_iterator_eastl.h>
74 #include <stk_util/util/type_traits_eastl.h>
75 #include <stk_util/util/algorithm_eastl.h>
76 #include <stk_util/util/allocator_eastl.h>
77 
78 #ifdef _MSC_VER
79  #pragma warning(push, 0)
80 #endif
81 #include <stdlib.h>
82 #ifdef _MSC_VER
83  #pragma warning(pop)
84 #endif
85 
86 #ifdef _MSC_VER
87  #pragma warning(push)
88  #pragma warning(disable: 4530) // C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
89 #endif
90 
91 
92 namespace eastl
93 {
94 
99  #ifndef EASTL_TEMP_DEFAULT_NAME
100  #define EASTL_TEMP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " temp" // Unless the user overrides something, this is "EASTL temp".
101  #endif
102 
103 
121  template <typename T>
122  pair<T*, ptrdiff_t> get_temporary_buffer(ptrdiff_t n, size_t alignment = 0, size_t alignmentOffset = 0, const char* pName = EASTL_TEMP_DEFAULT_NAME)
123  {
124  EASTLAllocatorType allocator(*EASTLAllocatorDefault(), pName);
125  return eastl::pair<T*, ptrdiff_t>(static_cast<T*>(EASTLAllocAligned(allocator, n * sizeof(T), alignment, alignmentOffset)), n);
126  }
127 
128 
142  template <typename T>
143  void return_temporary_buffer(T* p, ptrdiff_t n = 0)
144  {
145  EASTLAllocatorType& allocator(*EASTLAllocatorDefault());
146  EASTLFree(allocator, p, n * sizeof(T));
147  }
148 
149 
150 
168 
169  template <bool hasTrivialMove, typename iteratorTag>
171  {
172  template <typename ForwardIterator, typename ForwardIteratorDest>
173  static ForwardIteratorDest do_move_start(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
174  {
175  typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
176 
177  #if EASTL_EXCEPTIONS_ENABLED
178  ForwardIteratorDest origDest(dest);
179  try
180  {
181  for(; first != last; ++first, ++dest)
182  ::new(&*dest) value_type(*first);
183  }
184  catch(...)
185  {
186  for(; origDest < dest; ++origDest)
187  origDest->~value_type();
188  throw;
189  }
190  #else
191  for(; first != last; ++first, ++dest)
192  ::new(&*dest) value_type(*first);
193  #endif
194 
195  return dest;
196  }
197 
198  template <typename ForwardIterator, typename ForwardIteratorDest>
199  static ForwardIteratorDest do_move_commit(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest) //throw()
200  {
201  typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
202  for(; first != last; ++first, ++dest)
203  first->~value_type();
204 
205  return dest;
206  }
207 
208  template <typename ForwardIterator, typename ForwardIteratorDest>
209  static ForwardIteratorDest do_move_abort(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest) //throw()
210  {
211  typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
212  for(; first != last; ++first, ++dest)
213  dest->~value_type();
214  return dest;
215  }
216  };
217 
218  template <>
219  struct uninitialized_move_impl<true, EASTL_ITC_NS::random_access_iterator_tag>
220  {
221  template <typename T>
222  static T* do_move_start(T* first, T* last, T* dest)
223  {
224  return (T*)memcpy(dest, first, (size_t)((uintptr_t)last - (uintptr_t)first)) + (last - first);
225  }
226 
227  template <typename T>
228  static T* do_move_commit(T* first, T* last, T* dest)
229  {
230  return dest + (last - first);
231  }
232 
233  template <typename T>
234  static T* do_move_abort(T* first, T* last, T* dest)
235  {
236  return dest + (last - first);
237  }
238  };
239 
240 
265  template <typename ForwardIterator, typename ForwardIteratorDest>
266  inline ForwardIteratorDest uninitialized_move_start(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
267  {
268  typedef typename eastl::iterator_traits<ForwardIterator>::iterator_category IC;
269  typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type_input;
270  typedef typename eastl::iterator_traits<ForwardIteratorDest>::value_type value_type_output;
271 
272  const bool bHasTrivialMove = type_and<has_trivial_relocate<value_type_input>::value,
273  is_pointer<ForwardIterator>::value,
274  is_pointer<ForwardIteratorDest>::value,
275  is_same<value_type_input, value_type_output>::value>::value;
276 
278  }
279 
280  template <typename ForwardIterator, typename ForwardIteratorDest>
281  inline ForwardIteratorDest uninitialized_move_commit(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
282  {
283  typedef typename eastl::iterator_traits<ForwardIterator>::iterator_category IC;
284  typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type_input;
285  typedef typename eastl::iterator_traits<ForwardIteratorDest>::value_type value_type_output;
286 
287  const bool bHasTrivialMove = type_and<has_trivial_relocate<value_type_input>::value,
288  is_pointer<ForwardIterator>::value,
289  is_pointer<ForwardIteratorDest>::value,
290  is_same<value_type_input, value_type_output>::value>::value;
291 
293  }
294 
295  template <typename ForwardIterator, typename ForwardIteratorDest>
296  inline ForwardIteratorDest uninitialized_move_abort(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
297  {
298  typedef typename eastl::iterator_traits<ForwardIterator>::iterator_category IC;
299  typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type_input;
300  typedef typename eastl::iterator_traits<ForwardIteratorDest>::value_type value_type_output;
301 
302  const bool bHasTrivialMove = type_and<has_trivial_relocate<value_type_input>::value,
303  is_pointer<ForwardIterator>::value,
304  is_pointer<ForwardIteratorDest>::value,
305  is_same<value_type_input, value_type_output>::value>::value;
306 
308  }
309 
317  template <typename ForwardIterator, typename ForwardIteratorDest>
318  inline ForwardIteratorDest uninitialized_move(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
319  {
320  ForwardIteratorDest result = uninitialized_move_start(first, last, dest);
321  uninitialized_move_commit(first, last, dest);
322 
323  return result;
324  }
325 
326 
327 
328 
329 
330  // uninitialized_copy
331  //
332  template <typename InputIterator, typename ForwardIterator>
333  inline ForwardIterator uninitialized_copy_impl(InputIterator first, InputIterator last, ForwardIterator dest, true_type)
334  {
335  return eastl::copy(first, last, dest); // The copy() in turn will use memcpy for POD types.
336  }
337 
338  template <typename InputIterator, typename ForwardIterator>
339  inline ForwardIterator uninitialized_copy_impl(InputIterator first, InputIterator last, ForwardIterator dest, false_type)
340  {
341  typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
342  ForwardIterator currentDest(dest);
343 
344  #if EASTL_EXCEPTIONS_ENABLED
345  try
346  {
347  for(; first != last; ++first, ++currentDest)
348  ::new(&*currentDest) value_type(*first);
349  }
350  catch(...)
351  {
352  for(; dest < currentDest; ++dest)
353  dest->~value_type();
354  throw;
355  }
356  #else
357  for(; first != last; ++first, ++currentDest)
358  ::new(&*currentDest) value_type(*first);
359  #endif
360 
361  return currentDest;
362  }
363 
378  template <typename InputIterator, typename ForwardIterator>
379  inline ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result)
380  {
381  typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
382 
383  // Note: has_trivial_assign isn't actually the right thing to use here, as it
384  // refers to assignment as opposed to construction. Bug Paul Pedriana if this
385  // is becoming a problem. In the meantime, this code assumes that if has_trivial_assign
386  // is present for a type, then has_trivial_copy is as well.
387  return uninitialized_copy_impl(first, last, result, has_trivial_assign<value_type>());
388  }
389 
396  template <typename First, typename Last, typename Result>
397  inline Result uninitialized_copy_ptr(First first, Last last, Result result)
398  {
399  typedef typename eastl::iterator_traits<generic_iterator<Result, void> >::value_type value_type;
400  const generic_iterator<Result, void> i(uninitialized_copy_impl(generic_iterator<First, void>(first),
403  has_trivial_assign<value_type>()));
404  return i.base();
405  }
406 
407 
408 
409 
410  // uninitialized_fill
411  //
412  template <typename ForwardIterator, typename T>
413  inline void uninitialized_fill_impl(ForwardIterator first, ForwardIterator last, const T& value, true_type)
414  {
415  eastl::fill(first, last, value);
416  }
417 
418  template <typename ForwardIterator, typename T>
419  void uninitialized_fill_impl(ForwardIterator first, ForwardIterator last, const T& value, false_type)
420  {
421  typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
422  ForwardIterator currentDest(first);
423 
424  #if EASTL_EXCEPTIONS_ENABLED
425  try
426  {
427  for(; currentDest != last; ++currentDest)
428  ::new(&*currentDest) value_type(value);
429  }
430  catch(...)
431  {
432  for(; first < currentDest; ++first)
433  first->~value_type();
434  throw;
435  }
436  #else
437  for(; currentDest != last; ++currentDest)
438  ::new(&*currentDest) value_type(value);
439  #endif
440  }
441 
452  template <typename ForwardIterator, typename T>
453  inline void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& value)
454  {
455  typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
456  uninitialized_fill_impl(first, last, value, has_trivial_assign<value_type>());
457  }
458 
465  template <typename T>
466  inline void uninitialized_fill_ptr(T* first, T* last, const T& value)
467  {
468  typedef typename eastl::iterator_traits<generic_iterator<T*, void> >::value_type value_type;
469  uninitialized_fill_impl(generic_iterator<T*, void>(first), generic_iterator<T*, void>(last), value, has_trivial_assign<value_type>());
470  }
471 
472 
473 
474 
475  // uninitialized_fill_n
476  //
477  template <typename ForwardIterator, typename Count, typename T>
478  inline void uninitialized_fill_n_impl(ForwardIterator first, Count n, const T& value, true_type)
479  {
480  eastl::fill_n(first, n, value);
481  }
482 
483  template <typename ForwardIterator, typename Count, typename T>
484  void uninitialized_fill_n_impl(ForwardIterator first, Count n, const T& value, false_type)
485  {
486  typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
487  ForwardIterator currentDest(first);
488 
489  #if EASTL_EXCEPTIONS_ENABLED
490  try
491  {
492  for(; n > 0; --n, ++currentDest)
493  ::new(&*currentDest) value_type(value);
494  }
495  catch(...)
496  {
497  for(; first < currentDest; ++first)
498  first->~value_type();
499  throw;
500  }
501  #else
502  for(; n > 0; --n, ++currentDest)
503  ::new(&*currentDest) value_type(value);
504  #endif
505  }
506 
517  template <typename ForwardIterator, typename Count, typename T>
518  inline void uninitialized_fill_n(ForwardIterator first, Count n, const T& value)
519  {
520  typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
521  uninitialized_fill_n_impl(first, n, value, has_trivial_assign<value_type>());
522  }
523 
530  template <typename T, typename Count>
531  inline void uninitialized_fill_n_ptr(T* first, Count n, const T& value)
532  {
533  typedef typename eastl::iterator_traits<generic_iterator<T*, void> >::value_type value_type;
534  uninitialized_fill_n_impl(generic_iterator<T*, void>(first), n, value, has_trivial_assign<value_type>());
535  }
536 
537 
538 
539 
545  template <typename InputIterator, typename ForwardIterator, typename T>
546  inline void uninitialized_copy_fill(InputIterator first1, InputIterator last1,
547  ForwardIterator first2, ForwardIterator last2, const T& value)
548  {
549  const ForwardIterator mid(eastl::uninitialized_copy(first1, last1, first2));
550 
551  #if EASTL_EXCEPTIONS_ENABLED
552  try
553  {
554  #endif
555  eastl::uninitialized_fill(mid, last2, value);
556  #if EASTL_EXCEPTIONS_ENABLED
557  }
558  catch(...)
559  {
560  for(; first2 < mid; ++first2)
561  first2->~value_type();
562  throw;
563  }
564  #endif
565  }
566 
567 
568 
569 
570 
575  template <typename ForwardIterator, typename T, typename InputIterator>
576  inline ForwardIterator
577  uninitialized_fill_copy(ForwardIterator result, ForwardIterator mid, const T& value, InputIterator first, InputIterator last)
578  {
579  eastl::uninitialized_fill(result, mid, value);
580 
581  #if EASTL_EXCEPTIONS_ENABLED
582  try
583  {
584  #endif
585  return eastl::uninitialized_copy(first, last, mid);
586  #if EASTL_EXCEPTIONS_ENABLED
587  }
588  catch(...)
589  {
590  for(; result < mid; ++result)
591  result->~value_type();
592  throw;
593  }
594  #endif
595  }
596 
597 
598 
604  template <typename InputIterator1, typename InputIterator2, typename ForwardIterator>
605  inline ForwardIterator
606  uninitialized_copy_copy(InputIterator1 first1, InputIterator1 last1,
607  InputIterator2 first2, InputIterator2 last2,
608  ForwardIterator result)
609  {
610  const ForwardIterator mid(eastl::uninitialized_copy(first1, last1, result));
611 
612  #if EASTL_EXCEPTIONS_ENABLED
613  try
614  {
615  #endif
616  return eastl::uninitialized_copy(first2, last2, mid);
617  #if EASTL_EXCEPTIONS_ENABLED
618  }
619  catch(...)
620  {
621  for(; result < mid; ++result)
622  result->~value_type();
623  throw;
624  }
625  #endif
626  }
627 
628 
629 
639  template <typename T>
640  inline void destruct(T* p)
641  {
642  p->~T();
643  }
644 
645 
646 
647  // destruct(first, last)
648  //
649  template <typename ForwardIterator>
650  inline void destruct_impl(ForwardIterator /*first*/, ForwardIterator /*last*/, true_type) // true means the type has a trivial destructor.
651  {
652  // Empty. The type has a trivial destructor.
653  }
654 
655  template <typename ForwardIterator>
656  inline void destruct_impl(ForwardIterator first, ForwardIterator last, false_type) // false means the type has a significant destructor.
657  {
658  typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
659 
660  for(; first != last; ++first)
661  (*first).~value_type();
662  }
663 
671  template <typename ForwardIterator>
672  inline void destruct(ForwardIterator first, ForwardIterator last)
673  {
674  typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
675  destruct_impl(first, last, eastl::has_trivial_destructor<value_type>());
676  }
677 
678 
679 } // namespace eastl
680 
681 
682 #ifdef _MSC_VER
683  #pragma warning(pop)
684 #endif
685 
686 
687 #endif // Header include guard
OutputIterator fill_n(OutputIterator first, Size n, const T &value)
void uninitialized_copy_fill(InputIterator first1, InputIterator last1, ForwardIterator first2, ForwardIterator last2, const T &value)
Definition: memory_eastl.h:546
ForwardIterator uninitialized_copy_copy(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, ForwardIterator result)
Definition: memory_eastl.h:606
void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T &value)
Definition: memory_eastl.h:453
OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)
void uninitialized_fill_n(ForwardIterator first, Count n, const T &value)
Definition: memory_eastl.h:518
void uninitialized_fill_n_ptr(T *first, Count n, const T &value)
Definition: memory_eastl.h:531
void destruct(T *p)
Definition: memory_eastl.h:640
void uninitialized_fill_ptr(T *first, T *last, const T &value)
Definition: memory_eastl.h:466
ForwardIterator uninitialized_fill_copy(ForwardIterator result, ForwardIterator mid, const T &value, InputIterator first, InputIterator last)
Definition: memory_eastl.h:577
ForwardIteratorDest uninitialized_move_start(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
Definition: memory_eastl.h:266
ForwardIteratorDest uninitialized_move(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
Definition: memory_eastl.h:318
Result uninitialized_copy_ptr(First first, Last last, Result result)
Definition: memory_eastl.h:397
void return_temporary_buffer(T *p, ptrdiff_t n=0)
Definition: memory_eastl.h:143
pair< T *, ptrdiff_t > get_temporary_buffer(ptrdiff_t n, size_t alignment=0, size_t alignmentOffset=0, const char *pName=EASTL_DEFAULT_NAME_PREFIX " temp")
Definition: memory_eastl.h:122
void fill(ForwardIterator first, ForwardIterator last, const T &value)
EA Standard Template Library.
ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result)
Definition: memory_eastl.h:379