From 4be8438cdddcc11141209a8d0f5538fbb014c637 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 9 Apr 2014 11:21:41 -0700 Subject: [PATCH] Updated Boost.Align implementation --- README.md | 14 + doc/html/index.html | 679 ++++++++++++++++++ example/aligned_ptr.hpp | 27 + example/aligned_vector.cpp | 19 + example/aligned_vector.hpp | 19 + example/make_aligned.cpp | 19 + example/make_aligned.hpp | 33 + include/boost/align.hpp | 18 + include/boost/align/align.hpp | 28 + include/boost/align/aligned_alloc.hpp | 50 ++ include/boost/align/aligned_allocator.hpp | 162 +++++ .../boost/align/aligned_allocator_adaptor.hpp | 183 +++++ include/boost/align/detail/address.hpp | 26 + include/boost/align/detail/addressof.hpp | 32 + include/boost/align/detail/align.hpp | 39 + include/boost/align/detail/align_cxx11.hpp | 22 + include/boost/align/detail/aligned_alloc.hpp | 53 ++ .../align/detail/aligned_alloc_android.hpp | 34 + .../boost/align/detail/aligned_alloc_msvc.hpp | 34 + .../align/detail/aligned_alloc_posix.hpp | 44 ++ .../align/detail/aligned_alloc_sunos.hpp | 34 + include/boost/align/detail/alignment_of.hpp | 32 + include/boost/align/detail/is_aligned.hpp | 29 + include/boost/align/detail/is_alignment.hpp | 25 + include/boost/align/detail/is_power_of_2.hpp | 27 + include/boost/align/detail/max_count_of.hpp | 27 + include/boost/align/detail/max_size.hpp | 27 + include/boost/align/is_aligned.hpp | 22 + index.html | 31 + test/Jamfile.v2 | 14 + test/align_test.cpp | 91 +++ test/aligned_alloc_test.cpp | 57 ++ test/aligned_allocator_adaptor_test.cpp | 104 +++ test/aligned_allocator_test.cpp | 81 +++ test/is_aligned_test.cpp | 67 ++ 35 files changed, 2203 insertions(+) create mode 100644 README.md create mode 100644 doc/html/index.html create mode 100644 example/aligned_ptr.hpp create mode 100644 example/aligned_vector.cpp create mode 100644 example/aligned_vector.hpp create mode 100644 example/make_aligned.cpp create mode 100644 example/make_aligned.hpp create mode 100644 include/boost/align.hpp create mode 100644 include/boost/align/align.hpp create mode 100644 include/boost/align/aligned_alloc.hpp create mode 100644 include/boost/align/aligned_allocator.hpp create mode 100644 include/boost/align/aligned_allocator_adaptor.hpp create mode 100644 include/boost/align/detail/address.hpp create mode 100644 include/boost/align/detail/addressof.hpp create mode 100644 include/boost/align/detail/align.hpp create mode 100644 include/boost/align/detail/align_cxx11.hpp create mode 100644 include/boost/align/detail/aligned_alloc.hpp create mode 100644 include/boost/align/detail/aligned_alloc_android.hpp create mode 100644 include/boost/align/detail/aligned_alloc_msvc.hpp create mode 100644 include/boost/align/detail/aligned_alloc_posix.hpp create mode 100644 include/boost/align/detail/aligned_alloc_sunos.hpp create mode 100644 include/boost/align/detail/alignment_of.hpp create mode 100644 include/boost/align/detail/is_aligned.hpp create mode 100644 include/boost/align/detail/is_alignment.hpp create mode 100644 include/boost/align/detail/is_power_of_2.hpp create mode 100644 include/boost/align/detail/max_count_of.hpp create mode 100644 include/boost/align/detail/max_size.hpp create mode 100644 include/boost/align/is_aligned.hpp create mode 100644 index.html create mode 100644 test/Jamfile.v2 create mode 100644 test/align_test.cpp create mode 100644 test/aligned_alloc_test.cpp create mode 100644 test/aligned_allocator_adaptor_test.cpp create mode 100644 test/aligned_allocator_test.cpp create mode 100644 test/is_aligned_test.cpp diff --git a/README.md b/README.md new file mode 100644 index 0000000..5d34131 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# boost.align + +Boost.Align provides memory alignment functions, allocators, and adaptors. + +### directories + +* **doc** - Boost.Align documentation +* **example** - Boost.Align examples +* **include** - Source code of Boost.Align +* **test** - Boost.Align unit tests + +### more information + +* [Documentation](http://glenfe.github.io/align) diff --git a/doc/html/index.html b/doc/html/index.html new file mode 100644 index 0000000..972aa33 --- /dev/null +++ b/doc/html/index.html @@ -0,0 +1,679 @@ + + + + +Boost.Align + + + + +

boost.align

+

© 2014 Glen Fernandes

+

Contents

+
    +
  1. Introduction
  2. +
  3. Rationale
  4. +
  5. Vocabulary
  6. +
  7. Synopsis
  8. +
  9. align
  10. +
  11. aligned_alloc
  12. +
  13. aligned_free
  14. +
  15. aligned_allocator
  16. +
  17. aligned_allocator_adaptor
  18. +
  19. is_aligned
  20. +
  21. Examples
  22. +
  23. Testing
  24. +
  25. Acknowledgments
  26. +
  27. History
  28. +
  29. License
  30. +
+

Introduction

+

The header <boost/align.hpp> + provides function align for implementations which do + not have the C++11 standard library std::align + function available.

+

It provides allocation functions aligned_alloc and + aligned_free as their functionality is not yet + available in the C++ standard library. They use platform specific + functions, if available, or use standard library functions in + conjunction with align.

+

It provides C++ allocators, class templates + aligned_allocator and + aligned_allocator_adaptor, which respect alignment. + The first uses aligned_alloc and + aligned_free while the second uses the allocator in + conjunction with align.

+

It also provides function is_aligned to test the + alignment of a pointer.

+

Rationale

+

C++11 added the ability to specify increased alignment + (over-alignment) for class types. Unfortunately, + ::operator new allocation functions, new + expressions, and the default allocator, + std::allocator, do not support dynamic memory + allocation of over-aligned data.

+

The aligned_alloc function can be used in place of + ::operator new to specify the alignment of the memory + allocated.

+

The aligned_allocator class template can be used in + place of std::allocator as an alignment-aware default + allocator.

+

The aligned_allocator_adaptor class template can be + used to adapt any allocator into an alignment-aware allocator.

+

Vocabulary

+

N3485 3.11 [basic.align]

+
+ 1 Object types have alignment requirements + which place restrictions on the addresses at which an object of + that type may be allocated. An alignment is an + implementation-defined integer value representing the number of + bytes between successive addresses at which a given object can be + allocated. An object type imposes an alignment requirement on + every object of that type; stricter alignment can be requested + using the alignment specifier. +
+
+ 2 A fundamental alignment is represented by an + alignment less than or equal to the greatest alignment supported + by the implementation in all contexts, which is equal to + alignof(std::max_align_t). The alignment required + for a type might be different when it is used as the type of a + complete object and when it is used as the type of a + subobject. [ Example: +
+
struct B { long double d; };
+struct D : virtual B { char c; };
+
+ When D is the type of a complete object, it will + have a subobject of type B, so it must be aligned + appropriately for a long double. If D + appears as a subobject of another object that also has + B as a virtual base class, the B + subobject might be part of a different subobject, reducing the + alignment requirements on the D subobject. + end example ] The + result of the alignof operator reflects the alignment + requirement of the type in the complete-object case. +
+
+ 3 An extended alignment is represented by an + alignment greater than alignof(std::max_align_t). It + is implementation-defined whether any extended alignments are + supported and the contexts in which they are supported. A type + having an extended alignment requirement is an + over-aligned type. [ + Note: every over-aligned type is or contains a + class type to which extended alignment applies (possibly through a + non-static data member). end + note ] +
+
+ 4 Alignments are represented as values of the type + std::size_t. Valid alignments include only those + values returned by an alignof expression for the + fundamental types plus an additional implementation-defined set + of values, which may be empty. Every alignment value shall be a + non-negative integral power of two. +
+

Synopsis

+
namespace boost {
+    void* align(std::size_t alignment, std::size_t size,
+        void*& ptr, std::size_t& space);
+
+    void* aligned_alloc(std::size_t alignment,
+        std::size_t size);
+
+    void aligned_free(void* ptr);
+
+    template<class T, std::size_t Alignment = 1>
+    class aligned_allocator;
+
+    template<std::size_t Alignment>
+    class aligned_allocator<void, Alignment>;
+
+    template<class T1, class T2, std::size_t Alignment>
+    bool operator==(const aligned_allocator<T1,
+        Alignment>&, const aligned_allocator<T2,
+        Alignment>&);
+
+    template<class T1, class T2, std::size_t Alignment>
+    bool operator!=(const aligned_allocator<T1,
+        Alignment>&, const aligned_allocator<T2,
+        Alignment>&);
+
+    template<class Allocator, std::size_t Alignment = 1>
+    class aligned_allocator_adaptor;
+
+    template<class A1, class A2, std::size_t Alignment>
+    bool operator==(const aligned_allocator_adaptor<A1,
+        Alignment>& a, const aligned_allocator_adaptor<A2,
+        Alignment>& b);
+
+    template<class A1, class A2, std::size_t Alignment>
+    bool operator!=(const aligned_allocator_adaptor<A1,
+        Alignment>& a, const aligned_allocator_adaptor<A2,
+        Alignment>& b);
+
+    bool is_aligned(std::size_t alignment,
+        const void* ptr);
+}
+

align

+
void* align(std::size_t alignment, std::size_t size,
+    void*& ptr, std::size_t& space);
+
+ Effects: If it is possible to fit + size bytes of storage aligned by alignment into the + buffer pointed to by ptr with length + space, the function updates ptr to + point to the first possible address of such storage and decreases + space by the number of bytes used for alignment. + Otherwise, the function does nothing. +
+
+ Requires: +
+

alignment shall be a fundamental + alignment value or an extended alignment value, and shall be a + power of two

+

ptr shall point to contiguous storage of + at least space bytes

+
+
+
+ Returns: A null pointer if the requested aligned buffer + would not fit into the available space, otherwise the adjusted + value of ptr. +
+
+ Note: The function updates its ptr and + space arguments so that it can be called repeatedly + with possibly different alignment and + size arguments for the same buffer. +
+

aligned_alloc

+
void* aligned_alloc(std::size_t alignment,
+    std::size_t size);
+
+ Description: The aligned_alloc + function allocates space for an object whose alignment is + specified by alignment, whose size is specified by + size, and whose value is indeterminate. The value of + alignment shall be a power of two. +
+
+ Returns: The aligned_alloc function returns + either a null pointer or a pointer to the allocated space. +
+
+ Note: On certain platforms the space allocated may be + slightly larger than size bytes, for alignment + purposes, by an additional sizeof(void*) and + alignment bytes. +
+

aligned_free

+
void aligned_free(void* ptr);
+
+ Description: The aligned_free + function causes the space pointed to by ptr to be + deallocated, that is, made available for further allocation. If + ptr is a null pointer, no action occurs. Otherwise, + if the argument does not match a pointer earlier returned by the + aligned_alloc function, or if the space has been + deallocated by a call to aligned_free, the behavior + is undefined. +
+
+ Returns: The aligned_free function returns + no value. +
+

aligned_allocator

+
template<class T, std::size_t Alignment = 1>
+class aligned_allocator;
+
+template<std::size_t Alignment>
+class aligned_allocator<void, Alignment> {
+public:
+    typedef void value_type;
+    typedef void* pointer;
+    typedef const void* const_pointer;
+
+    template<class U>
+    struct rebind {
+        typedef aligned_allocator<U, Alignment> other;
+    };
+};
+
+template<class T, std::size_t Alignment>
+class aligned_allocator {
+public:
+    typedef T value_type;
+    typedef T* pointer;
+    typedef const T* const_pointer;
+    typedef std::size_t size_type;
+    typedef std::ptrdiff_t difference_type;
+    typedef T& reference;
+    typedef const T& const_reference;
+
+    template<class U>
+    struct rebind {
+        typedef aligned_allocator<U, Alignment> other;
+    };
+
+    aligned_allocator();
+
+    template<class U>
+    aligned_allocator(const aligned_allocator<U, Alignment>&);
+
+    pointer address(reference x) const;
+
+    const_pointer address(const_reference x) const;
+
+    pointer allocate(size_type n,
+        aligned_allocator<void, Alignment>::const_pointer = 0);
+
+    void deallocate(pointer p, size_type);
+
+    size_type max_size() const;
+
+    template<class U, class... Args>
+    void construct(U* memory, Args&&... args);
+
+    template<class U>
+    void destroy(U* memory);
+};
+
+template<class T1, class T2, std::size_t Alignment>
+bool operator==(const aligned_allocator<T1,
+    Alignment>&, const aligned_allocator<T2,
+    Alignment>&);
+
+template<class T1, class T2, std::size_t Alignment>
+bool operator!=(const aligned_allocator<T1,
+    Alignment>&, const aligned_allocator<T2,
+    Alignment>&);
+

aligned_allocator requirements

+

The Alignment template parameter is the minimum + alignment to specify for allocations, if it is larger than the + alignment of the value type. The value of Alignment + shall be a power of two.

+

aligned_allocator members

+

Except for the destructor, member functions of the aligned + allocator shall not introduce data races as a result of concurrent + calls to those member functions from different threads. Calls to + these functions that allocate or deallocate a particular unit of + storage shall occur in a single total order, and each such + deallocation call shall happen before the next allocation (if any) + in this order.

