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

Integrating Fibers with Nonblocking I/O

Boost , Chapter 1. Fiber , Chapter 1. Fiber

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

Overview

Неблокировка I/O отличается от синхронной I/O. Истинная операция async I/O обещает инициировать операцию и уведомлять звонящего о завершении, как правило, через какой-то обратный вызов (как описано в Интеграция волокон с асинхронными звонками).

В отличие от этого, неблокирующая операция I/O отказывается начать вообще, если будет необходимо заблокировать, возвращая код ошибки, такой как EWOULDBLOCK. Операция выполняется только тогда, когда она может завершиться немедленно. В действительности, звонящий должен повторно провести операцию до тех пор, пока она не прекратит возвращение EWOULDBLOCK.

В классической программе, ориентированной на события, это может быть чем-то вроде головной боли, чтобы использовать неблокирование I/O. В точке, где делается попытка неблокирования I/O, значение возврата EWOULDBLOCK требует, чтобы звонящий передал контроль обратно к основной петле событий, организовав возврат на следующую итерацию.

Хуже того, неблокирующая операция I/O может частично преуспеть. Это означает, что соответствующая бизнес-логика должна продолжать получать контроль над каждой основной итерацией петли до тех пор, пока не будут обработаны все необходимые данные: дублируемая петля, реализованная как государственный аппарат, управляемый вызовом.

Boost.Fiber может значительно упростить эту проблему. После того, как вы интегрировались с основной петлей приложения, как описано в Соединение Thread с другим главным Loop , ожидание следующей итерации основной волны так же просто, как вызов this_fiber::yield().

Example Nonblocking API

Для иллюстрации рассмотрим этот API:

class NonblockingAPI {
public:
    NonblockingAPI();
    // nonblocking operation: may return EWOULDBLOCK
    int read( std::string & data, std::size_t desired);
    ...
};

Polling for Completion

Мы можем построить низкоуровневую обертку около NonblockingAPI::read(), которая защищает своего звонящего от необходимости иметь дело с EWOULDBLOCK:

// guaranteed not to return EWOULDBLOCK
int read_chunk( NonblockingAPI & api, std::string & data, std::size_t desired) {
    int error;
    while ( EWOULDBLOCK == ( error = api.read( data, desired) ) ) {
        // not ready yet -- try again on the next iteration of the
        // application's main loop
        boost::this_fiber::yield();
    }
    return error;
}

Filling All Desired Data

Учитывая read_chunk(), мы можем просто итерировать, пока не получим все желаемые данные:

// keep reading until desired length, EOF or error
// may return both partial data and nonzero error
int read_desired( NonblockingAPI & api, std::string & data, std::size_t desired) {
    // we're going to accumulate results into 'data'
    data.clear();
    std::string chunk;
    int error = 0;
    while ( data.length() < desired &&
           ( error = read_chunk( api, chunk, desired - data.length() ) ) == 0) {
        data.append( chunk);
    }
    return error;
}

(Из course есть более эффективные способы накопления строковых данных. Это не суть этого примера.)

Wrapping it Up

Наконец, мы можем определить соответствующее исключение:

// exception class augmented with both partially-read data and errorcode
class IncompleteRead : public std::runtime_error {
public:
    IncompleteRead( std::string const& what, std::string const& partial, int ec) :
        std::runtime_error( what),
        partial_( partial),
        ec_( ec) {
    }
    std::string get_partial() const {
        return partial_;
    }
    int get_errorcode() const {
        return ec_;
    }
private:
    std::string partial_;
    int         ec_;
};

и написать простую функцию read(), которая либо возвращает все желаемые данные, либо бросает In completeRead:

// read all desired data or throw IncompleteRead
std::string read( NonblockingAPI & api, std::size_t desired) {
    std::string data;
    int ec( read_desired( api, data, desired) );
    // for present purposes, EOF isn't a failure
    if ( 0 == ec || EOF == ec) {
        return data;
    }
    // oh oh, partial read
    std::ostringstream msg;
    msg << "NonblockingAPI::read() error " << ec << " after "
        << data.length() << " of " << desired << " characters";
    throw IncompleteRead( msg.str(), data, ec);
}

Как только мы сможем прозрачно ждать следующей итерации с главной крышей, используя This_fiber::yield(), обычная инкапсуляция Just Works.

Исходный код выше содержится в adapt_nonblocking.cpp.


PrevUpHomeNext

Статья Integrating Fibers with Nonblocking I/O раздела Chapter 1. Fiber Chapter 1. Fiber может быть полезна для разработчиков на c++ и boost.




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



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


реклама


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

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 19:19:47/0.0073308944702148/0