Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Class execution_context (version 1)

Boost , Chapter 1. Context , Chapter 1. Context

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext
[Note] Note

Этот класс включается только в том случае, если свойство segmented-stacks=on (включает сегментированные стеки) или флаг компилятора BOOST_EXECUTION_CONTEXT=1 указывается в b2-командной строке.

Класс execution_context инкапсулирует переключение контекста и управляет стеком связанного контекста (выделение/выделение).

execution_context выделяет контекстный стек (используя его аргумент StackAllocator) и создает поверх него управляющую структуру. Эта структура отвечает за управление стеком контекста. Случаи execution_context, связанные с конкретным контекстом, разделяют право собственности на структуру управления. Если последняя ссылка выходит из области действия, структура управления разрушается, и стек размещается через StackAllocator.

execution_context является копируемым, подвижным, копируемым и подвижным.

execution_context поддерживает статический (потоковый) указатель, доступный по execution_context::current(), указывая на активный контекст. На каждом переключателе контекста указатель обновляется. Использование этого глобального указателя делает переключение контекста немного медленнее (из-за доступа к локальному хранилищу потоков), но имеет некоторые преимущества. Он позволяет получить доступ к структуре управления текущим активным контекстом из произвольных путей кода, необходимых для поддержки сегментированных стеков, которые требуют вызова определенных функций обслуживания (например, __splitstack_getcontext() и т. д.) перед каждым коммутатором контекста (каждый коммутатор контекста обменивается стеком).

execution_context ожидает функцию/функтор с подписью void( vp) (vp - данные, переданные при первом вызове ecv1::operator()()).

usage of execution_context

int n=35;
boost::context::execution_context sink(boost::context::execution_context::current());
boost::context::execution_context source(
    [n,&sink](void*)mutable{
        int a=0;
        int b=1;
        while(n-->0){
            sink(&a);
            auto next=a+b;
            a=b;
            b=next;
        }
    });
for(int i=0;i<10;++i){
    std::cout<<*(int*)source()<<" ";
}
output:
    0 1 1 2 3 5 8 13 21 34

Этот простой пример демонстрирует основное использование execution_context. Контекст sink, возвращаемый execution_context::current(), представляет собой main-context (функция main() run) и является одним из захваченных параметров в лямбда-выражении. Ламбда, вычисляющая числа Фибоначчи, выполняется внутри контекста, представленного источником . Вычисленные числа Фибоначчи переносятся между двумя контекстами через выражение sink(&a) (и возвращаются source()).

Локальные переменные a, b и next остаются их значениями во время каждого контекстного переключателя (yield(a)). Это возможно, потому что ctx имеет стек (обмен с помощью переключателя контекста).

inverting the control flow

/*
 * grammar:
 *   P ---> E '\0'
 *   E ---> T {('+'|'-') T}
 *   T ---> S {('*'|'/') S}
 *   S ---> digit | '(' E ')'
 */
class Parser{
    // implementation omitted; see examples directory
};
std::istringstream is("1+1");
bool done=false;
std::exception_ptr except;
// create handle to main execution context
auto main_ctx(boost::context::execution_context::current());
// execute parser in new execution context
boost::context::execution_context source(
        [&sink,&is,&done,&except](void*){
        // create parser with callback function
        Parser p(is,
                 [&sink](char ch){
                        // resume main execution context
                        sink(&ch);
                });
            try {
                // start recursive parsing
                p.run();
            } catch (...) {
                // store other exceptions in exception-pointer
                except = std::current_exception();
            }
            // set termination flag
            done=true;
            // resume main execution context
            sink();
        });
// user-code pulls parsed data from parser
// invert control flow
void* vp = source();
if (except) {
    std::rethrow_exception(except);
}
while( ! done) {
    printf("Parsed: %c\n",* static_cast<char*>(vp));
    vp = source();
    if (except) {
        std::rethrow_exception(except);
    }
}
output:
    Parsed: 1
    Parsed: +
    Parsed: 1

В этом примере рекурсивный парсер спуска использует обратный вызов, чтобы излучать недавно принятый символ. Используя execution_context, поток управления может быть инвертирован, например, пользовательский код извлекает парсированные символы из парсера - вместо этого, чтобы получить выталкивание из парсера (через обратный вызов).

Данные (характер) передаются между двумя execution_context.

