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>
destroy(ElementType * first,size_t count)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>
moveOrCopyAssign(ElementType & dest,ElementType & source,std::true_type)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>
moveOrCopyAssign(ElementType & dest,ElementType & source,std::false_type)45 inline void moveOrCopyAssign(ElementType &dest, ElementType &source,
46 std::false_type) {
47 dest = source;
48 }
49
50 template <typename ElementType>
moveOrCopyAssign(ElementType & dest,ElementType & source)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>
uninitializedMoveOrCopy(ElementType * source,size_t count,ElementType * dest,std::true_type)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>
uninitializedMoveOrCopy(ElementType * source,size_t count,ElementType * dest,std::false_type,std::true_type)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>
uninitializedMoveOrCopy(ElementType * source,size_t count,ElementType * dest,std::false_type,std::false_type)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>
uninitializedMoveOrCopy(ElementType * source,size_t count,ElementType * dest,std::false_type)87 inline void uninitializedMoveOrCopy(ElementType *source, size_t count,
88 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>
uninitializedMoveOrCopy(ElementType * source,size_t count,ElementType * dest)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(source, count, dest,
108 typename std::is_trivial<ElementType>::type());
109 // typename std::is_trivially_copy_constructible<ElementType>::type());
110 }
111
112 template <typename T, typename... Args>
memoryAlloc(Args &&...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