1 /****
2 DIAMOND protein aligner
3 Copyright (C) 2020 Max Planck Society for the Advancement of Science e.V.
4 
5 Code developed by Benjamin Buchfink <benjamin.buchfink@tue.mpg.de>
6 
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 ****/
20 
21 #pragma once
22 #include <stdlib.h>
23 #include <cstddef>
24 #include <exception>
25 
26 namespace Util { namespace Memory {
27 
aligned_malloc(size_t n,size_t align)28 static inline void* aligned_malloc(size_t n, size_t align) {
29 #ifdef WIN32
30     void* p = _aligned_malloc(n, align);
31     if (p == nullptr)
32         throw std::bad_alloc();
33     return p;
34 #else
35     void* p;
36     if (posix_memalign(&p, align, n) != 0)
37         throw std::bad_alloc();
38     return p;
39 #endif
40 }
41 
aligned_free(void * p)42 static inline void aligned_free(void* p) {
43 #ifdef WIN32
44     _aligned_free(p);
45 #else
46     free(p);
47 #endif
48 }
49 
50 template <typename T, std::size_t N = 16>
51 class AlignmentAllocator {
52 public:
53     typedef T value_type;
54     typedef std::size_t size_type;
55     typedef std::ptrdiff_t difference_type;
56 
57     typedef T* pointer;
58     typedef const T* const_pointer;
59 
60     typedef T& reference;
61     typedef const T& const_reference;
62 
63 public:
AlignmentAllocator()64     inline AlignmentAllocator() throw () { }
65 
66     template <typename T2>
AlignmentAllocator(const AlignmentAllocator<T2,N> &)67     inline AlignmentAllocator(const AlignmentAllocator<T2, N>&) throw () { }
68 
~AlignmentAllocator()69     ~AlignmentAllocator() noexcept { }
70 
adress(reference r)71     inline pointer adress(reference r) {
72         return &r;
73     }
74 
adress(const_reference r)75     inline const_pointer adress(const_reference r) const {
76         return &r;
77     }
78 
allocate(size_type n)79     inline pointer allocate(size_type n) {
80         return (pointer)aligned_malloc(n * sizeof(value_type), N);
81     }
82 
deallocate(pointer p,size_type)83     inline void deallocate(pointer p, size_type) {
84         aligned_free(p);
85     }
86 
construct(pointer p,const value_type & wert)87     inline void construct(pointer p, const value_type& wert) {
88         new (p) value_type(wert);
89     }
90 
destroy(pointer p)91     inline void destroy(pointer p) {
92         p->~value_type();
93     }
94 
max_size()95     inline size_type max_size() const throw () {
96         return size_type(-1) / sizeof(value_type);
97     }
98 
99     template <typename T2>
100     struct rebind {
101         typedef AlignmentAllocator<T2, N> other;
102     };
103 
104     bool operator!=(const AlignmentAllocator<T, N>& other) const {
105         return !(*this == other);
106     }
107 
108     // Returns true if and only if storage allocated from *this
109     // can be deallocated from other, and vice versa.
110     // Always returns true for stateless allocators.
111     bool operator==(const AlignmentAllocator<T, N>& other) const {
112         return true;
113     }
114 };
115 
116 }}