Skip to content
Snippets Groups Projects
Verified Commit 61a4c4d6 authored by orestis.malaspin's avatar orestis.malaspin
Browse files

added counter

parent 4f068bcd
Branches
No related tags found
No related merge requests found
Pipeline #38982 passed
--
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)
...@@ -97,8 +97,6 @@ impl Future for Coroutine { ...@@ -97,8 +97,6 @@ impl Future for Coroutine {
self.stack.writer = Some(self.stack.buffer.as_mut().unwrap()); self.stack.writer = Some(self.stack.buffer.as_mut().unwrap());
println!("Program starting"); println!("Program starting");
// ---------------------------------
let fut1 = Box::new(Http::get("/600/HelloAsyncWait")); let fut1 = Box::new(Http::get("/600/HelloAsyncWait"));
self.state = State::Wait1(fut1); self.state = State::Wait1(fut1);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment