diff --git a/build/pomdog.gyp b/build/pomdog.gyp index fc2ea81c7..347b7e052 100644 --- a/build/pomdog.gyp +++ b/build/pomdog.gyp @@ -314,6 +314,7 @@ '../src/Signals/ConnectionList.cpp', '../src/Signals/EventQueue.cpp', '../src/Signals/ScopedConnection.cpp', + '../src/Utility/AlignedNew.hpp', '../src/Utility/CRC32.cpp', '../src/Utility/Noncopyable.hpp', '../src/Utility/PathHelper.cpp', diff --git a/build/pomdog.xcodeproj/project.pbxproj b/build/pomdog.xcodeproj/project.pbxproj index 071dd242f..96068eb9c 100644 --- a/build/pomdog.xcodeproj/project.pbxproj +++ b/build/pomdog.xcodeproj/project.pbxproj @@ -594,6 +594,7 @@ A9AE680DD0E3FCEA11AF8F48 /* FloatingPointVector4.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FloatingPointVector4.cpp; sourceTree = ""; }; A9D18E8B1CA426FA0011A6CE /* MetalCompiler.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MetalCompiler.hpp; sourceTree = ""; }; A9D18E8C1CA427270011A6CE /* MetalCompiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MetalCompiler.cpp; sourceTree = ""; }; + A9FC99071DC3D89300C78D63 /* AlignedNew.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = AlignedNew.hpp; sourceTree = ""; }; AA4220AFBD6F377F07163A1E /* EffectAnnotation.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; path = EffectAnnotation.hpp; sourceTree = ""; }; ABEE70990030BA68A5F9002D /* PipelineStateGL4.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; path = PipelineStateGL4.hpp; sourceTree = ""; }; AC349E78729FC3024C1BC5D9 /* Assert.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; path = Assert.hpp; sourceTree = ""; }; @@ -1011,6 +1012,7 @@ 582932A6CEFF570AC75B5E15 /* Utility */ = { isa = PBXGroup; children = ( + A9FC99071DC3D89300C78D63 /* AlignedNew.hpp */, 874BAF3803BCB9751C9574C4 /* CRC32.cpp */, 2749362BB85096C3C6B6347F /* Noncopyable.hpp */, 5DAB111727E9143A507A0C10 /* PathHelper.cpp */, diff --git a/src/Utility/AlignedNew.hpp b/src/Utility/AlignedNew.hpp new file mode 100644 index 000000000..62ff4f7cb --- /dev/null +++ b/src/Utility/AlignedNew.hpp @@ -0,0 +1,67 @@ +// Copyright (c) 2013-2016 mogemimi. Distributed under the MIT license. + +#pragma once + +#if defined(_MSC_VER) +#include +#else +#include +#endif + +namespace Pomdog { +namespace Detail { + +constexpr bool IsPowerOfTwo(int x) +{ + return (x != 0) && ((x & (x - 1)) == 0); +} + +template +class AlignedNew { +public: + static void* operator new(size_t size) + { + constexpr size_t alignment = __alignof(T); + static_assert(alignment > 8, ""); + static_assert(IsPowerOfTwo(static_cast(alignment)), "Must be integer power of 2."); + + #if defined(_MSC_VER) + auto ptr = ::_aligned_malloc(size, alignment); + #elif (__STDC_VERSION__ > 201112L) + auto ptr = std::aligned_alloc(alignment, size); + #else + void* ptr = nullptr; + if (posix_memalign(&ptr, alignment, size) != 0) { + ptr = nullptr; + } + #endif + + if (nullptr == ptr) { + throw std::bad_alloc(); + } + return ptr; + } + + static void operator delete(void * ptr) + { + #if defined(_MSC_VER) + ::_aligned_free(ptr); + #else + // NOTE: When using `std::aligned_alloc` or `posix_memalign`, you can call `free(3)`. + free(ptr); + #endif + } + + static void* operator new[](size_t size) + { + return operator new(size); + } + + static void operator delete[](void * ptr) + { + operator delete(ptr); + } +}; + +} // namespace Detail +} // namespace Pomdog