Если код, выполненный execution_context, испускает исключение, приложение прекращается. std:: Exception_ptr может использоваться для передачи исключений между различными контекстами исполнения.

stack unwinding

Иногда необходимо раскручивать стек незавершенного контекста, чтобы уничтожить локальные переменные стека, чтобы они могли высвобождать выделенные ресурсы (паттерн RAII). Пользователь несет ответственность за эту задачу.

allocating control structures on top of stack

Выделение структур управления поверх стека требует выделения stack_context и создания новой структуры управления с размещением до создания execution_context.

[Note] Note

Пользователь несет ответственность за разрушение структуры управления в верхней части стека.

// stack-allocator used for (de-)allocating stack
fixedsize_stack salloc( 4048);
// allocate stack space
stack_context sctx( salloc.allocate() );
// reserve space for control structure on top of the stack
void * sp = static_cast< char * >( sctx.sp) - sizeof( my_control_structure);
std::size_t size = sctx.size - sizeof( my_control_structure);
// placement new creates control structure on reserved space
my_control_structure * cs = new ( sp) my_control_structure( sp, size, sctx, salloc);
...
// destructing the control structure
cs->~my_control_structure();
...
struct my_control_structure  {
    // execution context
    execution_context ectx;
    template< typename StackAllocator >
    my_control_structure( void * sp, std::size_t size, stack_context sctx, StackAllocator salloc) :
        // create execution context
        ectx( std::allocator_arg, preallocated( sp, size, sctx), salloc, entry_func) {
    }
    ...
};

exception handling

Если функция, выполненная внутри execution_context, испускает исключение, приложение завершается вызовом std::terminate(). std:: Exception_ptr может использоваться для передачи исключений между различными контекстами исполнения.

[Important] Important

Не прыгайте изнутри блок-уловки, а затем повторно бросайте исключение в другой контекст исполнения.

parameter passing

Аргумент void pointer передан execution_context::operator(), в одном контексте, передается как последний аргумент context-function, если контекст запущен впервые. Во всех следующих вызовах execution_context::operator() указатель пустоты, переданный execution_context::operator(), в одном контексте возвращается execution_context::operator() в другом контексте.

class X {
private:
    std::exception_ptr excptr_;
    boost::context::execution_context caller_;
    boost::context::execution_context callee_;
public:
    X() :
        excptr_(),
        caller_( boost::context::execution_context::current() ),
        callee_( [=] (void * vp) {
                    try {
                        int i = * static_cast< int * >( vp);
                        std::string str = boost::lexical_cast<std::string>(i);
                        caller_( & str);
                    } catch (std::bad_cast const&) {
                        excptr_=std::current_exception();
                    }
                 })
    {}
    std::string operator()( int i) {
        void * ret = callee_( & i);
        if(excptr_){
            std::rethrow_exception(excptr_);
        }
        return * static_cast< std::string * >( ret);
    }
};
X x;
std::cout << x( 7) << std::endl;
output:
    7

Class execution_context

class execution_context {
public:
    static execution_context current() noexcept;
    template< typename Fn, typename ... Args >
    execution_context( Fn && fn, Args && ... args);
    template< typename StackAlloc, typename Fn, typename ... Args >
    execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Args && ... args);
    template< typename StackAlloc, typename Fn, typename ... Args >
    execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Args && ... args);
    execution_context( execution_context const& other) noexcept;
    execution_context( execution_context && other) noexcept;
    execution_context & operator=( execution_context const& other) noexcept;
    execution_context & operator=( execution_context && other) noexcept;
    explicit operator bool() const noexcept;
    bool operator!() const noexcept;
    void * operator()( void * vp = nullptr);
    template< typename Fn >
    void * operator()( exec_ontop_arg_t, Fn && fn, void * vp = nullptr);
    bool operator==( execution_context const& other) const noexcept;
    bool operator!=( execution_context const& other) const noexcept;
    bool operator<( execution_context const& other) const noexcept;
    bool operator>( execution_context const& other) const noexcept;
    bool operator<=( execution_context const& other) const noexcept;
    bool operator>=( execution_context const& other) const noexcept;
    template< typename charT, class traitsT >
    friend std::basic_ostream< charT, traitsT > &
    operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other);
};

Static member function current()

static execution_context current() noexcept;

Returns:

Возвращает экземпляр excution_context, указывающий на контекст активного исполнения.

