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