]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | [/ |
2 | Copyright Oliver Kowalke 2009-2013. | |
3 | Distributed under the Boost Software License, Version 1.0. | |
4 | (See accompanying file LICENSE_1_0.txt or copy at | |
5 | http://www.boost.org/LICENSE_1_0.txt | |
6 | ] | |
7 | ||
8 | [#stack] | |
9 | [section:stack Stack allocation] | |
10 | ||
11 | A __fiber__ uses internally an __econtext__ which manages a set of registers and a stack. | |
12 | The memory used by the stack is allocated/deallocated via a __stack_allocator__ | |
13 | which is required to model a __stack_allocator_concept__. | |
14 | ||
15 | A __stack_allocator__ can be passed to [link fiber_fiber `fiber::fiber()`] or | |
16 | to [ns_function_link fibers..async]. | |
17 | ||
18 | [#stack_allocator_concept] | |
19 | [heading stack-allocator concept] | |
20 | A __stack_allocator__ must satisfy the ['stack-allocator concept] requirements | |
21 | shown in the following table, in which `a` is an object of a | |
22 | __stack_allocator__ type, `sctx` is a __stack_context__, and `size` is a `std::size_t`: | |
23 | ||
24 | [table | |
25 | [[expression][return type][notes]] | |
26 | [ | |
27 | [`a(size)`] | |
28 | [] | |
29 | [creates a stack allocator] | |
30 | ] | |
31 | [ | |
32 | [`a.allocate()`] | |
33 | [__stack_context__] | |
34 | [creates a stack] | |
35 | ] | |
36 | [ | |
37 | [`a.deallocate( sctx)`] | |
38 | [`void`] | |
39 | [deallocates the stack created by `a.allocate()`] | |
40 | ] | |
41 | ] | |
42 | ||
43 | [important The implementation of `allocate()` might include logic to protect | |
44 | against exceeding the context's available stack size rather than leaving it as | |
45 | undefined behaviour.] | |
46 | ||
47 | [important Calling `deallocate()` with a __stack_context__ not obtained from | |
48 | `allocate()` results in undefined behaviour.] | |
49 | ||
50 | [note The memory for the stack is not required to be aligned; alignment takes | |
51 | place inside __econtext__.] | |
52 | ||
53 | See also [@http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack.html Boost.Context stack allocation]. | |
54 | In particular, `traits_type` methods are as described for | |
55 | [@http://www.boost.org/doc/libs/release/libs/context/doc/html/context/stack/stack_traits.html | |
56 | `boost::context::stack_traits`]. | |
57 | ||
58 | [class_heading protected_fixedsize_stack] | |
59 | ||
60 | __boost_fiber__ provides the class __pfixedsize_stack__ which models | |
61 | the __stack_allocator_concept__. | |
62 | It appends a guard page at the end of each stack to protect against exceeding | |
63 | the stack. If the guard page is accessed (read or write operation) a | |
64 | segmentation fault/access violation is generated by the operating system. | |
65 | ||
66 | [important Using __pfixedsize_stack__ is expensive. Launching a new fiber with | |
67 | a stack of this type incurs the overhead of setting the memory protection; | |
68 | once allocated, this stack is just as efficient to use as __fixedsize_stack__.] | |
69 | ||
70 | [note The appended `guard page` is [*not] mapped to physical memory, only | |
71 | virtual addresses are used.] | |
72 | ||
73 | #include <boost/fiber/protected_fixedsize.hpp> | |
74 | ||
75 | namespace boost { | |
76 | namespace fibers { | |
77 | ||
78 | struct protected_fixedsize { | |
79 | protected_fixesize(std::size_t size = traits_type::default_size()); | |
80 | ||
81 | stack_context allocate(); | |
82 | ||
83 | void deallocate( stack_context &); | |
84 | } | |
85 | ||
86 | }} | |
87 | ||
88 | [member_heading protected_fixedsize..allocate] | |
89 | ||
90 | stack_context allocate(); | |
91 | ||
92 | [variablelist | |
93 | [[Preconditions:] [`traits_type::minimum_size() <= size` and | |
94 | `traits_type::is_unbounded() || ( size <= traits_type::maximum_size() )`.]] | |
95 | [[Effects:] [Allocates memory of at least `size` bytes and stores a pointer | |
96 | to the stack and its actual size in `sctx`. Depending | |
97 | on the architecture (the stack grows downwards/upwards) the stored address is | |
98 | the highest/lowest address of the stack.]] | |
99 | ] | |
100 | ||
101 | [member_heading protected_fixesize..deallocate] | |
102 | ||
103 | void deallocate( stack_context & sctx); | |
104 | ||
105 | [variablelist | |
106 | [[Preconditions:] [`sctx.sp` is valid, `traits_type::minimum_size() <= sctx.size` and | |
107 | `traits_type::is_unbounded() || ( sctx.size <= traits_type::maximum_size() )`.]] | |
108 | [[Effects:] [Deallocates the stack space.]] | |
109 | ] | |
110 | ||
111 | ||
112 | [class_heading pooled_fixedsize_stack] | |
113 | ||
114 | __boost_fiber__ provides the class __ofixedsize_stack__ which models | |
115 | the __stack_allocator_concept__. | |
116 | In contrast to __pfixedsize_stack__ it does not append a guard page at the | |
117 | end of each stack. The memory is managed internally by | |
118 | [@http://www.boost.org/doc/libs/release/libs/pool/doc/html/boost/pool.html `boost::pool<>`]. | |
119 | ||
120 | #include <boost/fiber/pooled_fixedsize_stack.hpp> | |
121 | ||
122 | namespace boost { | |
123 | namespace fibers { | |
124 | ||
125 | struct pooled_fixedsize_stack { | |
126 | pooled_fixedsize_stack(std::size_t stack_size = traits_type::default_size(), std::size_t next_size = 32, std::size_t max_size = 0); | |
127 | ||
128 | stack_context allocate(); | |
129 | ||
130 | void deallocate( stack_context &); | |
131 | } | |
132 | ||
133 | }} | |
134 | ||
135 | [hding pooled_fixedsize..Constructor] | |
136 | ||
137 | pooled_fixedsize_stack(std::size_t stack_size, std::size_t next_size, std::size_t max_size); | |
138 | ||
139 | [variablelist | |
140 | [[Preconditions:] [`traits_type::is_unbounded() || ( traits_type::maximum_size() >= stack_size)` | |
141 | and `0 < next_size`.]] | |
142 | [[Effects:] [Allocates memory of at least `stack_size` bytes and stores a pointer to | |
143 | the stack and its actual size in `sctx`. Depending on the architecture (the | |
144 | stack grows downwards/upwards) the stored address is the highest/lowest | |
145 | address of the stack. Argument `next_size` determines the number of stacks to | |
146 | request from the system the first time that `*this` needs to allocate system | |
147 | memory. The third argument `max_size` controls how much memory might be | |
148 | allocated for stacks [mdash] a value of zero means no upper limit.]] | |
149 | ] | |
150 | ||
151 | [member_heading pooled_fixedsize..allocate] | |
152 | ||
153 | stack_context allocate(); | |
154 | ||
155 | [variablelist | |
156 | [[Preconditions:] [`traits_type::is_unbounded() || ( traits_type::maximum_size() >= stack_size)`.]] | |
157 | [[Effects:] [Allocates memory of at least `stack_size` bytes and stores a pointer to | |
158 | the stack and its actual size in `sctx`. Depending on the architecture (the | |
159 | stack grows downwards/upwards) the stored address is the highest/lowest | |
160 | address of the stack.]] | |
161 | ] | |
162 | ||
163 | [member_heading pooled_fixesize..deallocate] | |
164 | ||
165 | void deallocate( stack_context & sctx); | |
166 | ||
167 | [variablelist | |
168 | [[Preconditions:] [`sctx.sp` is valid, | |
169 | `traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size)`.]] | |
170 | [[Effects:] [Deallocates the stack space.]] | |
171 | ] | |
172 | ||
173 | [note This stack allocator is not thread safe.] | |
174 | ||
175 | ||
176 | [class_heading fixedsize_stack] | |
177 | ||
178 | __boost_fiber__ provides the class __fixedsize_stack__ which models | |
179 | the __stack_allocator_concept__. | |
180 | In contrast to __pfixedsize_stack__ it does not append a guard page at the | |
181 | end of each stack. The memory is simply managed by `std::malloc()` and | |
182 | `std::free()`. | |
183 | ||
184 | #include <boost/context/fixedsize_stack.hpp> | |
185 | ||
186 | namespace boost { | |
187 | namespace fibers { | |
188 | ||
189 | struct fixedsize_stack { | |
190 | fixedsize_stack(std::size_t size = traits_type::default_size()); | |
191 | ||
192 | stack_context allocate(); | |
193 | ||
194 | void deallocate( stack_context &); | |
195 | } | |
196 | ||
197 | }} | |
198 | ||
199 | [member_heading fixedsize..allocate] | |
200 | ||
201 | stack_context allocate(); | |
202 | ||
203 | [variablelist | |
204 | [[Preconditions:] [`traits_type::minimum_size() <= size` and | |
205 | `traits_type::is_unbounded() || ( traits_type::maximum_size() >= size)`.]] | |
206 | [[Effects:] [Allocates memory of at least `size` bytes and stores a pointer to | |
207 | the stack and its actual size in `sctx`. Depending on the architecture (the | |
208 | stack grows downwards/upwards) the stored address is the highest/lowest | |
209 | address of the stack.]] | |
210 | ] | |
211 | ||
212 | [member_heading fixesize..deallocate] | |
213 | ||
214 | void deallocate( stack_context & sctx); | |
215 | ||
216 | [variablelist | |
217 | [[Preconditions:] [`sctx.sp` is valid, `traits_type::minimum_size() <= sctx.size` and | |
218 | `traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size)`.]] | |
219 | [[Effects:] [Deallocates the stack space.]] | |
220 | ] | |
221 | ||
222 | ||
223 | [class_heading segmented_stack] | |
224 | ||
225 | __boost_fiber__ supports usage of a __segmented_stack__, i.e. | |
226 | the stack grows on demand. The fiber is created with a minimal stack size | |
227 | which will be increased as required. | |
228 | Class __segmented_stack__ models the __stack_allocator_concept__. | |
229 | In contrast to __pfixedsize_stack__ and __fixedsize_stack__ it creates a | |
230 | stack which grows on demand. | |
231 | ||
232 | [note Segmented stacks are currently only supported by [*gcc] from version | |
233 | [*4.7] and [*clang] from version [*3.4] onwards. In order to use a | |
234 | __segmented_stack__ __boost_fiber__ must be built with | |
235 | property `segmented-stacks`, e.g. [*toolset=gcc segmented-stacks=on] at b2/bjam | |
236 | command line.] | |
237 | ||
238 | #include <boost/fiber/segmented_stack.hpp> | |
239 | ||
240 | namespace boost { | |
241 | namespace fibers { | |
242 | ||
243 | struct segmented_stack { | |
244 | segmented_stack(std::size_t stack_size = traits_type::default_size()); | |
245 | ||
246 | stack_context allocate(); | |
247 | ||
248 | void deallocate( stack_context &); | |
249 | } | |
250 | ||
251 | }} | |
252 | ||
253 | [member_heading segmented..allocate] | |
254 | ||
255 | stack_context allocate(); | |
256 | ||
257 | [variablelist | |
258 | [[Preconditions:] [`traits_type::minimum_size() <= size` and | |
259 | `traits_type::is_unbounded() || ( traits_type::maximum_size() >= size)`.]] | |
260 | [[Effects:] [Allocates memory of at least `size` bytes and stores a pointer to | |
261 | the stack and its actual size in `sctx`. Depending on the architecture (the | |
262 | stack grows downwards/upwards) the stored address is the highest/lowest | |
263 | address of the stack.]] | |
264 | ] | |
265 | ||
266 | [member_heading segmented..deallocate] | |
267 | ||
268 | void deallocate( stack_context & sctx); | |
269 | ||
270 | ||
271 | [variablelist | |
272 | [[Preconditions:] [`sctx.sp` is valid, `traits_type::minimum_size() <= sctx.size` and | |
273 | `traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size)`.]] | |
274 | [[Effects:] [Deallocates the stack space.]] | |
275 | ] | |
276 | ||
277 | [note If the library is compiled for segmented stacks, __segmented_stack__ is the only | |
278 | available stack allocator.] | |
279 | ||
280 | [endsect] |