]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // | |
3 | // (C) Copyright Ion Gaztanaga 2005-2015. | |
4 | // (C) Copyright Gennaro Prota 2003 - 2004. | |
5 | // | |
6 | // Distributed under the Boost Software License, Version 1.0. | |
7 | // (See accompanying file LICENSE_1_0.txt or copy at | |
8 | // http://www.boost.org/LICENSE_1_0.txt) | |
9 | // | |
10 | // See http://www.boost.org/libs/interprocess for documentation. | |
11 | // | |
12 | ////////////////////////////////////////////////////////////////////////////// | |
13 | ||
14 | #ifndef BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP | |
15 | #define BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP | |
16 | ||
17 | #ifndef BOOST_CONFIG_HPP | |
18 | # include <boost/config.hpp> | |
19 | #endif | |
20 | # | |
21 | #if defined(BOOST_HAS_PRAGMA_ONCE) | |
22 | # pragma once | |
23 | #endif | |
24 | ||
25 | #include <boost/interprocess/detail/config_begin.hpp> | |
26 | #include <boost/interprocess/detail/workaround.hpp> | |
27 | ||
28 | #include <boost/interprocess/interprocess_fwd.hpp> | |
29 | #include <boost/move/utility_core.hpp> | |
30 | #include <boost/interprocess/detail/min_max.hpp> | |
31 | #include <boost/interprocess/detail/type_traits.hpp> | |
32 | #include <boost/interprocess/detail/mpl.hpp> | |
33 | #include <boost/intrusive/pointer_traits.hpp> | |
34 | #include <boost/move/utility_core.hpp> | |
35 | #include <boost/static_assert.hpp> | |
36 | #include <boost/cstdint.hpp> | |
37 | #include <climits> | |
38 | ||
39 | namespace boost { | |
40 | namespace interprocess { | |
41 | namespace ipcdetail { | |
42 | ||
43 | template <class T> | |
44 | inline T* to_raw_pointer(T* p) | |
45 | { return p; } | |
46 | ||
47 | template <class Pointer> | |
48 | inline typename boost::intrusive::pointer_traits<Pointer>::element_type* | |
49 | to_raw_pointer(const Pointer &p) | |
50 | { return boost::interprocess::ipcdetail::to_raw_pointer(p.operator->()); } | |
51 | ||
52 | //Rounds "orig_size" by excess to round_to bytes | |
53 | template<class SizeType> | |
54 | inline SizeType get_rounded_size(SizeType orig_size, SizeType round_to) | |
55 | { | |
56 | return ((orig_size-1)/round_to+1)*round_to; | |
57 | } | |
58 | ||
59 | //Truncates "orig_size" to a multiple of "multiple" bytes. | |
60 | template<class SizeType> | |
61 | inline SizeType get_truncated_size(SizeType orig_size, SizeType multiple) | |
62 | { | |
63 | return orig_size/multiple*multiple; | |
64 | } | |
65 | ||
66 | //Rounds "orig_size" by excess to round_to bytes. round_to must be power of two | |
67 | template<class SizeType> | |
68 | inline SizeType get_rounded_size_po2(SizeType orig_size, SizeType round_to) | |
69 | { | |
70 | return ((orig_size-1)&(~(round_to-1))) + round_to; | |
71 | } | |
72 | ||
73 | //Truncates "orig_size" to a multiple of "multiple" bytes. multiple must be power of two | |
74 | template<class SizeType> | |
75 | inline SizeType get_truncated_size_po2(SizeType orig_size, SizeType multiple) | |
76 | { | |
77 | return (orig_size & (~(multiple-1))); | |
78 | } | |
79 | ||
80 | template <std::size_t OrigSize, std::size_t RoundTo> | |
81 | struct ct_rounded_size | |
82 | { | |
83 | BOOST_STATIC_ASSERT((RoundTo != 0)); | |
84 | static const std::size_t intermediate_value = (OrigSize-1)/RoundTo+1; | |
85 | BOOST_STATIC_ASSERT(intermediate_value <= std::size_t(-1)/RoundTo); | |
86 | static const std::size_t value = intermediate_value*RoundTo; | |
87 | }; | |
88 | ||
89 | // Gennaro Prota wrote this. Thanks! | |
90 | template <int p, int n = 4> | |
91 | struct ct_max_pow2_less | |
92 | { | |
93 | static const std::size_t c = 2*n < p; | |
94 | ||
95 | static const std::size_t value = | |
96 | c ? (ct_max_pow2_less< c*p, 2*c*n>::value) : n; | |
97 | }; | |
98 | ||
99 | template <> | |
100 | struct ct_max_pow2_less<0, 0> | |
101 | { | |
102 | static const std::size_t value = 0; | |
103 | }; | |
104 | ||
105 | } //namespace ipcdetail { | |
106 | ||
107 | //!Trait class to detect if an index is a node | |
108 | //!index. This allows more efficient operations | |
109 | //!when deallocating named objects. | |
110 | template <class Index> | |
111 | struct is_node_index | |
112 | { | |
113 | static const bool value = false; | |
114 | }; | |
115 | ||
116 | //!Trait class to detect if an index is an intrusive | |
117 | //!index. This will embed the derivation hook in each | |
118 | //!allocation header, to provide memory for the intrusive | |
119 | //!container. | |
120 | template <class Index> | |
121 | struct is_intrusive_index | |
122 | { | |
123 | static const bool value = false; | |
124 | }; | |
125 | ||
126 | template <typename T> | |
127 | BOOST_INTERPROCESS_FORCEINLINE T* addressof(T& v) | |
128 | { | |
129 | return reinterpret_cast<T*>( | |
130 | &const_cast<char&>(reinterpret_cast<const volatile char &>(v))); | |
131 | } | |
132 | ||
133 | template<class SizeType> | |
134 | struct sqrt_size_type_max | |
135 | { | |
136 | static const SizeType value = (SizeType(1) << (sizeof(SizeType)*(CHAR_BIT/2)))-1; | |
137 | }; | |
138 | ||
139 | template<class SizeType> | |
140 | inline bool multiplication_overflows(SizeType a, SizeType b) | |
141 | { | |
142 | const SizeType sqrt_size_max = sqrt_size_type_max<SizeType>::value; | |
143 | return //Fast runtime check | |
144 | ( (a | b) > sqrt_size_max && | |
145 | //Slow division check | |
146 | b && a > SizeType(-1)/b | |
147 | ); | |
148 | } | |
149 | ||
150 | template<std::size_t SztSizeOfType, class SizeType> | |
151 | BOOST_INTERPROCESS_FORCEINLINE bool size_overflows(SizeType count) | |
152 | { | |
153 | //Compile time-check | |
154 | BOOST_STATIC_ASSERT(SztSizeOfType <= SizeType(-1)); | |
155 | //Runtime check | |
156 | return multiplication_overflows(SizeType(SztSizeOfType), count); | |
157 | } | |
158 | ||
159 | template<class RawPointer> | |
160 | class pointer_uintptr_caster; | |
161 | ||
162 | template<class T> | |
163 | class pointer_uintptr_caster<T*> | |
164 | { | |
165 | public: | |
166 | BOOST_INTERPROCESS_FORCEINLINE explicit pointer_uintptr_caster(uintptr_t sz) | |
167 | : m_uintptr(sz) | |
168 | {} | |
169 | ||
170 | BOOST_INTERPROCESS_FORCEINLINE explicit pointer_uintptr_caster(const volatile T *p) | |
171 | : m_uintptr(reinterpret_cast<uintptr_t>(p)) | |
172 | {} | |
173 | ||
174 | BOOST_INTERPROCESS_FORCEINLINE uintptr_t uintptr() const | |
175 | { return m_uintptr; } | |
176 | ||
177 | BOOST_INTERPROCESS_FORCEINLINE T* pointer() const | |
178 | { return reinterpret_cast<T*>(m_uintptr); } | |
179 | ||
180 | private: | |
181 | uintptr_t m_uintptr; | |
182 | }; | |
183 | ||
184 | ||
185 | template<class SizeType> | |
186 | inline bool sum_overflows(SizeType a, SizeType b) | |
187 | { return SizeType(-1) - a < b; } | |
188 | ||
189 | //Anti-exception node eraser | |
190 | template<class Cont> | |
191 | class value_eraser | |
192 | { | |
193 | public: | |
194 | value_eraser(Cont & cont, typename Cont::iterator it) | |
195 | : m_cont(cont), m_index_it(it), m_erase(true){} | |
196 | ~value_eraser() | |
197 | { if(m_erase) m_cont.erase(m_index_it); } | |
198 | ||
199 | BOOST_INTERPROCESS_FORCEINLINE void release() { m_erase = false; } | |
200 | ||
201 | private: | |
202 | Cont &m_cont; | |
203 | typename Cont::iterator m_index_it; | |
204 | bool m_erase; | |
205 | }; | |
206 | ||
207 | } //namespace interprocess { | |
208 | } //namespace boost { | |
209 | ||
210 | #include <boost/interprocess/detail/config_end.hpp> | |
211 | ||
212 | #endif //#ifndef BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP | |
213 |