Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

Refactor the API (possibly adding overhead) to fix a corner case

Abierto
#37 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
5/5
Tiempo estimado
Más de una semana
Aptitud para principiantes
25/100
Tipo de issue
Refactorización
Claridad
Bastante claro
Estado de actividad
Estancado
Stack tecnológico
cpp

Línea de trabajo

Comienza con las APIs push_type y pull_type de boost::coroutines2::coroutine, especialmente begin(), operator(), las operaciones de los iteradores y la contraparte generada por el framework descrita en el issue. Compara las tablas de ciclo de vida actuales y previstas, y después define el comportamiento para los rangos vacíos y el valor final; el issue no nombra archivos fuente ni tests, por lo que localizar esos puntos de entrada forma parte del trabajo.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

According to the documentation:

  1. push_type does not enter coroutine-function on construction;
  2. the first call of push_type::operator() synthesizes a complementary pull_type and passes it as reference to coroutine-function

But what happens if:

  • push_type coro([](pull_type&){ return; });
  • the user finds that bool(coro) == true (or: begin(coro) != end(coro)) so the user would like to perform coro(value_of_T) (or: *begin(coro) = value_of_T)

It seems the value will be lost.

The problem is: you don't know whether an output range is empty unless you push a value to it first.

(Edit: sorry for the mistake, it's the last value that will always be lost if the output range is not infinite.)

#include<boost/coroutine2/all.hpp>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<utility>
int main()
{
    typedef boost::coroutines2::coroutine<std::string> coro_t;

    struct FinalEOL {
        ~FinalEOL() {
            std::cout << std::endl;
        }
    };

    const int num = 5, width = 15;
    coro_t::push_type writer(
        [&](coro_t::pull_type& in) {
            //// finish the last line when we leave by whatever means
            //FinalEOL eol;
            // pull values from upstream, lay them out 'num' to a line
            //for (;;) {
            //    for (int i = 0; i < num; ++i) {
            //        // when we exhaust the input, stop
            //        if (!in) return;
            //        std::cout << std::setw(width) << in.get();
            //        // now that we've handled this item, advance to next
            //        in();
            //    }
            //    // after 'num' items, line break
            //    std::cout << std::endl;
            //}
        });

    std::vector<std::string> words{
        "peas", "porridge", "hot", "peas",
        "porridge", "cold", "peas", "porridge",
        "in", "the", "pot", "nine",
        "days", "old" };

    //std::copy(begin(words), end(words), begin(writer));

    // safe version of std::copy that takes care of end(dest)
    auto [words_it, writer_it] = std::pair{ begin(words),begin(writer) };
    for (; words_it != end(words) && writer_it != end(writer); ++words_it, ++writer_it)
    {
        *writer_it = *words_it;
    }

    // print remaining words; the first word is lost
    for (; words_it != end(words); ++words_it)
    {
        std::cout << *words_it << "\t";
    }
}

An applicable approach would be to resume the coroutine in begin(coro) like https://github.com/lewissbaker/cppcoro#generatort .

Here is the current API and the imagined API:

current API:

pull_type framework-generated push_type for pull_type push_type framework-generated pull_type for push_type
constructor enter coroutine-function
operator()
iterator::operator++()
resume coroutine-function suspend coroutine-function
get() transfer data transfer data
operator()
iterator::operator=()
transfer data, suspend coroutine-function (first time: transfer data, enter coroutine-function)
transfer data, resume coroutine-function

imagined API:

pull_type framework-generated push_type for pull_type push_type framework-generated pull_type for push_type
constructor
start()
begin(coro)
①enter coroutine-function ② ⒈enter coroutine-function ⒉suspend coroutine-function
advance()
iterator::operator++()
⑥⑩resume coroutine-function ④⑧suspend coroutine-function ⒋⒏resume coroutine-function ⒍⒑suspend coroutine-function
get() ⑤⑨transfer data ⒌⒐transfer data
set()
iterator::operator=()
③⑦transfer data ⒊⒎transfer data

Note that in the column of push_type: if after ⒊transfer data instead of ⒋resume coroutine-function you ⒋abandon the coroutine, then the value_of_T will still be lost. But this time it is the user of API to blame, not the framework.

These are what you can do:

utility current API imagined API
merge pipe and source into source
void(pull_type<T1>,push_type<T2>) + pull_type<T1> -> pull_type<T2>
trivial for loop trivial for loop
merge pipe and source into source
T2(T1) + pull_type<T1> -> pull_type<T2>
trivial for loop trivial for loop
merge pipe and sink into sink
void(pull_type<T1>,push_type<T2>) + push_type<T2> -> push_type<T1>
trivial for loop trivial for loop
merge pipe and sink into sink
T2(T1) + push_type<T2> -> push_type<T1>
trivial for loop trivial for loop
merge source and sink and stops when either one exhausts
std::pair<source_it_t, sink_it_t> safe_copy(source_begin, source_end, sink_begin, sink_end)
the first value of source will be lost if sink is an empty range trivial for loop
the user will not lose the first value of source because if sink is an empty range then we have begin(sink) == end(sink) after construction and start()/begin(sink)
Lenguaje dominante
C++
Estrellas
139
Forks
44
Métricas de merge de PR
Sin PR fusionados en 30 d

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de boostorg/coroutine2

Todos los issues de boostorg/coroutine2

Issues similares

Más issues de C++

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.