memory_impl.h revision 97156830527953070044eed8b0eb42ba689c53c4
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 27namespace chre { 28 29template<typename ElementType> 30inline 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 37template<typename ElementType> 38inline 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 44template<typename ElementType> 45inline void moveOrCopyAssign(ElementType& dest, ElementType& source, 46 std::false_type) { 47 dest = source; 48} 49 50template<typename ElementType> 51inline 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 57template<typename ElementType> 58inline 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 65template<typename ElementType> 66inline 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 76template<typename ElementType> 77inline 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 86template<typename ElementType> 87inline 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 100template<typename ElementType> 101inline 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 112template<typename T, typename... Args> 113inline 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