+
pointer address(reference x) const;
+
+ Returns: The actual address of the object + referenced by x, even in the presence of an + overloaded operator&. +
+
const_pointer address(const_reference x) const;
+
+ Returns: The actual address of the object + referenced by x, even in the presence of an + overloaded operator&. +
+
pointer allocate(size_type n,
+    aligned_allocator<void, Alignment>::const_pointer = 0);
+
+ Returns: A pointer to the initial element of an array of + storage of size n * sizeof(T), aligned on the + maximum of the minimum alignment specified and the alignment of + objects of type T. +
+
+ Remarks: The storage is obtained by calling + aligned_alloc(std::size_t, std::size_t). +
+
+ Throws: std::bad_alloc if the storage cannot + be obtained. +
+
void deallocate(pointer p, size_type);
+
+ Requires: p shall be a pointer value + obtained from allocate(). +
+
+ Effects: Deallocates the storage referenced by + p. +
+
+ Remarks: Uses aligned_free(void*). +
+
size_type max_size() const;
+
+ Returns: The largest value N for which the call + allocate(N) might succeed. +
+
template<class U, class... Args>
+void construct(U* p, Args&&... args);
+
+ Effects: ::new((void*)p) + U(std::forward<Args>(args)...) +
+
template<class U>
+void destroy(U* p);
+
+ Effects: p->~U() +
+

aligned_allocator globals

+
template<class T1, class T2, std::size_t Alignment>
+bool operator==(const aligned_allocator<T1,
+    Alignment>&, const aligned_allocator<T2,
+    Alignment>&);
+
+ Returns: true. +
+
template<class T1, class T2, std::size_t Alignment>
+bool operator!=(const aligned_allocator<T1,
+    Alignment>&, const aligned_allocator<T2,
+    Alignment>&);
+
+ Returns: false. +
+

aligned_allocator notes

+

Specifying minimum alignment is generally only suitable for + containers such as vector and undesirable with other, node-based, + containers. For node-based containers, such as list, the node + object would have the minimum alignment specified instead of the + value type object.

+

aligned_allocator_adaptor

+
template<class Allocator, std::size_t Alignment = 1>
+class aligned_allocator_adaptor
+    : public Allocator {
+private:
+    typedef std::allocator_traits<Allocator> Traits;
+
+public:
+    typedef Allocator allocator_type;
+
+    typedef typename Traits::value_type value_type;
+    typedef typename Traits::size_type size_type;
+
+    typedef value_type* pointer;
+    typedef const value_type* const_pointer;
+    typedef void* void_pointer;
+    typedef const void* const_void_pointer;
+    typedef std::ptrdiff_t difference_type;
+
+    template<class U>
+    struct rebind {
+        typedef aligned_allocator_adaptor<typename Traits::
+            template rebind_alloc<U>, Alignment> other;
+    };
+
+    aligned_allocator_adaptor();
+
+    template<class A>
+    explicit aligned_allocator_adaptor(A&& alloc);
+
+    template<class U>
+    aligned_allocator_adaptor(const
+        aligned_allocator_adaptor<U, Alignment>& other);
+
+    allocator_type& allocator();
+
+    const allocator_type& allocator() const;
+
+    pointer allocate(size_type n);
+
+    pointer allocate(size_type n, const_void_pointer hint);
+
+    void deallocate(pointer p, size_type n);
+};
+
+template<class A1, class A2, std::size_t Alignment>
+bool operator==(const aligned_allocator_adaptor<A1,
+    Alignment>& a, const aligned_allocator_adaptor<A2,
+    Alignment>& b);
+
+template<class A1, class A2, std::size_t Alignment>
+bool operator!=(const aligned_allocator_adaptor<A1,
+    Alignment>& a, const aligned_allocator_adaptor<A2,
+    Alignment>& b);
+

aligned_allocator_adaptor requirements

+

The Alignment template parameter is the minimum + alignment to specify for allocations, if it is larger than the + alignment of the value type. The value of Alignment + shall be a fundamental alignment value or an extended alignment + value, and shall be a power of two.

+

aligned_allocator_adaptor constructors

+
aligned_allocator_adaptor();
+
+ Effects: value-initializes the + Allocator base class. +
+
template<class A>
+explicit aligned_allocator_adaptor(A&& alloc);
+
+ Requires: Allocator shall be + constructible from A. +
+
+ Effects: initializes the Allocator + base class with std::forward<A>(alloc). +
+
template<class U>
+aligned_allocator_adaptor(const
+    aligned_allocator_adaptor<U, Alignment>& other);
+
+ Effects: initializes the Allocator + base class with the allocator from other. +
+

aligned_allocator_adaptor members

+
allocator_type& allocator();
+
+ Returns: + static_cast<Allocator&>(*this). +
+
const allocator_type& allocator() const;
+
+ Returns: + static_cast<const Allocator&>(*this). +
+
pointer allocate(size_type n);
+
+ Returns: A pointer to the initial element of an array of + storage of size n * sizeof(value_type), aligned on + the maximum of the minimum alignment specified and the alignment + of objects of type value_type. +
+
+ Remarks: The storage is obtained by calling + A2::allocate on an object a2, where + a2 of type A2 is a rebound copy of + allocator() where its value_type is + unspecified. +
+
+ Throws: An exception thrown from + A2::allocate if the storage cannot be obtained. +
+
pointer allocate(size_type n,
+    const_void_pointer hint);
+
+ Requires: hint is a value obtained by + calling allocate() on any equivalent aligned + allocator adaptor object, or else nullptr. +
+
+ Returns: A pointer to the initial element of an array of + storage of size n * sizeof(value_type), aligned on + the maximum of the minimum alignment specified and the alignment + of objects of type value_type. +
+
+ Remarks: The storage is obtained by calling + A2::allocate on an object a2, where + a2 of type A2 is a rebound copy of + allocator() where its value_type is + unspecified. +
+
+ Throws: An exception thrown from + A2::allocate if the storage cannot be obtained. +
+
void deallocate(pointer p, size_type n);
+
+ Requires: p shall be a pointer value + obtained from allocate(). n shall equal + the value passed as the first argument to the invocation of + allocate which returned p. +
+
+ Effects: Deallocates the storage referenced by + p. +
+
+ Remarks: Uses A2::deallocate on an object + a2, where a2 of type A2 + is a rebound copy of allocator() where its + value_type is unspecified. +
+

aligned_allocator_adaptor operators

+
template<class A1, class A2, std::size_t Alignment>
+bool operator==(const aligned_allocator_adaptor<A1,
+    Alignment>& a, const aligned_allocator_adaptor<A2,
+    Alignment>& b);
+
+ Returns: a.allocator() == b.allocator(). +
+
template<class A1, class A2, std::size_t Alignment>
+bool operator!=(const aligned_allocator_adaptor<A1,
+    Alignment>& a, const aligned_allocator_adaptor<A2,
+    Alignment>& b);
+
+ Returns: !(a == b). +
+

aligned_allocator_adaptor notes

+

This adaptor can be used with a C++11 allocator whose + pointer type is a smart pointer but the adaptor will + expose only raw pointers.

