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 namespace chre {
26
27 template<typename ElementType>
destroy(ElementType * first,size_t count)28 inline void destroy(ElementType *first, size_t count) {
29 for (size_t i = 0; i < count; i++) {
30 first[i].~ElementType();
31 }
32 }
33
34 //! Overload used when the type is move assignable
35 template<typename ElementType>
moveOrCopyAssign(ElementType & dest,ElementType & source,std::true_type)36 inline void moveOrCopyAssign(ElementType& dest, ElementType& source,
37 std::true_type) {
38 dest = std::move(source);
39 }
40
41 //! Overload used when the type is not move assignable
42 template<typename ElementType>
moveOrCopyAssign(ElementType & dest,ElementType & source,std::false_type)43 inline void moveOrCopyAssign(ElementType& dest, ElementType& source,
44 std::false_type) {
45 dest = source;
46 }
47
48 template<typename ElementType>
moveOrCopyAssign(ElementType & dest,ElementType & source)49 inline void moveOrCopyAssign(ElementType& dest, ElementType& source) {
50 moveOrCopyAssign(dest, source,
51 typename std::is_move_assignable<ElementType>::type());
52 }
53
54 //! Overload used when type is trivially copy constructible
55 template<typename ElementType>
uninitializedMoveOrCopy(ElementType * source,size_t count,ElementType * dest,std::true_type)56 inline void uninitializedMoveOrCopy(ElementType *source, size_t count,
57 ElementType *dest, std::true_type) {
58 std::memcpy(dest, source, count * sizeof(ElementType));
59 }
60
61 //! Overload used when type is not trivially copy constructible, but is move
62 //! constructible
63 template<typename ElementType>
uninitializedMoveOrCopy(ElementType * source,size_t count,ElementType * dest,std::false_type,std::true_type)64 inline void uninitializedMoveOrCopy(ElementType *source, size_t count,
65 ElementType *dest, std::false_type,
66 std::true_type) {
67 for (size_t i = 0; i < count; i++) {
68 new (&dest[i]) ElementType(std::move(source[i]));
69 }
70 }
71
72 //! Overload used when type is not trivially copy constructible or move
73 //! constructible
74 template<typename ElementType>
uninitializedMoveOrCopy(ElementType * source,size_t count,ElementType * dest,std::false_type,std::false_type)75 inline void uninitializedMoveOrCopy(ElementType *source, size_t count,
76 ElementType *dest, std::false_type,
77 std::false_type) {
78 for (size_t i = 0; i < count; i++) {
79 new (&dest[i]) ElementType(source[i]);
80 }
81 }
82
83 //! Overload used when type is not trivially copy constructible
84 template<typename ElementType>
uninitializedMoveOrCopy(ElementType * source,size_t count,ElementType * dest,std::false_type)85 inline void uninitializedMoveOrCopy(
86 ElementType *source, size_t count, ElementType *dest, std::false_type) {
87 // Check the assumption that if is_move_constructible is false, then
88 // is_copy_constructible is true
89 static_assert(std::is_move_constructible<ElementType>()
90 || std::is_copy_constructible<ElementType>(),
91 "Object must be copy- or move- constructible to use "
92 "unintializedMoveOrCopy");
93 uninitializedMoveOrCopy(
94 source, count, dest, std::false_type(),
95 typename std::is_move_constructible<ElementType>::type());
96 }
97
98 template<typename ElementType>
uninitializedMoveOrCopy(ElementType * source,size_t count,ElementType * dest)99 inline void uninitializedMoveOrCopy(ElementType *source, size_t count,
100 ElementType *dest) {
101 // TODO: we should be able to use std::is_trivially_copy_constructible here,
102 // but it's not found in the linux x86 build, because our build uses GCC 4.8's
103 // C++ standard library, which doesn't support it. Works in the SLPI build,
104 // though...
105 uninitializedMoveOrCopy(
106 source, count, dest, typename std::is_trivial<ElementType>::type());
107 //typename std::is_trivially_copy_constructible<ElementType>::type());
108 }
109
110 } // namespace chre
111
112 #endif // CHRE_UTIL_MEMORY_IMPL_H_
113