// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// AlignedMemory is a POD type that gives you a portable way to specify static
// or local stack data of a given alignment and size. For example, if you need
// static storage for a class, but you want manual control over when the object
// is constructed and destructed (you don't want static initialization and
// destruction), use AlignedMemory:
//
// static AlignedMemory<sizeof(MyClass), ALIGNOF(MyClass)> my_class;
//
// // ... at runtime:
// new(my_class.void_data()) MyClass();
//
// // ... use it:
// MyClass* mc = my_class.data_as<MyClass>();
//
// // ... later, to destruct my_class:
// my_class.data_as<MyClass>()->MyClass::~MyClass();
//
// Alternatively, a runtime sized aligned allocation can be created:
//
// float* my_array = static_cast<float*>(AlignedAlloc(size, alignment));
//
// // ... later, to release the memory:
// AlignedFree(my_array);
//
// Or using scoped_ptr_malloc:
//
// scoped_ptr_malloc<float, ScopedPtrAlignedFree> my_array(
// static_cast<float*>(AlignedAlloc(size, alignment)));
#ifndef BASE_MEMORY_ALIGNED_MEMORY_H_
#define BASE_MEMORY_ALIGNED_MEMORY_H_
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#if defined(COMPILER_MSVC)
#include <malloc.h>
#else
#include <stdlib.h>
#endif
namespace base
{
// AlignedMemory is specialized for all supported alignments.
// Make sure we get a compiler error if someone uses an unsupported alignment.
template <size_t Size, size_t ByteAlignment>
struct AlignedMemory {};
// 大小为
#define BASE_DECL_ALIGNED_MEMORY(byte_alignment) \
template <size_t Size> \
class AlignedMemory<Size, byte_alignment> { \
public: \
ALIGNAS(byte_alignment) uint8 data_[Size]; \
void* void_data() { return static_cast<void*>(data_); } \
const void* void_data() const { \
return static_cast<const void*>(data_); \
} \
template<typename Type> \
Type* data_as() { return static_cast<Type*>(void_data()); } \
template<typename Type> \
const Type* data_as() const { \
return static_cast<const Type*>(void_data()); \
} \
private: \
void* operator new(size_t); \
void operator delete(void*); \
}
// Specialization for all alignments is required because MSVC (as of VS 2008)
// does not understand ALIGNAS(ALIGNOF(Type)) or ALIGNAS(template_param).
// Greater than 4096 alignment is not supported by some compilers, so 4096 is
// the maximum specified here.
BASE_DECL_ALIGNED_MEMORY(1);
BASE_DECL_ALIGNED_MEMORY(2);
BASE_DECL_ALIGNED_MEMORY(4);
BASE_DECL_ALIGNED_MEMORY(8);
BASE_DECL_ALIGNED_MEMORY(16);
BASE_DECL_ALIGNED_MEMORY(32);
BASE_DECL_ALIGNED_MEMORY(64);
BASE_DECL_ALIGNED_MEMORY(128);
BASE_DECL_ALIGNED_MEMORY(256);
BASE_DECL_ALIGNED_MEMORY(512);
BASE_DECL_ALIGNED_MEMORY(1024);
BASE_DECL_ALIGNED_MEMORY(2048);
BASE_DECL_ALIGNED_MEMORY(4096);
#undef BASE_DECL_ALIGNED_MEMORY
BASE_EXPORT void* AlignedAlloc(size_t size, size_t alignment);
inline void AlignedFree(void* ptr)
{
#if defined(COMPILER_MSVC)
_aligned_free(ptr);
#else
free(ptr);
#endif
}
// Helper class for use with scoped_ptr_malloc.
class BASE_EXPORT ScopedPtrAlignedFree
{
public:
inline void operator()(void* ptr) const
{
AlignedFree(ptr);
}
};
} // namespace base
#endif // BASE_MEMORY_ALIGNED_MEMORY_H_
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// ManualConstructor statically-allocates space in which to store some
// object, but does not initialize it. You can then call the constructor
// and destructor for the object yourself as you see fit. This is useful
// for memory management optimizations, where you want to initialize and
// destroy an object multiple times but only allocate it once.
//
// (When I say ManualConstructor statically allocates space, I mean that
// the ManualConstructor object itself is forced to be the right size.)
//
// For example usage, check out base/containers/small_map.h.
#ifndef BASE_MEMORY_MANUAL_CONSTRUCTOR_H_
#define BASE_MEMORY_MANUAL_CONSTRUCTOR_H_
#include <stddef.h>
#include "base/memory/aligned_memory.h"
namespace base
{
template <typename Type>
class ManualConstructor
{
public:
// No constructor or destructor because one of the most useful uses of
// this class is as part of a union, and members of a union cannot have
// constructors or destructors. And, anyway, the whole point of this
// class is to bypass these.
// Support users creating arrays of ManualConstructor<>s. This ensures that
// the array itself has the correct alignment.
static void* operator new[](size_t size)
{
#if defined(COMPILER_MSVC)
return AlignedAlloc(size, __alignof(Type));
#else
return AlignedAlloc(size, __alignof__(Type));
#endif
}
static void operator delete[](void* mem)
{
AlignedFree(mem);
}
inline Type* get()
{
return space_.template data_as<Type>();
}
inline const Type* get() const
{
return space_.template data_as<Type>();
}
inline Type* operator->()
{
return get();
}
inline const Type* operator->() const { return get(); }
inline Type& operator*() { return *get(); }
inline const Type& operator*() const { return *get(); }
// You can pass up to eight constructor arguments as arguments of Init().
inline void Init()
{
new(space_.void_data()) Type;
}
template <typename T1>
inline void Init(const T1& p1)
{
new(space_.void_data()) Type(p1);
}
template <typename T1, typename T2>
inline void Init(const T1& p1, const T2& p2)
{
new(space_.void_data()) Type(p1, p2);
}
template <typename T1, typename T2, typename T3>
inline void Init(const T1& p1, const T2& p2, const T3& p3)
{
new(space_.void_data()) Type(p1, p2, p3);
}
template <typename T1, typename T2, typename T3, typename T4>
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4)
{
new(space_.void_data()) Type(p1, p2, p3, p4);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5>
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5) {
new(space_.void_data()) Type(p1, p2, p3, p4, p5);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6>
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6) {
new(space_.void_data()) Type(p1, p2, p3, p4, p5, p6);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7>
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6, const T7& p7) {
new(space_.void_data()) Type(p1, p2, p3, p4, p5, p6, p7);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8>
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6, const T7& p7, const T8& p8) {
new(space_.void_data()) Type(p1, p2, p3, p4, p5, p6, p7, p8);
}
inline void Destroy()
{
get()->~Type();
}
private:
#if defined(COMPILER_MSVC)
AlignedMemory<sizeof(Type), __alignof(Type)> space_;
#else
AlignedMemory<sizeof(Type), __alignof__(Type)> space_;
#endif
};
} // namespace base
#endif // BASE_MEMORY_MANUAL_CONSTRUCTOR_H_