Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Stack allocation

Support for valgrind
Support for sanitizers

A fiber uses internally an __econtext__ which manages a set of registers and a stack. The memory used by the stack is allocated/deallocated via a stack_allocator which is required to model a stack-allocator concept.

A stack_allocator can be passed to fiber::fiber() or to fibers::async().

stack-allocator concept

A stack_allocator must satisfy the stack-allocator concept requirements shown in the following table, in which a is an object of a stack_allocator type, sctx is a stack_context, and size is a std::size_t:

expression

return type

notes

a(size)

creates a stack allocator

a.allocate()

stack_context

creates a stack

a.deallocate( sctx)

void

deallocates the stack created by a.allocate()

[Important] Important

The implementation of allocate() might include logic to protect against exceeding the context's available stack size rather than leaving it as undefined behaviour.

[Important] Important

Calling deallocate() with a stack_context not obtained from allocate() results in undefined behaviour.

[Note] Note

The memory for the stack is not required to be aligned; alignment takes place inside __econtext__.

See also Boost.Context stack allocation. In particular, traits_type methods are as described for boost::context::stack_traits.

Class protected_fixedsize_stack

Boost.Fiber provides the class protected_fixedsize_stack which models the stack-allocator concept. It appends a guard page at the end of each stack to protect against exceeding the stack. If the guard page is accessed (read or write operation) a segmentation fault/access violation is generated by the operating system.

[Important] Important

Using protected_fixedsize_stack is expensive. Launching a new fiber with a stack of this type incurs the overhead of setting the memory protection; once allocated, this stack is just as efficient to use as fixedsize_stack.

[Note] Note

The appended guard page is not mapped to physical memory, only virtual addresses are used.

#include <boost/fiber/protected_fixedsize.hpp>

namespace boost {
namespace fibers {

struct protected_fixedsize {
    protected_fixesize(std::size_t size = traits_type::default_size());

    stack_context allocate();

    void deallocate( stack_context &);
}

}}

Member function allocate()

stack_context allocate();

Preconditions:

traits_type::minimum_size() <= size and traits_type::is_unbounded() || ( size <= traits_type::maximum_size() ).

Effects:

Allocates memory of at least size bytes and stores a pointer to the stack and its actual size in sctx. Depending on the architecture (the stack grows downwards/upwards) the stored address is the highest/lowest address of the stack.

Member function deallocate()

void deallocate( stack_context & sctx);

Preconditions:

sctx.sp is valid, traits_type::minimum_size() <= sctx.size and traits_type::is_unbounded() || ( sctx.size <= traits_type::maximum_size() ).

Effects:

Deallocates the stack space.

Class pooled_fixedsize_stack

Boost.Fiber provides the class pooled_fixedsize_stack which models the stack-allocator concept. In contrast to protected_fixedsize_stack it does not append a guard page at the end of each stack. The memory is managed internally by boost::pool<>.

#include <boost/fiber/pooled_fixedsize_stack.hpp>

namespace boost {
namespace fibers {

struct pooled_fixedsize_stack {
    pooled_fixedsize_stack(std::size_t stack_size = traits_type::default_size(), std::size_t next_size = 32, std::size_t max_size = 0);

    stack_context allocate();

    void deallocate( stack_context &);
}

}}

Constructor

pooled_fixedsize_stack(std::size_t stack_size, std::size_t next_size, std::size_t max_size);

Preconditions:

traits_type::is_unbounded() || ( traits_type::maximum_size() >= stack_size) and 0 < next_size.

Effects:

Allocates memory of at least stack_size bytes and stores a pointer to the stack and its actual size in sctx. Depending on the architecture (the stack grows downwards/upwards) the stored address is the highest/lowest address of the stack. Argument next_size determines the number of stacks to request from the system the first time that *this needs to allocate system memory. The third argument max_size controls how much memory might be allocated for stacks — a value of zero means no upper limit.

Member function allocate()

stack_context allocate();

Preconditions:

traits_type::is_unbounded() || ( traits_type::maximum_size() >= stack_size).

Effects:

Allocates memory of at least stack_size bytes and stores a pointer to the stack and its actual size in sctx. Depending on the architecture (the stack grows downwards/upwards) the stored address is the highest/lowest address of the stack.

Member function deallocate()

void deallocate( stack_context & sctx);

Preconditions:

sctx.sp is valid, traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size).

Effects:

Deallocates the stack space.

[Note] Note

This stack allocator is not thread safe.

Class fixedsize_stack

Boost.Fiber provides the class fixedsize_stack which models the stack-allocator concept. In contrast to protected_fixedsize_stack it does not append a guard page at the end of each stack. The memory is simply managed by std::malloc() and std::free().

#include <boost/context/fixedsize_stack.hpp>

namespace boost {
namespace fibers {

struct fixedsize_stack {
    fixedsize_stack(std::size_t size = traits_type::default_size());

    stack_context allocate();

    void deallocate( stack_context &);
}

}}

Member function allocate()

stack_context allocate();

Preconditions:

traits_type::minimum_size() <= size and traits_type::is_unbounded() || ( traits_type::maximum_size() >= size).

Effects:

Allocates memory of at least size bytes and stores a pointer to the stack and its actual size in sctx. Depending on the architecture (the stack grows downwards/upwards) the stored address is the highest/lowest address of the stack.

Member function deallocate()

void deallocate( stack_context & sctx);

Preconditions:

sctx.sp is valid, traits_type::minimum_size() <= sctx.size and traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size).

Effects:

Deallocates the stack space.

Class segmented_stack

Boost.Fiber supports usage of a segmented_stack, i.e. the stack grows on demand. The fiber is created with a minimal stack size which will be increased as required. Class segmented_stack models the stack-allocator concept. In contrast to protected_fixedsize_stack and fixedsize_stack it creates a stack which grows on demand.

[Note] Note

Segmented stacks are currently only supported by gcc from version 4.7 and clang from version 3.4 onwards. In order to use a segmented_stack Boost.Fiber must be built with property segmented-stacks, e.g. toolset=gcc segmented-stacks=on and applying BOOST_USE_SEGMENTED_STACKS at b2/bjam command line.

[Note] Note

Segmented stacks can only be used with callcc() using property context-impl=ucontext.

#include <boost/fiber/segmented_stack.hpp>

namespace boost {
namespace fibers {

struct segmented_stack {
    segmented_stack(std::size_t stack_size = traits_type::default_size());

    stack_context allocate();

    void deallocate( stack_context &);
}

}}

Member function allocate()

stack_context allocate();

Preconditions:

traits_type::minimum_size() <= size and traits_type::is_unbounded() || ( traits_type::maximum_size() >= size).

Effects:

Allocates memory of at least size bytes and stores a pointer to the stack and its actual size in sctx. Depending on the architecture (the stack grows downwards/upwards) the stored address is the highest/lowest address of the stack.

Member function deallocate()

void deallocate( stack_context & sctx);

Preconditions:

sctx.sp is valid, traits_type::minimum_size() <= sctx.size and traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size).

Effects:

Deallocates the stack space.

[Note] Note

If the library is compiled for segmented stacks, segmented_stack is the only available stack allocator.


PrevUpHomeNext