+

is_aligned

+
bool is_aligned(std::size_t alignment,
+    const void* ptr);
+
+ Description: The is_aligned function + determines whether the space pointed to by ptr has + alignment specified by alignment. +
+
+ Returns: The is_aligned function returns + true if and only if ptr points to space + that has alignment specified by alignment. +
+

Examples

+

aligned_ptr and make_aligned

+
#include <boost/align.hpp>
+#include <memory>
+
+template<class T>
+struct aligned_delete {
+    void operator()(T* ptr) {
+        ptr->~T();
+        boost::aligned_free(ptr);
+    }
+};
+
+template<class T>
+using aligned_ptr = std::unique_ptr<T,
+    aligned_delete<T> >;
+
+template<class T, class... Args>
+inline aligned_ptr<T>
+    make_aligned(Args&&... args)
+{
+    auto p = boost::aligned_alloc(alignof(T),
+        sizeof(T));
+    if (!p) {
+        throw std::bad_alloc();
+    }
+    try {
+        auto q = ::new(p)
+            T(std::forward<Args>(args)...);
+        return aligned_ptr<T>(q);
+    } catch (...) {
+        boost::aligned_free(p);
+        throw;
+    }
+}
+
+struct alignas(16) type {
+    float data[4];
+};
+
+int main()
+{
+    auto p = make_aligned<type>();
+    p->data[0] = 1.0f;
+}
+

aligned_vector

+
#include <boost/align.hpp>
+#include <vector>
+
+template<class T, std::size_t Alignment = 1>
+using aligned_vector = std::vector<T,
+    boost::aligned_allocator<T, Alignment> >;
+
+enum {
+    cache_line = 64
+};
+
+int main()
+{
+    aligned_vector<int, cache_line> v(32);
+    v[0] = 1;
+}
+

Testing

+

The following compilers and platforms have been tested.

+ +

Acknowledgments

+

Thank you to everyone who helped me improve this library.

+ +

Thank you to Ahmed Charles for being the review manager.

+

History

+

2014.02.19. Glen Fernandes first implemented + Boost.Align.

+

License

+

Distributed under the + Boost Software + License, Version 1.0.

+ + diff --git a/example/aligned_ptr.hpp b/example/aligned_ptr.hpp new file mode 100644 index 0000000..9ffbe9f --- /dev/null +++ b/example/aligned_ptr.hpp @@ -0,0 +1,27 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef ALIGNED_PTR_HPP +#define ALIGNED_PTR_HPP + +#include +#include + +template +struct aligned_delete { + void operator()(T* ptr) { + ptr->~T(); + boost::aligned_free(ptr); + } +}; + +template +using aligned_ptr = std::unique_ptr >; + +#endif diff --git a/example/aligned_vector.cpp b/example/aligned_vector.cpp new file mode 100644 index 0000000..6d120df --- /dev/null +++ b/example/aligned_vector.cpp @@ -0,0 +1,19 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#include "aligned_vector.hpp" + +enum { + cache_line = 64 +}; + +int main() +{ + aligned_vector v(32); + v[0] = 1; +} diff --git a/example/aligned_vector.hpp b/example/aligned_vector.hpp new file mode 100644 index 0000000..98491b4 --- /dev/null +++ b/example/aligned_vector.hpp @@ -0,0 +1,19 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef ALIGNED_VECTOR_HPP +#define ALIGNED_VECTOR_HPP + +#include +#include + +template +using aligned_vector = std::vector >; + +#endif diff --git a/example/make_aligned.cpp b/example/make_aligned.cpp new file mode 100644 index 0000000..da3db44 --- /dev/null +++ b/example/make_aligned.cpp @@ -0,0 +1,19 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#include "make_aligned.hpp" + +struct alignas(16) type { + float data[4]; +}; + +int main() +{ + auto p = make_aligned(); + p->data[0] = 1.0f; +} diff --git a/example/make_aligned.hpp b/example/make_aligned.hpp new file mode 100644 index 0000000..968abce --- /dev/null +++ b/example/make_aligned.hpp @@ -0,0 +1,33 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef MAKE_ALIGNED_HPP +#define MAKE_ALIGNED_HPP + +#include "aligned_ptr.hpp" + +template +inline aligned_ptr + make_aligned(Args&&... args) +{ + auto p = boost::aligned_alloc(alignof(T), + sizeof(T)); + if (!p) { + throw std::bad_alloc(); + } + try { + auto q = ::new(p) + T(std::forward(args)...); + return aligned_ptr(q); + } catch (...) { + boost::aligned_free(p); + throw; + } +} + +#endif diff --git a/include/boost/align.hpp b/include/boost/align.hpp new file mode 100644 index 0000000..6e74e71 --- /dev/null +++ b/include/boost/align.hpp @@ -0,0 +1,18 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_HPP +#define BOOST_ALIGN_HPP + +#include +#include +#include +#include +#include + +#endif diff --git a/include/boost/align/align.hpp b/include/boost/align/align.hpp new file mode 100644 index 0000000..57e40a0 --- /dev/null +++ b/include/boost/align/align.hpp @@ -0,0 +1,28 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_ALIGN_HPP +#define BOOST_ALIGN_ALIGN_HPP + +#include + +#if !defined(BOOST_NO_CXX11_STD_ALIGN) +#include +#else +#include +#endif + +namespace boost { + namespace alignment { + using detail::align; + } + + using alignment::align; +} + +#endif diff --git a/include/boost/align/aligned_alloc.hpp b/include/boost/align/aligned_alloc.hpp new file mode 100644 index 0000000..c95660b --- /dev/null +++ b/include/boost/align/aligned_alloc.hpp @@ -0,0 +1,50 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_ALIGNED_ALLOC_HPP +#define BOOST_ALIGN_ALIGNED_ALLOC_HPP + +#include + +#if defined(BOOST_HAS_UNISTD_H) +#include +#endif + +#if defined(__APPLE__) || defined(__APPLE_CC__) || defined(macintosh) +#include +#endif + +#if defined(BOOST_MSVC) +#include +#elif defined(__MINGW32__) && (__MSVCRT_VERSION__ >= 0x0700) +#include +#elif MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 +#include +#elif defined(__ANDROID__) +#include +#elif defined(__SunOS_5_11) || defined(__SunOS_5_12) +#include +#elif defined(sun) || defined(__sun) +#include +#elif (_POSIX_C_SOURCE >= 200112L) || (_XOPEN_SOURCE >= 600) +#include +#else +#include +#endif + +namespace boost { + namespace alignment { + using detail::aligned_alloc; + using detail::aligned_free; + } + + using alignment::aligned_alloc; + using alignment::aligned_free; +} + +#endif diff --git a/include/boost/align/aligned_allocator.hpp b/include/boost/align/aligned_allocator.hpp new file mode 100644 index 0000000..a6fa4c8 --- /dev/null +++ b/include/boost/align/aligned_allocator.hpp @@ -0,0 +1,162 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_ALIGNED_ALLOCATOR_HPP +#define BOOST_ALIGN_ALIGNED_ALLOCATOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#include +#endif + +namespace boost { + namespace alignment { + template + class aligned_allocator; + + template + class aligned_allocator { + BOOST_STATIC_ASSERT(detail:: + is_power_of_2::value); + + public: + typedef void value_type; + typedef void* pointer; + typedef const void* const_pointer; + + template + struct rebind { + typedef aligned_allocator other; + }; + }; + + template + class aligned_allocator { + BOOST_STATIC_ASSERT(detail:: + is_power_of_2::value); + + public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T& reference; + typedef const T& const_reference; + + private: + enum { + TypeAlign = detail:: + alignment_of::value, + MaxAlign = detail:: + max_size::value + }; + + public: + template + struct rebind { + typedef aligned_allocator other; + }; + + aligned_allocator() { + } + + template + aligned_allocator(const aligned_allocator&) { + } + + pointer address(reference value) const { + return detail::addressof(value); + } + + const_pointer address(const_reference value) const { + return detail::addressof(value); + } + + pointer allocate(size_type size, + aligned_allocator::const_pointer = 0) { + void* p1 = aligned_alloc(MaxAlign, sizeof(T) * size); + if (!p1) { + throw std::bad_alloc(); + } + return static_cast(p1); + } + + void deallocate(pointer memory, size_type) { + alignment::aligned_free(memory); + } + + size_type max_size() const { + return detail::max_count_of::value; + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template + void construct(U* memory, Args&&... args) { + void* p1 = memory; + ::new(p1) U(std::forward(args)...); + } +#endif + template + void construct(U* memory, U&& value) { + void* p1 = memory; + ::new(p1) U(std::move(value)); + } +#endif + + template + void construct(U* memory, const U& value) { + void* p1 = memory; + ::new(p1) U(value); + } + + template + void construct(U* memory) { + void* p1 = memory; + ::new(p1) U(); + } + + template + void destroy(U* memory) { + (void)memory; + memory->~U(); + } + }; + + template + inline bool operator==(const aligned_allocator&, const aligned_allocator&) + { + return true; + } + + template + inline bool operator!=(const aligned_allocator&, const aligned_allocator&) + { + return false; + } + } + + using alignment::aligned_allocator; +} + +#endif diff --git a/include/boost/align/aligned_allocator_adaptor.hpp b/include/boost/align/aligned_allocator_adaptor.hpp new file mode 100644 index 0000000..8b7d4f2 --- /dev/null +++ b/include/boost/align/aligned_allocator_adaptor.hpp @@ -0,0 +1,183 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_HPP +#define BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_HPP + +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +#include +#endif + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#include +#endif + +namespace boost { + namespace alignment { + template + class aligned_allocator_adaptor + : public Allocator { + BOOST_STATIC_ASSERT(detail:: + is_power_of_2::value); + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + typedef std::allocator_traits Traits; + typedef typename Traits:: + template rebind_alloc CharAlloc; + typedef typename Traits:: + template rebind_traits CharTraits; + typedef typename CharTraits::pointer CharPtr; +#else + typedef typename Allocator:: + template rebind::other CharAlloc; + typedef typename CharAlloc::pointer CharPtr; +#endif + + public: + typedef Allocator allocator_type; + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + typedef typename Traits::value_type value_type; + typedef typename Traits::size_type size_type; +#else + typedef typename Allocator::value_type value_type; + typedef typename Allocator::size_type size_type; +#endif + + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef void* void_pointer; + typedef const void* const_void_pointer; + typedef std::ptrdiff_t difference_type; + + private: + enum { + TypeAlign = detail:: + alignment_of::value, + PtrAlign = detail:: + alignment_of::value, + BlockAlign = detail:: + max_size::value, + MaxAlign = detail:: + max_size::value + }; + + public: + template + struct rebind { +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + typedef aligned_allocator_adaptor, Alignment> other; +#else + typedef aligned_allocator_adaptor::other, Alignment> other; +#endif + }; + + aligned_allocator_adaptor() + : Allocator() { + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template + explicit aligned_allocator_adaptor(A&& alloc) + : Allocator(std::forward(alloc)) { + } +#else + template + explicit aligned_allocator_adaptor(const A& alloc) + : Allocator(alloc) { + } +#endif + + template + aligned_allocator_adaptor(const + aligned_allocator_adaptor& other) + : Allocator(other.allocator()) { + } + + allocator_type& allocator() { + return static_cast(*this); + } + + const allocator_type& allocator() const { + return static_cast(*this); + } + + pointer allocate(size_type size) { + std::size_t n1 = size * sizeof(value_type); + std::size_t n2 = n1 + MaxAlign; + CharAlloc a1(allocator()); + CharPtr p1 = a1.allocate(sizeof(p1) + n2); + void* p2 = detail::addressof(*p1) + sizeof p1; + align(MaxAlign, n1, p2, n2); + void* p3 = static_cast(p2) - 1; + ::new(p3) CharPtr(p1); + return static_cast(p2); + } + + pointer allocate(size_type size, const_void_pointer hint) { + std::size_t n1 = size * sizeof(value_type); + std::size_t n2 = n1 + MaxAlign; + CharPtr h1 = CharPtr(); + if (hint) { + h1 = *(static_cast(hint) - 1); + } + CharAlloc a1(allocator()); +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + CharPtr p1 = CharTraits::allocate(a1, sizeof(p1) + + n2, h1); +#else + CharPtr p1 = a1.allocate(sizeof(p1) + n2, h1); +#endif + void* p2 = detail::addressof(*p1) + sizeof p1; + align(MaxAlign, n1, p2, n2); + void* p3 = static_cast(p2) - 1; + ::new(p3) CharPtr(p1); + return static_cast(p2); + } + + void deallocate(pointer memory, size_type size) { + CharPtr* p1 = reinterpret_cast(memory) - 1; + CharPtr p2 = *p1; + p1->~CharPtr(); + CharAlloc a1(allocator()); + a1.deallocate(p2, size * sizeof(value_type) + + MaxAlign + sizeof p2); + } + }; + + template + inline bool operator==(const aligned_allocator_adaptor& a, const aligned_allocator_adaptor& b) + { + return a.allocator() == b.allocator(); + } + + template + inline bool operator!=(const aligned_allocator_adaptor& a, const aligned_allocator_adaptor& b) + { + return !(a == b); + } + } + + using alignment::aligned_allocator_adaptor; +} + +#endif diff --git a/include/boost/align/detail/address.hpp b/include/boost/align/detail/address.hpp new file mode 100644 index 0000000..b5de84d --- /dev/null +++ b/include/boost/align/detail/address.hpp @@ -0,0 +1,26 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_DETAIL_ADDRESS_HPP +#define BOOST_ALIGN_DETAIL_ADDRESS_HPP + +#include + +namespace boost { + namespace alignment { + namespace detail { +#if defined(BOOST_HAS_INTPTR_T) + typedef boost::uintptr_t address_t; +#else + typedef std::size_t address_t; +#endif + } + } +} + +#endif diff --git a/include/boost/align/detail/addressof.hpp b/include/boost/align/detail/addressof.hpp new file mode 100644 index 0000000..d55d4cf --- /dev/null +++ b/include/boost/align/detail/addressof.hpp @@ -0,0 +1,32 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_DETAIL_ADDRESSOF_HPP +#define BOOST_ALIGN_DETAIL_ADDRESSOF_HPP + +#include + +#if !defined(BOOST_NO_CXX11_ADDRESSOF) +#include +#else +#include +#endif + +namespace boost { + namespace alignment { + namespace detail { +#if !defined(BOOST_NO_CXX11_ADDRESSOF) + using std::addressof; +#else + using boost::addressof; +#endif + } + } +} + +#endif diff --git a/include/boost/align/detail/align.hpp b/include/boost/align/detail/align.hpp new file mode 100644 index 0000000..9fbc65d --- /dev/null +++ b/include/boost/align/detail/align.hpp @@ -0,0 +1,39 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGN_HPP +#define BOOST_ALIGN_DETAIL_ALIGN_HPP + +#include +#include +#include + +namespace boost { + namespace alignment { + namespace detail { + inline void* align(std::size_t alignment, std::size_t size, + void*& ptr, std::size_t& space) + { + BOOST_ASSERT(is_alignment(alignment)); + std::size_t n1 = address_t(ptr) & (alignment - 1); + if (n1 != 0) { + n1 = alignment - n1; + } + void* p1 = 0; + if (n1 <= space && size <= space - n1) { + p1 = static_cast(ptr) + n1; + ptr = p1; + space -= n1; + } + return p1; + } + } + } +} + +#endif diff --git a/include/boost/align/detail/align_cxx11.hpp b/include/boost/align/detail/align_cxx11.hpp new file mode 100644 index 0000000..5be64f6 --- /dev/null +++ b/include/boost/align/detail/align_cxx11.hpp @@ -0,0 +1,22 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGN_CXX11_HPP +#define BOOST_ALIGN_DETAIL_ALIGN_CXX11_HPP + +#include + +namespace boost { + namespace alignment { + namespace detail { + using std::align; + } + } +} + +#endif diff --git a/include/boost/align/detail/aligned_alloc.hpp b/include/boost/align/detail/aligned_alloc.hpp new file mode 100644 index 0000000..a77b375 --- /dev/null +++ b/include/boost/align/detail/aligned_alloc.hpp @@ -0,0 +1,53 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_HPP +#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_HPP + +#include +#include +#include +#include +#include + +namespace boost { + namespace alignment { + namespace detail { + inline void* aligned_alloc(std::size_t alignment, + std::size_t size) + { + BOOST_ASSERT(is_alignment(alignment)); + enum { + VoidAlign = alignment_of::value + }; + if (alignment < VoidAlign) { + alignment = VoidAlign; + } + std::size_t n1 = size + alignment; + void* p1 = 0; + void* p2 = std::malloc(n1 + sizeof p2); + if (p2) { + p1 = static_cast(p2) + sizeof p2; + align(alignment, size, p1, n1); + *(static_cast(p1) - 1) = p2; + } + return p1; + } + + inline void aligned_free(void* ptr) + { + if (ptr) { + void* p1 = *(static_cast(ptr) - 1); + std::free(p1); + } + } + } + } +} + +#endif diff --git a/include/boost/align/detail/aligned_alloc_android.hpp b/include/boost/align/detail/aligned_alloc_android.hpp new file mode 100644 index 0000000..4fae596 --- /dev/null +++ b/include/boost/align/detail/aligned_alloc_android.hpp @@ -0,0 +1,34 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_ANDROID_HPP +#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_ANDROID_HPP + +#include +#include +#include + +namespace boost { + namespace alignment { + namespace detail { + inline void* aligned_alloc(std::size_t alignment, + std::size_t size) + { + BOOST_ASSERT(is_alignment(alignment)); + return memalign(alignment, size); + } + + inline void aligned_free(void* ptr) + { + free(ptr); + } + } + } +} + +#endif diff --git a/include/boost/align/detail/aligned_alloc_msvc.hpp b/include/boost/align/detail/aligned_alloc_msvc.hpp new file mode 100644 index 0000000..dac37ff --- /dev/null +++ b/include/boost/align/detail/aligned_alloc_msvc.hpp @@ -0,0 +1,34 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_MSVC_HPP +#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_MSVC_HPP + +#include +#include +#include + +namespace boost { + namespace alignment { + namespace detail { + inline void* aligned_alloc(std::size_t alignment, + std::size_t size) + { + BOOST_ASSERT(is_alignment(alignment)); + return _aligned_malloc(size, alignment); + } + + inline void aligned_free(void* ptr) + { + _aligned_free(ptr); + } + } + } +} + +#endif diff --git a/include/boost/align/detail/aligned_alloc_posix.hpp b/include/boost/align/detail/aligned_alloc_posix.hpp new file mode 100644 index 0000000..a252e8d --- /dev/null +++ b/include/boost/align/detail/aligned_alloc_posix.hpp @@ -0,0 +1,44 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_POSIX_HPP +#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_POSIX_HPP + +#include +#include +#include + +namespace boost { + namespace alignment { + namespace detail { + inline void* aligned_alloc(std::size_t alignment, + std::size_t size) + { + BOOST_ASSERT(is_alignment(alignment)); + enum { + VoidSize = sizeof(void*) + }; + if (alignment < VoidSize) { + alignment = VoidSize; + } + void* p1; + if (posix_memalign(&p1, alignment, size) != 0) { + p1 = 0; + } + return p1; + } + + inline void aligned_free(void* ptr) + { + free(ptr); + } + } + } +} + +#endif diff --git a/include/boost/align/detail/aligned_alloc_sunos.hpp b/include/boost/align/detail/aligned_alloc_sunos.hpp new file mode 100644 index 0000000..bc2827c --- /dev/null +++ b/include/boost/align/detail/aligned_alloc_sunos.hpp @@ -0,0 +1,34 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_SUNOS_HPP +#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_SUNOS_HPP + +#include +#include +#include + +namespace boost { + namespace alignment { + namespace detail { + inline void* aligned_alloc(std::size_t alignment, + std::size_t size) + { + BOOST_ASSERT(is_alignment(alignment)); + return memalign(alignment, size); + } + + inline void aligned_free(void* ptr) + { + free(ptr); + } + } + } +} + +#endif diff --git a/include/boost/align/detail/alignment_of.hpp b/include/boost/align/detail/alignment_of.hpp new file mode 100644 index 0000000..f4acc21 --- /dev/null +++ b/include/boost/align/detail/alignment_of.hpp @@ -0,0 +1,32 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGNMENT_OF_HPP +#define BOOST_ALIGN_DETAIL_ALIGNMENT_OF_HPP + +#include + +#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) +#include +#else +#include +#endif + +namespace boost { + namespace alignment { + namespace detail { +#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) + using std::alignment_of; +#else + using boost::alignment_of; +#endif + } + } +} + +#endif diff --git a/include/boost/align/detail/is_aligned.hpp b/include/boost/align/detail/is_aligned.hpp new file mode 100644 index 0000000..8310311 --- /dev/null +++ b/include/boost/align/detail/is_aligned.hpp @@ -0,0 +1,29 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_DETAIL_IS_ALIGNED_HPP +#define BOOST_ALIGN_DETAIL_IS_ALIGNED_HPP + +#include +#include +#include + +namespace boost { + namespace alignment { + namespace detail { + inline bool is_aligned(std::size_t alignment, + const void* ptr) + { + BOOST_ASSERT(is_alignment(alignment)); + return (address_t(ptr) & (alignment - 1)) == 0; + } + } + } +} + +#endif diff --git a/include/boost/align/detail/is_alignment.hpp b/include/boost/align/detail/is_alignment.hpp new file mode 100644 index 0000000..203592e --- /dev/null +++ b/include/boost/align/detail/is_alignment.hpp @@ -0,0 +1,25 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_DETAIL_IS_ALIGNMENT_HPP +#define BOOST_ALIGN_DETAIL_IS_ALIGNMENT_HPP + +#include + +namespace boost { + namespace alignment { + namespace detail { + inline bool is_alignment(std::size_t value) + { + return (value > 0) && ((value & (value - 1)) == 0); + } + } + } +} + +#endif diff --git a/include/boost/align/detail/is_power_of_2.hpp b/include/boost/align/detail/is_power_of_2.hpp new file mode 100644 index 0000000..dfacbd5 --- /dev/null +++ b/include/boost/align/detail/is_power_of_2.hpp @@ -0,0 +1,27 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_DETAIL_IS_POWER_OF_2_HPP +#define BOOST_ALIGN_DETAIL_IS_POWER_OF_2_HPP + +#include + +namespace boost { + namespace alignment { + namespace detail { + template + struct is_power_of_2 { + enum { + value = (N > 0) && ((N & (N - 1)) == 0) + }; + }; + } + } +} + +#endif diff --git a/include/boost/align/detail/max_count_of.hpp b/include/boost/align/detail/max_count_of.hpp new file mode 100644 index 0000000..0b418b0 --- /dev/null +++ b/include/boost/align/detail/max_count_of.hpp @@ -0,0 +1,27 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_DETAIL_MAX_COUNT_OF_HPP +#define BOOST_ALIGN_DETAIL_MAX_COUNT_OF_HPP + +#include + +namespace boost { + namespace alignment { + namespace detail { + template + struct max_count_of { + enum { + value = static_cast(-1) / sizeof(T) + }; + }; + } + } +} + +#endif diff --git a/include/boost/align/detail/max_size.hpp b/include/boost/align/detail/max_size.hpp new file mode 100644 index 0000000..06248d3 --- /dev/null +++ b/include/boost/align/detail/max_size.hpp @@ -0,0 +1,27 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_DETAIL_MAX_SIZE_HPP +#define BOOST_ALIGN_DETAIL_MAX_SIZE_HPP + +#include + +namespace boost { + namespace alignment { + namespace detail { + template + struct max_size { + enum { + value = (A > B) ? A : B + }; + }; + } + } +} + +#endif diff --git a/include/boost/align/is_aligned.hpp b/include/boost/align/is_aligned.hpp new file mode 100644 index 0000000..d8e5e18 --- /dev/null +++ b/include/boost/align/is_aligned.hpp @@ -0,0 +1,22 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_ALIGN_IS_ALIGNED_HPP +#define BOOST_ALIGN_IS_ALIGNED_HPP + +#include + +namespace boost { + namespace alignment { + using detail::is_aligned; + } + + using alignment::is_aligned; +} + +#endif diff --git a/index.html b/index.html new file mode 100644 index 0000000..4bce176 --- /dev/null +++ b/index.html @@ -0,0 +1,31 @@ + + + + +Boost.Align + + + + + +

Automatic redirection failed, please go to + doc/html/index.html

+

© 2014 Glen Fernandes

+ + diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 new file mode 100644 index 0000000..c0894f8 --- /dev/null +++ b/test/Jamfile.v2 @@ -0,0 +1,14 @@ +# Copyright (c) 2014 Glen Joseph Fernandes +# glenfe at live dot com +# +# Distributed under the Boost Software License, +# Version 1.0. (See accompanying file LICENSE_1_0.txt +# or copy at http://boost.org/LICENSE_1_0.txt) + +import testing ; + +run align_test.cpp ; +run aligned_alloc_test.cpp ; +run aligned_allocator_test.cpp ; +run aligned_allocator_adaptor_test.cpp ; +run is_aligned_test.cpp ; diff --git a/test/align_test.cpp b/test/align_test.cpp new file mode 100644 index 0000000..47650f9 --- /dev/null +++ b/test/align_test.cpp @@ -0,0 +1,91 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#include +#include +#include +#include + +#if !defined(BOOST_NO_ALIGNMENT) + +void test(std::size_t alignment, char* buffer) +{ + { + std::size_t n = alignment; + void* p = buffer; + void* q = boost::align(alignment, 0, p, n); + BOOST_TEST(q == p); + BOOST_TEST(q == buffer); + BOOST_TEST(boost::is_aligned(alignment, q)); + BOOST_TEST(n == alignment); + } + { + std::size_t n = alignment - 1; + void* p = &buffer[1]; + void* q = boost::align(alignment, 1, p, n); + BOOST_TEST(q == 0); + BOOST_TEST(p == &buffer[1]); + BOOST_TEST(n == alignment - 1); + } + { + std::size_t n = alignment; + void* p = &buffer[1]; + void* q = boost::align(alignment, 0, p, n); + BOOST_TEST(q == p); + BOOST_TEST(q == &buffer[alignment]); + BOOST_TEST(boost::is_aligned(alignment, q)); + BOOST_TEST(n == 1); + } +} + +int main() +{ + { + BOOST_ALIGNMENT(1) char s[2]; + test(1, s); + } + { + BOOST_ALIGNMENT(2) char s[3]; + test(2, s); + } + { + BOOST_ALIGNMENT(4) char s[5]; + test(4, s); + } + { + BOOST_ALIGNMENT(8) char s[9]; + test(8, s); + } + { + BOOST_ALIGNMENT(16) char s[17]; + test(16, s); + } + { + BOOST_ALIGNMENT(32) char s[33]; + test(32, s); + } + { + BOOST_ALIGNMENT(64) char s[65]; + test(64, s); + } + { + BOOST_ALIGNMENT(128) char s[129]; + test(128, s); + } + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} + +#endif diff --git a/test/aligned_alloc_test.cpp b/test/aligned_alloc_test.cpp new file mode 100644 index 0000000..c774efd --- /dev/null +++ b/test/aligned_alloc_test.cpp @@ -0,0 +1,57 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#include +#include +#include +#include + +void test(std::size_t alignment) +{ + { + void* p = boost::aligned_alloc(alignment, alignment); + BOOST_TEST(p != 0); + BOOST_TEST(boost::is_aligned(alignment, p)); + std::memset(p, 0, 1); + boost::aligned_free(p); + } + { + void* p = boost::aligned_alloc(alignment, alignment + 1); + BOOST_TEST(p != 0); + BOOST_TEST(boost::is_aligned(alignment, p)); + std::memset(p, 0, 1); + boost::aligned_free(p); + } + if (alignment > 1) { + void* p = boost::aligned_alloc(alignment, alignment - 1); + BOOST_TEST(p != 0); + BOOST_TEST(boost::is_aligned(alignment, p)); + std::memset(p, 0, 1); + boost::aligned_free(p); + } + { + void* p = boost::aligned_alloc(alignment, 0); + boost::aligned_free(p); + } + { + enum { + n = static_cast(-1) + }; + void* p = boost::aligned_alloc(alignment, n); + BOOST_TEST(p == 0); + } +} + +int main() +{ + for (std::size_t i = 1; i <= 128; i <<= 1) { + test(i); + } + + return boost::report_errors(); +} diff --git a/test/aligned_allocator_adaptor_test.cpp b/test/aligned_allocator_adaptor_test.cpp new file mode 100644 index 0000000..2952ed4 --- /dev/null +++ b/test/aligned_allocator_adaptor_test.cpp @@ -0,0 +1,104 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#include +#include +#include +#include + +template +struct adaptor { + typedef boost::aligned_allocator_adaptor, + Alignment> type; +}; + +template +void test_allocate() +{ + { + typename adaptor::type a; + int* p = a.allocate(1); + BOOST_TEST(p != 0); + BOOST_TEST(boost::is_aligned(Alignment, p)); + std::memset(p, 0, 1); + a.deallocate(p, 1); + } + { + typename adaptor::type a; + int* p1 = a.allocate(1); + int* p2 = a.allocate(1, p1); + BOOST_TEST(p2 != 0); + BOOST_TEST(boost::is_aligned(Alignment, p2)); + std::memset(p2, 0, 1); + a.deallocate(p2, 1); + a.deallocate(p1, 1); + } + { + typename adaptor::type a; + int* p = a.allocate(0); + a.deallocate(p, 0); + } +} + +template +void test_construct() +{ + typename adaptor::type a; + int* p = a.allocate(1); + a.construct(p, 1); + BOOST_TEST(*p == 1); + a.destroy(p); + a.deallocate(p, 1); +} + +template +void test_constructor() +{ + { + typename adaptor::type a1; + typename adaptor::type a2(a1); + BOOST_TEST(a2 == a1); + } + { + std::allocator a1; + typename adaptor::type a2(a1); + BOOST_TEST(a2.allocator() == a1); + } +} + +template +void test_rebind() +{ + typedef typename adaptor::type allocator; + allocator a1; + typename allocator::template rebind::other a2(a1); + BOOST_TEST(a2 == a1); +} + +template +void test() +{ + test_allocate(); + test_construct(); + test_constructor(); + test_rebind(); +} + +int main() +{ + test<1>(); + test<2>(); + test<4>(); + test<8>(); + test<16>(); + test<32>(); + test<64>(); + test<128>(); + + return boost::report_errors(); +} diff --git a/test/aligned_allocator_test.cpp b/test/aligned_allocator_test.cpp new file mode 100644 index 0000000..4586e02 --- /dev/null +++ b/test/aligned_allocator_test.cpp @@ -0,0 +1,81 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#include +#include +#include +#include + +template +void test_allocate() +{ + { + boost::aligned_allocator a; + int* p = a.allocate(1); + BOOST_TEST(p != 0); + BOOST_TEST(boost::is_aligned(Alignment, p)); + std::memset(p, 0, 1); + a.deallocate(p, 1); + } + { + boost::aligned_allocator a; + int* p = a.allocate(0); + a.deallocate(p, 0); + } +} + +template +void test_construct() +{ + boost::aligned_allocator a; + int* p = a.allocate(1); + a.construct(p, 1); + BOOST_TEST(*p == 1); + a.destroy(p); + a.deallocate(p, 1); +} + +template +void test_constructor() +{ + boost::aligned_allocator a1; + boost::aligned_allocator a2(a1); + BOOST_TEST(a2 == a1); +} + +template +void test_rebind() +{ + typedef boost::aligned_allocator allocator; + allocator a1; + typename allocator::template rebind::other a2(a1); + BOOST_TEST(a2 == a1); +} + +template +void test() +{ + test_allocate(); + test_construct(); + test_constructor(); + test_rebind(); +} + +int main() +{ + test<1>(); + test<2>(); + test<4>(); + test<8>(); + test<16>(); + test<32>(); + test<64>(); + test<128>(); + + return boost::report_errors(); +} diff --git a/test/is_aligned_test.cpp b/test/is_aligned_test.cpp new file mode 100644 index 0000000..5fcb644 --- /dev/null +++ b/test/is_aligned_test.cpp @@ -0,0 +1,67 @@ +/* + Copyright (c) 2014 Glen Joseph Fernandes + glenfe at live dot com + + Distributed under the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt) +*/ +#include +#include +#include + +#if !defined(BOOST_NO_ALIGNMENT) + +int main() +{ + { + BOOST_ALIGNMENT(1) char s[1]; + BOOST_TEST(boost::is_aligned(1, &s[0])); + } + { + BOOST_ALIGNMENT(2) char s[2]; + BOOST_TEST(boost::is_aligned(2, &s[0])); + BOOST_TEST(!boost::is_aligned(2, &s[1])); + } + { + BOOST_ALIGNMENT(4) char s[4]; + BOOST_TEST(boost::is_aligned(4, &s[0])); + BOOST_TEST(!boost::is_aligned(4, &s[1])); + } + { + BOOST_ALIGNMENT(8) char s[8]; + BOOST_TEST(boost::is_aligned(8, &s[0])); + BOOST_TEST(!boost::is_aligned(8, &s[1])); + } + { + BOOST_ALIGNMENT(16) char s[16]; + BOOST_TEST(boost::is_aligned(16, &s[0])); + BOOST_TEST(!boost::is_aligned(16, &s[1])); + } + { + BOOST_ALIGNMENT(32) char s[32]; + BOOST_TEST(boost::is_aligned(32, &s[0])); + BOOST_TEST(!boost::is_aligned(32, &s[1])); + } + { + BOOST_ALIGNMENT(64) char s[64]; + BOOST_TEST(boost::is_aligned(64, &s[0])); + BOOST_TEST(!boost::is_aligned(64, &s[1])); + } + { + BOOST_ALIGNMENT(128) char s[128]; + BOOST_TEST(boost::is_aligned(128, &s[0])); + BOOST_TEST(!boost::is_aligned(128, &s[1])); + } + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} + +#endif