v0.2.12
This commit is contained in:
97
chapters/028-defer-et-nettoyage.md
Normal file
97
chapters/028-defer-et-nettoyage.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# 28. `defer` et nettoyage
|
||||
|
||||
## 28.1 `defer` — V1 REQUIS — FIGÉ
|
||||
|
||||
`defer` est lié au scope lexical dans lequel il est atteint. Il enregistre un cleanup exécuté à toute sortie de ce scope.
|
||||
|
||||
Exemple :
|
||||
|
||||
```text
|
||||
{
|
||||
acquireA();
|
||||
defer {
|
||||
releaseA();
|
||||
}
|
||||
|
||||
acquireB();
|
||||
defer {
|
||||
releaseB();
|
||||
}
|
||||
|
||||
work();
|
||||
}
|
||||
```
|
||||
|
||||
Les `defer` d'un même scope s'exécutent en ordre LIFO :
|
||||
|
||||
```text
|
||||
releaseB();
|
||||
releaseA();
|
||||
```
|
||||
|
||||
Un `defer` n'est actif que si son statement a réellement été atteint pendant l'exécution.
|
||||
|
||||
Les sorties qui déclenchent les `defer` du scope traversé comprennent notamment :
|
||||
|
||||
```text
|
||||
fin normale
|
||||
return
|
||||
throw
|
||||
break
|
||||
continue
|
||||
emit quittant le scope concerné
|
||||
```
|
||||
|
||||
La valeur d'un `return` ou d'un `emit` est déterminée avant l'exécution des cleanups nécessaires ; les `defer` ne peuvent pas la remplacer.
|
||||
|
||||
## 28.2 Unwind et ordre avec `catch` / `finally` — V1 REQUIS — FIGÉ
|
||||
|
||||
Lorsqu'une `Exception` quitte un scope, les `defer` des scopes abandonnés sont exécutés avant l'entrée dans le `catch` correspondant.
|
||||
|
||||
Ordre conceptuel :
|
||||
|
||||
```text
|
||||
throw
|
||||
-> unwind des scopes quittés
|
||||
-> defer de ces scopes, LIFO
|
||||
-> catch correspondant éventuel
|
||||
-> defer du scope catch, LIFO
|
||||
-> finally éventuel
|
||||
-> continuation normale ou propagation
|
||||
```
|
||||
|
||||
Chaque scope imbriqué possède sa propre pile LIFO et est entièrement déroulé avant de poursuivre le scope parent.
|
||||
|
||||
L'ordre exact entre `defer` et les futurs destructeurs automatiques sera finalisé avec le modèle mémoire/lifecycle, sans modifier la règle de scope LIFO propre à `defer`.
|
||||
|
||||
## 28.3 `defer` non-escaping — V1 REQUIS — FIGÉ
|
||||
|
||||
Comme `finally`, un bloc `defer` ne doit jamais remplacer une sortie déjà en cours.
|
||||
|
||||
Sont interdits dans un `defer` lorsqu'ils quittent le bloc :
|
||||
|
||||
```text
|
||||
return
|
||||
throw
|
||||
break
|
||||
continue
|
||||
emit
|
||||
```
|
||||
|
||||
Aucune `Exception` non capturée ne peut sortir indirectement d'un `defer`. Une callable appelée depuis un `defer` et susceptible de lancer une `Exception` doit voir cette exception entièrement gérée à l'intérieur du bloc `defer`.
|
||||
|
||||
Un `ResultError` reste une simple valeur : un appel retournant `Result<T,E>` est autorisé dans un `defer`, sous réserve des règles normales de traitement de cette valeur.
|
||||
|
||||
## 28.4 `finally` versus `defer` — V1 REQUIS — FIGÉ
|
||||
|
||||
`defer` sert au cleanup lexical lié à une acquisition ou à un scope local.
|
||||
|
||||
`finally` sert au bloc commun final d'une vraie construction `try/catch`.
|
||||
|
||||
Un `try/finally` sans `catch` est interdit précisément parce que `defer` couvre le besoin de cleanup systématique sans introduire une construction d'exception inutile.
|
||||
|
||||
## 28.5 `errdefer` — REJETÉ
|
||||
|
||||
Pas de `errdefer` séparé en V1.
|
||||
|
||||
`catch` gère les chemins d'`Exception`; `defer` gère le cleanup systématique du scope. Un troisième mécanisme serait redondant.
|
||||
Reference in New Issue
Block a user