Sierra Toolkit Version of the Day
memory_eastl.h
00001 /*
00002 Copyright (C) 2009-2010 Electronic Arts, Inc.  All rights reserved.
00003 
00004 Redistribution and use in source and binary forms, with or without
00005 modification, are permitted provided that the following conditions
00006 are met:
00007 
00008 1.  Redistributions of source code must retain the above copyright
00009     notice, this list of conditions and the following disclaimer.
00010 2.  Redistributions in binary form must reproduce the above copyright
00011     notice, this list of conditions and the following disclaimer in the
00012     documentation and/or other materials provided with the distribution.
00013 3.  Neither the name of Electronic Arts, Inc. ("EA") nor the names of
00014     its contributors may be used to endorse or promote products derived
00015     from this software without specific prior written permission.
00016 
00017 THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
00018 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00019 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00020 DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
00021 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00022 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00023 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00024 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027 */
00028 
00030 // EASTL/memory.h
00031 //
00032 // Copyright (c) 2005, Electronic Arts. All rights reserved.
00033 // Written and maintained by Paul Pedriana.
00034 // The uninitialized_move function was written by Ryan Ingram.
00036 
00038 // This file implements the following functions from the C++ standard that
00039 // are found in the <memory> header:
00040 //
00041 // Temporary memory:
00042 //    get_temporary_buffer
00043 //    return_temporary_buffer
00044 //
00045 // Uninitialized operations:
00046 //    These are the same as the copy, fill, and fill_n algorithms, except that
00047 //    they *construct* the destination with the source values rather than assign
00048 //    the destination with the source values.
00049 //
00050 //    uninitialized_copy
00051 //    uninitialized_fill
00052 //    uninitialized_fill_n
00053 //    uninitialized_move          - Extention to standard functionality.
00054 //    uninitialized_copy_ptr      - Extention to standard functionality.
00055 //    uninitialized_fill_ptr      - Extention to standard functionality.
00056 //    uninitialized_fill_n_ptr    - Extention to standard functionality.
00057 //    uninitialized_copy_fill     - Extention to standard functionality.
00058 //    uninitialized_fill_copy     - Extention to standard functionality.
00059 //    uninitialized_copy_copy     - Extention to standard functionality.
00060 //
00061 // In-place destructor helpers:
00062 //    destruct(T*)
00063 //    destruct(first, last)
00064 //
00066 
00067 
00068 #ifndef EASTL_MEMORY_H
00069 #define EASTL_MEMORY_H
00070 
00071 
00072 #include <stk_util/util/config_eastl.h>
00073 #include <stk_util/util/generic_iterator_eastl.h>
00074 #include <stk_util/util/type_traits_eastl.h>
00075 #include <stk_util/util/algorithm_eastl.h>
00076 #include <stk_util/util/allocator_eastl.h>
00077 
00078 #ifdef _MSC_VER
00079     #pragma warning(push, 0)
00080 #endif
00081 #include <stdlib.h>
00082 #ifdef _MSC_VER
00083     #pragma warning(pop)
00084 #endif
00085 
00086 #ifdef _MSC_VER
00087     #pragma warning(push)
00088     #pragma warning(disable: 4530)  // C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
00089 #endif
00090 
00091 
00092 namespace eastl
00093 {
00094 
00099     #ifndef EASTL_TEMP_DEFAULT_NAME
00100         #define EASTL_TEMP_DEFAULT_NAME EASTL_DEFAULT_NAME_PREFIX " temp" // Unless the user overrides something, this is "EASTL temp".
00101     #endif
00102 
00103 
00121     template <typename T>
00122     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)
00123     {
00124         EASTLAllocatorType allocator(*EASTLAllocatorDefault(), pName);
00125         return eastl::pair<T*, ptrdiff_t>(static_cast<T*>(EASTLAllocAligned(allocator, n * sizeof(T), alignment, alignmentOffset)), n);
00126     }
00127 
00128 
00142     template <typename T>
00143     void return_temporary_buffer(T* p, ptrdiff_t n = 0)
00144     {
00145         EASTLAllocatorType& allocator(*EASTLAllocatorDefault());
00146         EASTLFree(allocator, p, n * sizeof(T));
00147     }
00148 
00149 
00150 
00168 
00169     template <bool hasTrivialMove, typename iteratorTag>
00170     struct uninitialized_move_impl
00171     {
00172         template <typename ForwardIterator, typename ForwardIteratorDest>
00173         static ForwardIteratorDest do_move_start(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
00174         {
00175             typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
00176 
00177             #if EASTL_EXCEPTIONS_ENABLED
00178                 ForwardIteratorDest origDest(dest);
00179                 try
00180                 {
00181                     for(; first != last; ++first, ++dest)
00182                         ::new(&*dest) value_type(*first);
00183                 }
00184                 catch(...)
00185                 {
00186                     for(; origDest < dest; ++origDest)
00187                         origDest->~value_type();
00188                     throw;
00189                 }
00190             #else
00191                 for(; first != last; ++first, ++dest)
00192                     ::new(&*dest) value_type(*first);
00193             #endif
00194 
00195             return dest;
00196         }
00197 
00198         template <typename ForwardIterator, typename ForwardIteratorDest>
00199         static ForwardIteratorDest do_move_commit(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest) //throw()
00200         {
00201             typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
00202             for(; first != last; ++first, ++dest)
00203                 first->~value_type();
00204 
00205             return dest;
00206         }
00207 
00208         template <typename ForwardIterator, typename ForwardIteratorDest>
00209         static ForwardIteratorDest do_move_abort(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest) //throw()
00210         {
00211             typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
00212             for(; first != last; ++first, ++dest)
00213                 dest->~value_type();
00214             return dest;
00215         }
00216     };
00217 
00218     template <>
00219     struct uninitialized_move_impl<true, EASTL_ITC_NS::random_access_iterator_tag>
00220     {
00221         template <typename T>
00222         static T* do_move_start(T* first, T* last, T* dest)
00223         {
00224             return (T*)memcpy(dest, first, (size_t)((uintptr_t)last - (uintptr_t)first)) + (last - first);
00225         }
00226 
00227         template <typename T>
00228         static T* do_move_commit(T* first, T* last, T* dest)
00229         {
00230             return dest + (last - first);
00231         }
00232 
00233         template <typename T>
00234         static T* do_move_abort(T* first, T* last, T* dest)
00235         {
00236             return dest + (last - first);
00237         }
00238     };
00239 
00240 
00265     template <typename ForwardIterator, typename ForwardIteratorDest>
00266     inline ForwardIteratorDest uninitialized_move_start(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
00267     {
00268         typedef typename eastl::iterator_traits<ForwardIterator>::iterator_category IC;
00269         typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type_input;
00270         typedef typename eastl::iterator_traits<ForwardIteratorDest>::value_type value_type_output;
00271 
00272         const bool bHasTrivialMove = type_and<has_trivial_relocate<value_type_input>::value,
00273                                               is_pointer<ForwardIterator>::value,
00274                                               is_pointer<ForwardIteratorDest>::value,
00275                                               is_same<value_type_input, value_type_output>::value>::value;
00276 
00277         return eastl::uninitialized_move_impl<bHasTrivialMove, IC>::do_move_start(first, last, dest);
00278     }
00279 
00280     template <typename ForwardIterator, typename ForwardIteratorDest>
00281     inline ForwardIteratorDest uninitialized_move_commit(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
00282     {
00283         typedef typename eastl::iterator_traits<ForwardIterator>::iterator_category IC;
00284         typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type_input;
00285         typedef typename eastl::iterator_traits<ForwardIteratorDest>::value_type value_type_output;
00286 
00287         const bool bHasTrivialMove = type_and<has_trivial_relocate<value_type_input>::value,
00288                                               is_pointer<ForwardIterator>::value,
00289                                               is_pointer<ForwardIteratorDest>::value,
00290                                               is_same<value_type_input, value_type_output>::value>::value;
00291 
00292         return eastl::uninitialized_move_impl<bHasTrivialMove, IC>::do_move_commit(first, last, dest);
00293     }
00294 
00295     template <typename ForwardIterator, typename ForwardIteratorDest>
00296     inline ForwardIteratorDest uninitialized_move_abort(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
00297     {
00298         typedef typename eastl::iterator_traits<ForwardIterator>::iterator_category IC;
00299         typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type_input;
00300         typedef typename eastl::iterator_traits<ForwardIteratorDest>::value_type value_type_output;
00301 
00302         const bool bHasTrivialMove = type_and<has_trivial_relocate<value_type_input>::value,
00303                                               is_pointer<ForwardIterator>::value,
00304                                               is_pointer<ForwardIteratorDest>::value,
00305                                               is_same<value_type_input, value_type_output>::value>::value;
00306 
00307         return eastl::uninitialized_move_impl<bHasTrivialMove, IC>::do_move_abort(first, last, dest);
00308     }
00309 
00317     template <typename ForwardIterator, typename ForwardIteratorDest>
00318     inline ForwardIteratorDest uninitialized_move(ForwardIterator first, ForwardIterator last, ForwardIteratorDest dest)
00319     {
00320         ForwardIteratorDest result = uninitialized_move_start(first, last, dest);
00321         uninitialized_move_commit(first, last, dest);
00322 
00323         return result;
00324     }
00325 
00326 
00327 
00328 
00329 
00330     // uninitialized_copy
00331     //
00332     template <typename InputIterator, typename ForwardIterator>
00333     inline ForwardIterator uninitialized_copy_impl(InputIterator first, InputIterator last, ForwardIterator dest, true_type)
00334     {
00335         return eastl::copy(first, last, dest); // The copy() in turn will use memcpy for POD types.
00336     }
00337 
00338     template <typename InputIterator, typename ForwardIterator>
00339     inline ForwardIterator uninitialized_copy_impl(InputIterator first, InputIterator last, ForwardIterator dest, false_type)
00340     {
00341         typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
00342         ForwardIterator currentDest(dest);
00343 
00344         #if EASTL_EXCEPTIONS_ENABLED
00345             try
00346             {
00347                 for(; first != last; ++first, ++currentDest)
00348                     ::new(&*currentDest) value_type(*first);
00349             }
00350             catch(...)
00351             {
00352                 for(; dest < currentDest; ++dest)
00353                     dest->~value_type();
00354                 throw;
00355             }
00356         #else
00357             for(; first != last; ++first, ++currentDest)
00358                 ::new(&*currentDest) value_type(*first);
00359         #endif
00360 
00361         return currentDest;
00362     }
00363 
00378     template <typename InputIterator, typename ForwardIterator>
00379     inline ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result)
00380     {
00381         typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
00382 
00383         // Note: has_trivial_assign isn't actually the right thing to use here, as it
00384         // refers to assignment as opposed to construction. Bug Paul Pedriana if this
00385         // is becoming a problem. In the meantime, this code assumes that if has_trivial_assign
00386         // is present for a type, then has_trivial_copy is as well.
00387         return uninitialized_copy_impl(first, last, result, has_trivial_assign<value_type>());
00388     }
00389 
00396     template <typename First, typename Last, typename Result>
00397     inline Result uninitialized_copy_ptr(First first, Last last, Result result)
00398     {
00399         typedef typename eastl::iterator_traits<generic_iterator<Result, void> >::value_type value_type;
00400         const generic_iterator<Result, void> i(uninitialized_copy_impl(generic_iterator<First, void>(first),
00401                                                                        generic_iterator<Last, void>(last),
00402                                                                        generic_iterator<Result, void>(result),
00403                                                                        has_trivial_assign<value_type>()));
00404         return i.base();
00405     }
00406 
00407 
00408 
00409 
00410     // uninitialized_fill
00411     //
00412     template <typename ForwardIterator, typename T>
00413     inline void uninitialized_fill_impl(ForwardIterator first, ForwardIterator last, const T& value, true_type)
00414     {
00415         eastl::fill(first, last, value);
00416     }
00417 
00418     template <typename ForwardIterator, typename T>
00419     void uninitialized_fill_impl(ForwardIterator first, ForwardIterator last, const T& value, false_type)
00420     {
00421         typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
00422         ForwardIterator currentDest(first);
00423 
00424         #if EASTL_EXCEPTIONS_ENABLED
00425             try
00426             {
00427                 for(; currentDest != last; ++currentDest)
00428                     ::new(&*currentDest) value_type(value);
00429             }
00430             catch(...)
00431             {
00432                 for(; first < currentDest; ++first)
00433                     first->~value_type();
00434                 throw;
00435             }
00436         #else
00437             for(; currentDest != last; ++currentDest)
00438                 ::new(&*currentDest) value_type(value);
00439         #endif
00440     }
00441 
00452     template <typename ForwardIterator, typename T>
00453     inline void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& value)
00454     {
00455         typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
00456         uninitialized_fill_impl(first, last, value, has_trivial_assign<value_type>());
00457     }
00458 
00465     template <typename T>
00466     inline void uninitialized_fill_ptr(T* first, T* last, const T& value)
00467     {
00468         typedef typename eastl::iterator_traits<generic_iterator<T*, void> >::value_type value_type;
00469         uninitialized_fill_impl(generic_iterator<T*, void>(first), generic_iterator<T*, void>(last), value, has_trivial_assign<value_type>());
00470     }
00471 
00472 
00473 
00474 
00475     // uninitialized_fill_n
00476     //
00477     template <typename ForwardIterator, typename Count, typename T>
00478     inline void uninitialized_fill_n_impl(ForwardIterator first, Count n, const T& value, true_type)
00479     {
00480         eastl::fill_n(first, n, value);
00481     }
00482 
00483     template <typename ForwardIterator, typename Count, typename T>
00484     void uninitialized_fill_n_impl(ForwardIterator first, Count n, const T& value, false_type)
00485     {
00486         typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
00487         ForwardIterator currentDest(first);
00488 
00489         #if EASTL_EXCEPTIONS_ENABLED
00490             try
00491             {
00492                 for(; n > 0; --n, ++currentDest)
00493                     ::new(&*currentDest) value_type(value);
00494             }
00495             catch(...)
00496             {
00497                 for(; first < currentDest; ++first)
00498                     first->~value_type();
00499                 throw;
00500             }
00501         #else
00502             for(; n > 0; --n, ++currentDest)
00503                 ::new(&*currentDest) value_type(value);
00504         #endif
00505     }
00506 
00517     template <typename ForwardIterator, typename Count, typename T>
00518     inline void uninitialized_fill_n(ForwardIterator first, Count n, const T& value)
00519     {
00520         typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
00521         uninitialized_fill_n_impl(first, n, value, has_trivial_assign<value_type>());
00522     }
00523 
00530     template <typename T, typename Count>
00531     inline void uninitialized_fill_n_ptr(T* first, Count n, const T& value)
00532     {
00533         typedef typename eastl::iterator_traits<generic_iterator<T*, void> >::value_type value_type;
00534         uninitialized_fill_n_impl(generic_iterator<T*, void>(first), n, value, has_trivial_assign<value_type>());
00535     }
00536 
00537 
00538 
00539 
00545     template <typename InputIterator, typename ForwardIterator, typename T>
00546     inline void uninitialized_copy_fill(InputIterator first1, InputIterator last1,
00547                                         ForwardIterator first2, ForwardIterator last2, const T& value)
00548     {
00549         const ForwardIterator mid(eastl::uninitialized_copy(first1, last1, first2));
00550 
00551         #if EASTL_EXCEPTIONS_ENABLED
00552             try
00553             {
00554         #endif
00555                 eastl::uninitialized_fill(mid, last2, value);
00556         #if EASTL_EXCEPTIONS_ENABLED
00557             }
00558             catch(...)
00559             {
00560                 for(; first2 < mid; ++first2)
00561                     first2->~value_type();
00562                 throw;
00563             }
00564         #endif
00565     }
00566 
00567 
00568 
00569 
00570 
00575     template <typename ForwardIterator, typename T, typename InputIterator>
00576     inline ForwardIterator
00577     uninitialized_fill_copy(ForwardIterator result, ForwardIterator mid, const T& value, InputIterator first, InputIterator last)
00578     {
00579         eastl::uninitialized_fill(result, mid, value);
00580 
00581         #if EASTL_EXCEPTIONS_ENABLED
00582             try
00583             {
00584         #endif
00585                 return eastl::uninitialized_copy(first, last, mid);
00586         #if EASTL_EXCEPTIONS_ENABLED
00587             }
00588             catch(...)
00589             {
00590                 for(; result < mid; ++result)
00591                     result->~value_type();
00592                 throw;
00593             }
00594         #endif
00595     }
00596 
00597 
00598 
00604     template <typename InputIterator1, typename InputIterator2, typename ForwardIterator>
00605     inline ForwardIterator
00606     uninitialized_copy_copy(InputIterator1 first1, InputIterator1 last1,
00607                             InputIterator2 first2, InputIterator2 last2,
00608                             ForwardIterator result)
00609     {
00610         const ForwardIterator mid(eastl::uninitialized_copy(first1, last1, result));
00611 
00612         #if EASTL_EXCEPTIONS_ENABLED
00613             try
00614             {
00615         #endif
00616                 return eastl::uninitialized_copy(first2, last2, mid);
00617         #if EASTL_EXCEPTIONS_ENABLED
00618             }
00619             catch(...)
00620             {
00621                 for(; result < mid; ++result)
00622                     result->~value_type();
00623                 throw;
00624             }
00625         #endif
00626     }
00627 
00628 
00629 
00639     template <typename T>
00640     inline void destruct(T* p)
00641     {
00642         p->~T();
00643     }
00644 
00645 
00646 
00647     // destruct(first, last)
00648     //
00649     template <typename ForwardIterator>
00650     inline void destruct_impl(ForwardIterator /*first*/, ForwardIterator /*last*/, true_type) // true means the type has a trivial destructor.
00651     {
00652         // Empty. The type has a trivial destructor.
00653     }
00654 
00655     template <typename ForwardIterator>
00656     inline void destruct_impl(ForwardIterator first, ForwardIterator last, false_type) // false means the type has a significant destructor.
00657     {
00658         typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
00659 
00660         for(; first != last; ++first)
00661             (*first).~value_type();
00662     }
00663 
00671     template <typename ForwardIterator>
00672     inline void destruct(ForwardIterator first, ForwardIterator last)
00673     {
00674         typedef typename eastl::iterator_traits<ForwardIterator>::value_type value_type;
00675         destruct_impl(first, last, eastl::has_trivial_destructor<value_type>());
00676     }
00677 
00678 
00679 } // namespace eastl
00680 
00681 
00682 #ifdef _MSC_VER
00683     #pragma warning(pop)
00684 #endif
00685 
00686 
00687 #endif // Header include guard
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends