Coroutine C ++ 20, tipo restituito std e persistenza dello stato

Sep 28 2020

Questa domanda è in realtà due domande. Glielo chiederò subito perché potrebbero essere correlati.

Ho appena dato la prima occhiata alle coroutine C ++ 20. Se ho visto vari esempi, molti dei quali piuttosto semplici. Come il seguente:

generator<int> ints(int x)
{
   for (int i = 0; i < x; ++i)
   {
      co_yield i;
   }
}

Tutti gli esempi utilizzano un tipo di ritorno speciale che ovviamente contiene il risultato del calcolo più il contesto coroutine. Tuttavia, nessun esempio utilizza un tipo di ritorno standard. O omettono di nascosto quel tipo o definiscono una classe nidificata personalizzata che è difficile da capire (per me, attualmente).

1. Questo significa che la libreria standard C ++ 20 non fornisce tipi di ritorno coroutine pronti per l'uso, ad esempio per un generatore?

Il meglio che ho trovato è stato quello std::coroutine_handleutilizzato internamente dalle classi personalizzate menzionate.

Nei documenti si dice che le coroutine sono un buon strumento per implementare algoritmi che richiedono un'elaborazione dei dati pezzo per pezzo e normalmente dovrebbero essere suddivisi in frammenti, ad esempio utilizzando un motore a stati (potenzialmente orribilmente complicato). Lo capisco anche io. Ricordo persino un progetto che sarebbe stato un ottimo caso d'uso per una coroutine, ovvero il caricamento di un file XML grande e complesso utilizzando un'interfaccia di streaming.

Tuttavia sembra esserci una grande differenza: quando si implementa un motore di stato, è abbastanza facile memorizzare e caricare lo stato sul / dal disco poiché tutti i dati di stato sono disponibili come variabili standard (è sufficiente un controllo degli errori e la gestione dei file). Penso a qualcosa di simile a un'interfaccia utente per annullare / riprendere un calcolo di lunga durata.

2. Esiste un modo (semplice) per memorizzare / caricare un contesto di coroutine anche da / verso l'archiviazione permanente? C'è qualcosa nello standard C ++ 20 che aiuta a farlo?

Risposte

2 AndyG Sep 28 2020 at 22:23
  1. Questo significa che la libreria standard C ++ 20 non fornisce tipi di ritorno coroutine pronti per l'uso, ad esempio per un generatore?

Non è così. Sebbene le specifiche tecniche offrissero tutti i dettagli su come rendere un tipo compatibile con la coroutine, né essa né nessuna delle sue revisioni proponeva tipi compatibili con la coroutine standard.

Esso ha fornire almeno un'implementazione giocattolo di un generatore che, con un piccolo ritocco, potrebbe essere utilizzato.

p2168 propone formalmente un std::generatortipo da utilizzare nelle coroutine. Puoi anche controllare la libreria cppcoro di Lewis Baker .

  1. Esiste un modo (semplice) per archiviare / caricare un contesto coroutine anche da / verso l'archiviazione permanente?

La risposta breve è "no".

C'è qualcosa nello standard C ++ 20 che aiuta a farlo?

La risposta breve è anche "no".

Quando viene creata una coroutine, il compilatore allocherà un po 'di spazio nell'heap per un contesto coroutine, questo include variabili locali e copie / riferimenti ai parametri. Non totalmente diverso da come ci sono gli stack frame per le chiamate di funzione. Ma non serializziamo gli stack frame, vero? Non ha proprio senso.

Pensala in questo modo, se volessi serializzare una funzione regolare, la trasformeresti in un oggetto. Come fa il pattern Command. Il risultato non è esattamente come uno stack frame, ma hai ancora qualcosa da chiamare che fa quello che ti serve.

Le coroutine non sono diverse. Se è necessario serializzare / deserializzare lo stato, si utilizzerà un oggetto richiamabile. Potresti usare questo oggetto all'interno di una coroutine, ma non sarebbe esattamente lo stesso.

2 AnthonyWilliams Sep 28 2020 at 20:48

Non ci sono funzioni o tipi di coroutine di libreria in C ++ 20 ad eccezione degli handle e dei tratti a livello di implementazione. Hai bisogno di una libreria coroutine, che puoi costruire da solo o utilizzare da una fonte esistente come cppcoro .

Non è disponibile alcun supporto per il salvataggio di un contesto coroutine nella memoria permanente. Dovresti costruirlo da solo. Probabilmente avrebbe un'implementazione piuttosto complessa.