From 61a4c4d6e11dd4e1dc5ea333775ca35d33e0266a Mon Sep 17 00:00:00 2001 From: Orestis <orestis.malaspinas@pm.me> Date: Mon, 31 Mar 2025 13:04:25 +0200 Subject: [PATCH] added counter --- 09_pinning.md | 134 +++++++++++++++++++++++++ codes/coroutines-variables/src/main.rs | 2 - 2 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 09_pinning.md diff --git a/09_pinning.md b/09_pinning.md new file mode 100644 index 0000000..1f00212 --- /dev/null +++ b/09_pinning.md @@ -0,0 +1,134 @@ +-- +title: "Structures auto-référencées et pinning" +author: "Orestis Malaspinas" +date: "2025-03-31" +patat: + slideNumber: true + wrap: true + margins: + left: 10 + right: 10 + top: auto + slideLevel: 2 + images: + backend: kitty +... + +# Introduction + +## Programme + +* Impossible de stocker des variables au travers de changement d'états +* Partie 1: ajouter un compteur +* Partie 2: ajouter des références +* Partie 3: les structures auto-référencées +* Partie 4: Pinning + +# Partie 1: ajouter un compteur + +## Objectif: ajouter un compteur dans notre code async + +```rust +fn main() { + let mut executor = runtime::init(); + executor.block_on(async_main()); +} +coroutine fn async_main() { + let mut counter = 0; + println!("Program starting"); + let txt = http::Http::get("/600/HelloAsyncAwait").wait; + println!("{txt}"); + counter += 1; + let txt = http::Http::get("/400/HelloAsyncAwait").wait; + println!("{txt}"); + counter += 1; + println!("Received {} responses.", counter); +} +``` + +## Problème? + +* `counter` ne peut pas être partagé actuellement +* on a une structure (pas de `counter` là dedans) + + ```rust + fn poll(&mut self, waker: &Waker) -> PollState<Self::Output> { + match self.state { + State::Start => { + println!("Program starting"); + let fut1 = Box::new(Http::get("/600/HelloAsyncAwait")); + self.state = State::Wait1(fut1); + } + State::Wait1(ref mut future) => match future.poll(waker) { + PollState::Ready(txt) => { + println!("{txt}"); + let fut2 = Box::new(Http::get("/400/HelloAsyncAwait")); + self.state = State::Wait2(fut2); + }, + State::Wait2(ref mut future) => match future.poll(waker) { + PollState::Ready(txt) => { + println!("{txt}"); + self.state = State::Resolved; + break PollState::Ready(String::new()); + ``` + +## Solution + +* Ajout d'une "pile" dans `Coroutine` +* Stocke un état interne + + ```rust + struct Coroutine { + stack: Stack, + state: State, + } + struct Stack { + counter: Option<usize>, + } + ``` +* A présent `poll(&mut self, water: &Waker)` contient `counter` +* Pas complètement idéal, car on doit stocker une copie des données dans des structs séparées +* Chaque changement d'état doit contenir sa propre variable +* On pourrait faire mieux en stockant que les modifications + +## Le compteur 1/ + +```rust +State::Start => { + self.stack.counter = Some(0); + self.state = State::Wait1(Box::new(Http::get("/600/HelloAsyncWait"))); +} +State::Wait1(ref mut f1) => { + match f1.poll(waker) { + PollState::Ready(txt) => { + let mut counter = self.stack.counter.take().unwrap(); + counter += 1; + self.state = State::Wait2(Box::new(Http::get("/600/HelloAsyncWait"))); + self.stack.counter = Some(counter); + } +} +State::Wait2(ref mut f2) => { + match f2.poll(waker) { + PollState::Ready(txt) => { + let mut counter = self.stack.counter.take().unwrap(); + counter += 1; + println!("Received {counter} responses"); + self.state = State::Resolved; + break PollState::Ready(String::new()); + } +} +``` + +## Compteur 2/ + +* `Start`: on initialise le compteur +* `Wait1`: + * on **prend l'ownership** de la valeur dans le compteur (`take()`) + * on incrémente le compteur + * on stocke la valeur dans la pile à nouveau +* `Wait2`: + * on **prend l'ownership** de la valeur dans le compteur (`take()`) + * on incrémente le compteur + * on affiche sa velur à l'écran + * on "nettoie" la valeur (rien besoin de faire, car on a déjà `None` dans la pile) + diff --git a/codes/coroutines-variables/src/main.rs b/codes/coroutines-variables/src/main.rs index d057e0f..f720009 100644 --- a/codes/coroutines-variables/src/main.rs +++ b/codes/coroutines-variables/src/main.rs @@ -97,8 +97,6 @@ impl Future for Coroutine { self.stack.writer = Some(self.stack.buffer.as_mut().unwrap()); println!("Program starting"); - - // --------------------------------- let fut1 = Box::new(Http::get("/600/HelloAsyncWait")); self.state = State::Wait1(fut1); } -- GitLab