Throws:

Ничего.

Constructor

template< typename Fn, typename ... Args >
execution_context( Fn && fn, Args && ... args);
template< typename StackAlloc, typename Fn, typename ... Args >
execution_context( std::allocator_arg_t, StackAlloc salloc, Fn && fn, Args && ... args);
template< typename StackAlloc, typename Fn, typename ... Args >
execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc salloc, Fn && fn, Args && ... args);

Effects:

Создает новый контекст выполнения и подготавливает контекст для выполнения fn. fixedsize_stack используется в качестве распределителя стека по умолчанию (размер стека == fixedsize_stack::traits::default_size()). Конструктор с типом аргумента , выделенным , используется для создания пользовательских данных (например, дополнительных структур управления) поверх стека.

Copy constructor

execution_context( execution_context const& other) noexcept;

Effects:

Копии other, например, базовая структура управления совместно с *this.

Throws:

Ничего.

Move constructor

execution_context( execution_context && other) noexcept;

Effects:

Переносит структуру управления в *this.

Throws:

Ничего.

Copy assignment operator

execution_context & operator=( execution_context const& other) noexcept;

Effects:

Копии Состояние other to *this, структура управления является общей.

Throws:

Ничего.

Move assignment operator

execution_context & operator=( execution_context && other) noexcept;

Effects:

Переносит управляющую структуру других на *это с помощью семантики перемещения.

Throws:

Ничего.

Member function operator bool()

explicit operator bool() const noexcept;

Returns:

true, если * это указывает на структуру управления.

Throws:

Ничего.

Member function operator!()

bool operator!() const noexcept;

Returns:

true, если * это не указывает на структуру управления.

Throws:

Ничего.

Member function operator()()

void * operator()( void * vp = nullptr) noexcept;

Effects:

Хранит внутри текущие контекстные данные (указатель стека, указатель команд и регистры процессора) текущего активного контекста и восстанавливает контекстные данные из *this, что подразумевает переход к *this. Аргумент void pointer, vp, передается в текущий контекст для возврата последним вызовом execution_context::оператор() в той же нити. fn выполнен с аргументами args поверх стека this.

Note:

Поведение не определено, если оператор()() называется, в то время как исполнение_контекст::current() возвращает * это (например, возобновление уже запущенного контекста). Если функция контекста верхнего уровня возвращается, называется std::exit().

Returns:

Аргумент указателя пустоты перешел к последнему вызову execution_context::operator(), если таковой имеется.

Member function operator(exec_ontop_arg_t)()

template< typename Fn >
void * operator()( exec_ontop_arg_t, Fn && fn, void * vp = nullptr);

Effects:

Аналогично execution_context::operator(). Кроме того, функция fn выполнена с аргументами vp в контексте *this (например, кадр стека fn выделен на стеке this).

Returns:

Аргумент указателя пустоты перешел к последнему вызову execution_context::operator(), если таковой имеется.

Member function operator==()

bool operator==( execution_context const& other) const noexcept;

Returns:

true, если * это и другие представляют собой тот же контекст выполнения, фальсифицированный в противном случае.

Throws:

Ничего.

Member function operator!=()

bool operator!=( execution_context const& other) const noexcept;

Returns:

! (другой == * это)

Throws:

Ничего.

Member function operator<()

bool operator<( execution_context const& other) const noexcept;

Returns:

true, если это != прочее истинно, а заданный реализацией полный порядок execution_context значений мест это до прочее, ложно иначе.

Throws:

Ничего.

Member function operator>()

bool operator>( execution_context const& other) const noexcept;

Returns:

other < this

Throws:

Ничего.

Member function operator<=()

bool operator<=( execution_context const& other) const noexcept;

Returns:

! (other < this

Throws:

Ничего.

Member function operator>=()

bool operator>=( execution_context const& other) const noexcept;

Returns:

! (* this < other

Throws:

Ничего.

Non-member function operator<<()

template< typename charT, class traitsT >
std::basic_ostream< charT, traitsT > &
operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other);

Efects:

Записывает представление other для потоковой передачи os.

Returns:

os


PrevUpHomeNext

Статья Class execution_context (version 1) раздела Chapter 1. Context Chapter 1. Context может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: Chapter 1. Context ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-07-04 23:58:06/0.0097239017486572/0