Entry

プログラミングメモ - aligned_allocator とか

2011年04月20日

巷で公開されているアロケータは _aligned_malloc や posix_memalign をラップしている処理系依存のものが多いようなので,試験的に書いてみました。さっき書いたばっかで,あまりテストしてないんですけど。

#include <cassert>
#include <cstdlib>
#include <limits>

template<typename T, std::size_t Align = 0x10>
class aligned_allocator {
public:
  typedef std::size_t size_type;
  typedef T* pointer;
  typedef const T* const_pointer;
  typedef T& reference;
  typedef const T& const_reference;
  typedef T value_type;
public:
  typedef std::uintptr_t uintptr_type;
  static const size_type align_size = Align;
  static const size_type offset_size = sizeof(void*) + align_size;
public:
  aligned_allocator() {}
  aligned_allocator(const aligned_allocator& other) {}
  template<typename U> aligned_allocator(const aligned_allocator<U>& other) {}
  virtual ~aligned_allocator() {}
private:  // no implement
  aligned_allocator& operator=(const aligned_allocator<T>& rhs);
public:
  pointer allocate(size_type count, const void* hint = 0) {
    // checking if specified alignment value is power of 2.
    assert((align_size & (align_size - 1)) == 0);
    // allocate memory on aligned address
    size_type alloc_size = offset_size + (sizeof(value_type) * count);
    void** ptr = 0;
    void* addr = ::malloc(alloc_size);
    if (addr != 0) {
      ptr = (void**)(((uintptr_type)(addr) + offset_size) & ~(align_size - 1));
      *(ptr - 1) = addr;
    }
    return static_cast<pointer>((void*)ptr);
  }
  void deallocate(pointer ptr) {
    assert(ptr != 0);
    ::free(*(((void**)ptr) - 1));
  }
  void construct(pointer ptr, const_reference value) {
    new ((void*)ptr) value_type(value);
  }
  void destroy(pointer ptr, size_type count) {
    ::operator delete((void*)ptr);
  }
  pointer address(reference value) const {
    return &value;
  }
  const_pointer address(const_reference value) const {
    return &value;
  }
  size_type max_size() const {
    return std::numeric_limits<size_t>::max() / sizeof(value_type);
  }
};

template<typename T, typename U>
bool operator==(const aligned_allocator<T>&, const aligned_allocator<T>&) {
  return true;
}
template<typename T, typename U>
bool operator!=(const aligned_allocator<T>&, const aligned_allocator<T>&) {
  return false;
}

かなり汚いことをやっているので,reinterpret_cast<T> なところは,同じく汚い(?)Cスタイルでキャスト。ぱっと見 STL っぽく見えるけど,自前のクラス用に作ったので互換性はありません。デフォルトのアラインメントは 0x10 で,2の冪乗を指定していない場合は(今のところ) assert です。std::uintptr_t を使ってたりするので,C++0x をサポートしている処理系でビルドできます。

C++ から SIMD とか触ってみたい方はどうぞ。

【追記】
不具合を見つけたので直して再掲載しました(2011/04/21)。

Trackback
Trackback URL:
Ads
About
Search This Site
Ads
Categories
Recent Entries
Log Archive
Syndicate This Site
Info.
クリエイティブ・コモンズ・ライセンス
Movable Type 3.36
Valid XHTML 1.1!
Valid CSS!
ブログタイムズ

© 2003-2012 AIAN