Home | History | Annotate | Download | only in util
      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