michael@0: // Copyright (c) 2012 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: // AlignedMemory is a POD type that gives you a portable way to specify static michael@0: // or local stack data of a given alignment and size. For example, if you need michael@0: // static storage for a class, but you want manual control over when the object michael@0: // is constructed and destructed (you don't want static initialization and michael@0: // destruction), use AlignedMemory: michael@0: // michael@0: // static AlignedMemory my_class; michael@0: // michael@0: // // ... at runtime: michael@0: // new(my_class.void_data()) MyClass(); michael@0: // michael@0: // // ... use it: michael@0: // MyClass* mc = my_class.data_as(); michael@0: // michael@0: // // ... later, to destruct my_class: michael@0: // my_class.data_as()->MyClass::~MyClass(); michael@0: // michael@0: // Alternatively, a runtime sized aligned allocation can be created: michael@0: // michael@0: // float* my_array = static_cast(AlignedAlloc(size, alignment)); michael@0: // michael@0: // // ... later, to release the memory: michael@0: // AlignedFree(my_array); michael@0: // michael@0: // Or using scoped_ptr_malloc: michael@0: // michael@0: // scoped_ptr_malloc my_array( michael@0: // static_cast(AlignedAlloc(size, alignment))); michael@0: michael@0: #ifndef BASE_MEMORY_ALIGNED_MEMORY_H_ michael@0: #define BASE_MEMORY_ALIGNED_MEMORY_H_ michael@0: michael@0: #include "base/base_export.h" michael@0: #include "base/basictypes.h" michael@0: #include "base/compiler_specific.h" michael@0: michael@0: #if defined(COMPILER_MSVC) michael@0: #include michael@0: #else michael@0: #include michael@0: #endif michael@0: michael@0: namespace base { michael@0: michael@0: // AlignedMemory is specialized for all supported alignments. michael@0: // Make sure we get a compiler error if someone uses an unsupported alignment. michael@0: template michael@0: struct AlignedMemory {}; michael@0: michael@0: #define BASE_DECL_ALIGNED_MEMORY(byte_alignment) \ michael@0: template \ michael@0: class AlignedMemory { \ michael@0: public: \ michael@0: ALIGNAS(byte_alignment) uint8 data_[Size]; \ michael@0: void* void_data() { return static_cast(data_); } \ michael@0: const void* void_data() const { \ michael@0: return static_cast(data_); \ michael@0: } \ michael@0: template \ michael@0: Type* data_as() { return static_cast(void_data()); } \ michael@0: template \ michael@0: const Type* data_as() const { \ michael@0: return static_cast(void_data()); \ michael@0: } \ michael@0: private: \ michael@0: void* operator new(size_t); \ michael@0: void operator delete(void*); \ michael@0: } michael@0: michael@0: // Specialization for all alignments is required because MSVC (as of VS 2008) michael@0: // does not understand ALIGNAS(ALIGNOF(Type)) or ALIGNAS(template_param). michael@0: // Greater than 4096 alignment is not supported by some compilers, so 4096 is michael@0: // the maximum specified here. michael@0: BASE_DECL_ALIGNED_MEMORY(1); michael@0: BASE_DECL_ALIGNED_MEMORY(2); michael@0: BASE_DECL_ALIGNED_MEMORY(4); michael@0: BASE_DECL_ALIGNED_MEMORY(8); michael@0: BASE_DECL_ALIGNED_MEMORY(16); michael@0: BASE_DECL_ALIGNED_MEMORY(32); michael@0: BASE_DECL_ALIGNED_MEMORY(64); michael@0: BASE_DECL_ALIGNED_MEMORY(128); michael@0: BASE_DECL_ALIGNED_MEMORY(256); michael@0: BASE_DECL_ALIGNED_MEMORY(512); michael@0: BASE_DECL_ALIGNED_MEMORY(1024); michael@0: BASE_DECL_ALIGNED_MEMORY(2048); michael@0: BASE_DECL_ALIGNED_MEMORY(4096); michael@0: michael@0: #undef BASE_DECL_ALIGNED_MEMORY michael@0: michael@0: BASE_EXPORT void* AlignedAlloc(size_t size, size_t alignment); michael@0: michael@0: inline void AlignedFree(void* ptr) { michael@0: #if defined(COMPILER_MSVC) michael@0: _aligned_free(ptr); michael@0: #else michael@0: free(ptr); michael@0: #endif michael@0: } michael@0: michael@0: // Helper class for use with scoped_ptr_malloc. michael@0: class BASE_EXPORT ScopedPtrAlignedFree { michael@0: public: michael@0: inline void operator()(void* ptr) const { michael@0: AlignedFree(ptr); michael@0: } michael@0: }; michael@0: michael@0: } // namespace base michael@0: michael@0: #endif // BASE_MEMORY_ALIGNED_MEMORY_H_