aligned_allocator.hpp 2.57 KB
Newer Older
Damian S. Steiger's avatar
Damian S. Steiger committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Example codes for HPCSE course
// (c) 2012 Andreas Hehn, ETH Zurich

#ifndef HPCSE_ALIGNED_ALLOCATOR_HPP
#define HPCSE_ALIGNED_ALLOCATOR_HPP

#ifdef _WIN32
#include <malloc.h>
#else
#include <cstdlib>
#endif

#if __cplusplus >= 201103L 
#define NOEXCEPT_SPEC noexcept
#else
#define NOEXCEPT_SPEC
#endif

namespace hpcse {

// Alignment must be a power of 2 !
template <typename T, unsigned int Alignment>
class aligned_allocator {
  public:
    typedef T*              pointer;
    typedef T const*        const_pointer;
    typedef T&              reference;
    typedef T const&        const_reference;
    typedef T               value_type;
    typedef std::size_t     size_type;
    typedef std::ptrdiff_t  difference_type;

    template <typename U>
    struct rebind {
        typedef aligned_allocator<U,Alignment> other;
    };

    aligned_allocator() NOEXCEPT_SPEC {
    }

    aligned_allocator(aligned_allocator const& a) NOEXCEPT_SPEC {
    }

    template <typename U>
    aligned_allocator(aligned_allocator<U,Alignment> const& b) NOEXCEPT_SPEC {
    }

    pointer allocate(size_type n) {
        pointer p;
#ifdef _WIN32
        p = reinterpret_cast<pointer>(_aligned_malloc(n*sizeof(T), Alignment));
        if(p == 0)
            throw std::bad_alloc();
#else
        if(posix_memalign(reinterpret_cast<void**>(&p), Alignment, n * sizeof(T) ))
            throw std::bad_alloc();
#endif
        return p;
    }

    void deallocate(pointer p, size_type n) NOEXCEPT_SPEC {
#ifdef _WIN32
        _aligned_free(p);
#else
        std::free(p);
#endif
    }

    size_type max_size() const NOEXCEPT_SPEC {
        std::allocator<T> a;
        return a.max_size();
    }

#if __cplusplus >= 201103L 
    template <typename C, class... Args>
    void construct(C* c, Args&&... args) {
        new ((void*)c) C(std::forward<Args>(args)...);
    }
#else
    void construct(pointer p, const_reference t) {
        new((void *)p) T(t);
    }
#endif

    template <typename C>
    void destroy(C* c) {
        c->~C();
    }

    bool operator == (aligned_allocator const& a2) const NOEXCEPT_SPEC {
        return true;
    }

    bool operator != (aligned_allocator const& a2) const NOEXCEPT_SPEC {
        return false;
    }

    template <typename U, unsigned int UAlignment>
    bool operator == (aligned_allocator<U,UAlignment> const& b) const NOEXCEPT_SPEC {
        return false;
    }

    template <typename U, unsigned int UAlignment>
    bool operator != (aligned_allocator<U,UAlignment> const& b) const NOEXCEPT_SPEC {
        return true;
    }
};

}

#undef NOEXPECT_SPEC

#endif //HPCSE_ALIGNED_ALLOCATOR_HPP