1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be 3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file. 4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// ManualConstructor statically-allocates space in which to store some 6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// object, but does not initialize it. You can then call the constructor 7b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// and destructor for the object yourself as you see fit. This is useful 8b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// for memory management optimizations, where you want to initialize and 9b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// destroy an object multiple times but only allocate it once. 10b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// 11b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// (When I say ManualConstructor statically allocates space, I mean that 12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// the ManualConstructor object itself is forced to be the right size.) 13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// 14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// For example usage, check out base/containers/small_map.h. 15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#ifndef BASE_MEMORY_MANUAL_CONSTRUCTOR_H_ 17b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#define BASE_MEMORY_MANUAL_CONSTRUCTOR_H_ 18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <stddef.h> 20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/compiler_specific.h" 22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/memory/aligned_memory.h" 23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base { 25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erattemplate <typename Type> 27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass ManualConstructor { 28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public: 29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // No constructor or destructor because one of the most useful uses of 30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // this class is as part of a union, and members of a union cannot have 31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // constructors or destructors. And, anyway, the whole point of this 32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // class is to bypass these. 33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Support users creating arrays of ManualConstructor<>s. This ensures that 35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // the array itself has the correct alignment. 36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat static void* operator new[](size_t size) { 37b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return AlignedAlloc(size, ALIGNOF(Type)); 38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat static void operator delete[](void* mem) { 40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat AlignedFree(mem); 41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat inline Type* get() { 44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return space_.template data_as<Type>(); 45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat inline const Type* get() const { 47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return space_.template data_as<Type>(); 48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat inline Type* operator->() { return get(); } 51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat inline const Type* operator->() const { return get(); } 52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat inline Type& operator*() { return *get(); } 54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat inline const Type& operator*() const { return *get(); } 55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat template <typename... Ts> 5745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko inline void Init(Ts&&... params) { 5845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko new(space_.void_data()) Type(std::forward<Ts>(params)...); 5945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 6045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 6145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko inline void InitFromMove(ManualConstructor<Type>&& o) { 6245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko Init(std::move(*o)); 63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat inline void Destroy() { 66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat get()->~Type(); 67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private: 70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat AlignedMemory<sizeof(Type), ALIGNOF(Type)> space_; 71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace base 74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif // BASE_MEMORY_MANUAL_CONSTRUCTOR_H_ 76