1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef CHRE_UTIL_MEMORY_IMPL_H_ 18 #define CHRE_UTIL_MEMORY_IMPL_H_ 19 20 #include <cstring> 21 #include <new> 22 #include <type_traits> 23 #include <utility> 24 25 #include "chre/util/container_support.h" 26 27 namespace chre { 28 29 template<typename ElementType> 30 inline void destroy(ElementType *first, size_t count) { 31 for (size_t i = 0; i < count; i++) { 32 first[i].~ElementType(); 33 } 34 } 35 36 //! Overload used when the type is move assignable 37 template<typename ElementType> 38 inline void moveOrCopyAssign(ElementType& dest, ElementType& source, 39 std::true_type) { 40 dest = std::move(source); 41 } 42 43 //! Overload used when the type is not move assignable 44 template<typename ElementType> 45 inline void moveOrCopyAssign(ElementType& dest, ElementType& source, 46 std::false_type) { 47 dest = source; 48 } 49 50 template<typename ElementType> 51 inline void moveOrCopyAssign(ElementType& dest, ElementType& source) { 52 moveOrCopyAssign(dest, source, 53 typename std::is_move_assignable<ElementType>::type()); 54 } 55 56 //! Overload used when type is trivially copy constructible 57 template<typename ElementType> 58 inline void uninitializedMoveOrCopy(ElementType *source, size_t count, 59 ElementType *dest, std::true_type) { 60 std::memcpy(dest, source, count * sizeof(ElementType)); 61 } 62 63 //! Overload used when type is not trivially copy constructible, but is move 64 //! constructible 65 template<typename ElementType> 66 inline void uninitializedMoveOrCopy(ElementType *source, size_t count, 67 ElementType *dest, std::false_type, 68 std::true_type) { 69 for (size_t i = 0; i < count; i++) { 70 new (&dest[i]) ElementType(std::move(source[i])); 71 } 72 } 73 74 //! Overload used when type is not trivially copy constructible or move 75 //! constructible 76 template<typename ElementType> 77 inline void uninitializedMoveOrCopy(ElementType *source, size_t count, 78 ElementType *dest, std::false_type, 79 std::false_type) { 80 for (size_t i = 0; i < count; i++) { 81 new (&dest[i]) ElementType(source[i]); 82 } 83 } 84 85 //! Overload used when type is not trivially copy constructible 86 template<typename ElementType> 87 inline void uninitializedMoveOrCopy( 88 ElementType *source, size_t count, ElementType *dest, std::false_type) { 89 // Check the assumption that if is_move_constructible is false, then 90 // is_copy_constructible is true 91 static_assert(std::is_move_constructible<ElementType>() 92 || std::is_copy_constructible<ElementType>(), 93 "Object must be copy- or move- constructible to use " 94 "unintializedMoveOrCopy"); 95 uninitializedMoveOrCopy( 96 source, count, dest, std::false_type(), 97 typename std::is_move_constructible<ElementType>::type()); 98 } 99 100 template<typename ElementType> 101 inline void uninitializedMoveOrCopy(ElementType *source, size_t count, 102 ElementType *dest) { 103 // TODO: we should be able to use std::is_trivially_copy_constructible here, 104 // but it's not found in the linux x86 build, because our build uses GCC 4.8's 105 // C++ standard library, which doesn't support it. Works in the SLPI build, 106 // though... 107 uninitializedMoveOrCopy( 108 source, count, dest, typename std::is_trivial<ElementType>::type()); 109 //typename std::is_trivially_copy_constructible<ElementType>::type()); 110 } 111 112 template<typename T, typename... Args> 113 inline T *memoryAlloc(Args&&... args) { 114 auto *storage = static_cast<T *>(memoryAlloc(sizeof(T))); 115 if (storage != nullptr) { 116 new(storage) T(std::forward<Args>(args)...); 117 } 118 119 return storage; 120 } 121 122 } // namespace chre 123 124 #endif // CHRE_UTIL_MEMORY_IMPL_H_ 125