1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // |
3 | // (C) Copyright Ion Gaztanaga 2007-2013 |
4 | // |
5 | // Distributed under the Boost Software License, Version 1.0. |
6 | // (See accompanying file LICENSE_1_0.txt or copy at |
7 | // http://www.boost.org/LICENSE_1_0.txt) |
8 | // |
9 | // See http://www.boost.org/libs/intrusive for documentation. |
10 | // |
11 | ///////////////////////////////////////////////////////////////////////////// |
12 | |
13 | #ifndef BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP |
14 | #define BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP |
15 | |
16 | #include <boost/intrusive/detail/config_begin.hpp> |
17 | #include <boost/intrusive/intrusive_fwd.hpp> |
18 | #include <boost/intrusive/detail/mpl.hpp> //ls_zeros |
19 | #include <boost/intrusive/detail/assert.hpp> //BOOST_INTRUSIVE_INVARIANT_ASSERT |
20 | |
21 | #if defined(BOOST_HAS_PRAGMA_ONCE) |
22 | # pragma once |
23 | #endif |
24 | |
25 | namespace boost { |
26 | namespace intrusive { |
27 | |
28 | //!This trait class is used to know if a pointer |
29 | //!can embed extra bits of information if |
30 | //!it's going to be used to point to objects |
31 | //!with an alignment of "Alignment" bytes. |
32 | template<class VoidPointer, std::size_t Alignment> |
33 | struct max_pointer_plus_bits |
34 | { |
35 | static const std::size_t value = 0; |
36 | }; |
37 | |
38 | //!This is a specialization for raw pointers. |
39 | //!Raw pointers can embed extra bits in the lower bits |
40 | //!if the alignment is multiple of 2pow(NumBits). |
41 | template<std::size_t Alignment> |
42 | struct max_pointer_plus_bits<void*, Alignment> |
43 | { |
44 | static const std::size_t value = detail::ls_zeros<Alignment>::value; |
45 | }; |
46 | |
47 | //!This is class that is supposed to have static methods |
48 | //!to embed extra bits of information in a pointer. |
49 | //!This is a declaration and there is no default implementation, |
50 | //!because operations to embed the bits change with every pointer type. |
51 | //! |
52 | //!An implementation that detects that a pointer type whose |
53 | //!has_pointer_plus_bits<>::value is non-zero can make use of these |
54 | //!operations to embed the bits in the pointer. |
55 | template<class Pointer, std::size_t NumBits> |
56 | struct pointer_plus_bits |
57 | #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED |
58 | {} |
59 | #endif |
60 | ; |
61 | |
62 | //!This is the specialization to embed extra bits of information |
63 | //!in a raw pointer. The extra bits are stored in the lower bits of the pointer. |
64 | template<class T, std::size_t NumBits> |
65 | struct pointer_plus_bits<T*, NumBits> |
66 | { |
67 | static const uintptr_t Mask = uintptr_t((uintptr_t(1u) << NumBits) - 1); |
68 | typedef T* pointer; |
69 | |
70 | static pointer get_pointer(pointer n) |
71 | { return pointer(uintptr_t(n) & uintptr_t(~Mask)); } |
72 | |
73 | static void set_pointer(pointer &n, pointer p) |
74 | { |
75 | BOOST_INTRUSIVE_INVARIANT_ASSERT(0 == (uintptr_t(p) & Mask)); |
76 | n = pointer(uintptr_t(p) | (uintptr_t(n) & Mask)); |
77 | } |
78 | |
79 | static std::size_t get_bits(pointer n) |
80 | { return std::size_t(uintptr_t(n) & Mask); } |
81 | |
82 | static void set_bits(pointer &n, std::size_t c) |
83 | { |
84 | BOOST_INTRUSIVE_INVARIANT_ASSERT(uintptr_t(c) <= Mask); |
85 | n = pointer(uintptr_t((get_pointer)(n)) | uintptr_t(c)); |
86 | } |
87 | }; |
88 | |
89 | } //namespace intrusive |
90 | } //namespace boost |
91 | |
92 | #include <boost/intrusive/detail/config_end.hpp> |
93 | |
94 | #endif //BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP |
95 | |