|
Sierra Toolkit
Version of the Day
|
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