#pragma once #include #include #include #include #include "megdnn/arch.h" #if defined(_MSC_VER) || defined(__MINGW32__) #include "malloc.h" #endif #if defined(__ANDROID__) || defined(ANDROID) #include "malloc.h" #define HAS_MEMALIGN #elif !defined(_MSC_VER) && !defined(__MINGW32__) #define HAS_POSIX_MEMALIGN #endif namespace ah { /** * @tparam _Tp Type of allocated object. * @tparam _align Alignment, in bytes. */ template class aligned_allocator : public std::allocator<_Tp> { public: typedef size_t size_type; typedef std::ptrdiff_t difference_type; typedef _Tp* pointer; typedef const _Tp* const_pointer; typedef _Tp& reference; typedef const _Tp& const_reference; typedef _Tp value_type; template struct rebind { typedef aligned_allocator<_Tp1, _align> other; }; typedef std::true_type propagate_on_container_move_assignment; aligned_allocator() MEGDNN_NOEXCEPT {} template aligned_allocator(const aligned_allocator<_Tp1, _align>&) MEGDNN_NOEXCEPT {} ~aligned_allocator() MEGDNN_NOEXCEPT {} // NB: __n is permitted to be 0. The C++ standard says nothing // about what the return value is when __n == 0. pointer allocate(size_type __n, const void* = 0) { if (__n > this->max_size()) megdnn_trap(); #ifdef HAS_POSIX_MEMALIGN _Tp* result; if (posix_memalign(&(void*&)result, _align, __n * sizeof(_Tp)) != 0) { if (_Nothrow) { return nullptr; } else { megdnn_trap(); } } return result; #elif defined(HAS_MEMALIGN) return (_Tp*)memalign(_align, __n * sizeof(_Tp)); #elif defined(_MSC_VER) || defined(__MINGW32__) return (_Tp*)_aligned_malloc(__n * sizeof(_Tp), _align); #else #warning \ "aligned allocator fallbacks to normal malloc; allocated address may be unaligned" return (_Tp*)malloc(__n * sizeof(_Tp)); #endif } // __p is not permitted to be a null pointer. void deallocate(pointer __p, size_type) { #ifdef _MSC_VER _aligned_free((void*)__p); #else free((void*)__p); #endif } }; template inline bool operator==( const aligned_allocator<_T1, _A1>&, const aligned_allocator<_T2, _A2>&) { return true; } template inline bool operator!=( const aligned_allocator<_T1, _A1>&, const aligned_allocator<_T2, _A2>&) { return false; } /// allocator specialization. template class aligned_allocator { public: typedef size_t size_type; typedef std::ptrdiff_t difference_type; typedef void* pointer; typedef const void* const_pointer; typedef void value_type; template struct rebind { typedef aligned_allocator<_Tp1, _align> other; }; typedef std::true_type propagate_on_container_move_assignment; }; } // namespace ah // vim: syntax=cpp.doxygen