1 /*
2  * Copyright (C) 2015 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 #ifndef ART_RUNTIME_LAMBDA_LEAKING_ALLOCATOR_H_
17 #define ART_RUNTIME_LAMBDA_LEAKING_ALLOCATOR_H_
18 
19 #include <utility>  // std::forward
20 #include <type_traits>  // std::aligned_storage
21 
22 namespace art {
23 class Thread;  // forward declaration
24 
25 namespace lambda {
26 
27 // Temporary class to centralize all the leaking allocations.
28 // Allocations made through this class are never freed, but it is a placeholder
29 // that means that the calling code needs to be rewritten to properly:
30 //
31 // (a) Have a lifetime scoped to some other entity.
32 // (b) Not be allocated over and over again if it was already allocated once (immutable data).
33 //
34 // TODO: do all of the above a/b for each callsite, and delete this class.
35 class LeakingAllocator {
36  public:
37   // An opaque type which is guaranteed for:
38   // * a) be large enough to hold T (e.g. for in-place new)
39   // * b) be well-aligned (so that reads/writes are well-defined) to T
40   // * c) strict-aliasing compatible with T*
41   //
42   // Nominally used to allocate memory for yet unconstructed instances of T.
43   template <typename T>
44   using AlignedMemoryStorage = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
45 
46   // Allocate byte_size bytes worth of memory. Never freed.
47   template <typename T>
48   static AlignedMemoryStorage<T>* AllocateMemory(Thread* self, size_t byte_size = sizeof(T)) {
49     return reinterpret_cast<AlignedMemoryStorage<T>*>(
50         AllocateMemoryImpl(self, byte_size, alignof(T)));
51   }
52 
53   // Make a new instance of T, flexibly sized, in-place at newly allocated memory. Never freed.
54   template <typename T, typename... Args>
MakeFlexibleInstance(Thread * self,size_t byte_size,Args &&...args)55   static T* MakeFlexibleInstance(Thread* self, size_t byte_size, Args&&... args) {
56     return new (AllocateMemory<T>(self, byte_size)) T(std::forward<Args>(args)...);
57   }
58 
59   // Make a new instance of T in-place at newly allocated memory. Never freed.
60   template <typename T, typename... Args>
MakeInstance(Thread * self,Args &&...args)61   static T* MakeInstance(Thread* self, Args&&... args) {
62     return new (AllocateMemory<T>(self, sizeof(T))) T(std::forward<Args>(args)...);
63   }
64 
65  private:
66   static void* AllocateMemoryImpl(Thread* self, size_t byte_size, size_t align_size);
67 };
68 
69 }  // namespace lambda
70 }  // namespace art
71 
72 #endif  // ART_RUNTIME_LAMBDA_LEAKING_ALLOCATOR_H_
73