08 · Tratamento de Erros
Escopos de recursos visíveis
using recurso = aquisição { corpo } instala a limpeza após uma aquisição bem-sucedida. O tipo precisa implementar core::cleanup::Cleanup. A limpeza acompanha saídas léxicas e transferências de ownership a desarmam. Um método apenas chamado close não comprova o protocolo.
Nesta página
using recurso = aquisição { corpo } instala a limpeza após uma aquisição bem-sucedida. O tipo precisa implementar core::cleanup::Cleanup. A limpeza acompanha saídas léxicas e transferências de ownership a desarmam. Um método apenas chamado close não comprova o protocolo.
Exemplo completo
Escopos de recursos visíveis.
// Resource scopes install cleanup after successful acquisition.
var acquired = 0
struct Resource { id: int }
fn acquire(id: int) -> Result<Resource, str> {
acquired += 1
if id < 0 { .Err("acquisition") } else { .Ok(Resource { id }) }
}
impl core::cleanup::Cleanup for Resource {
fn close(self) { print("close"); print(self.id) }
}
fn read(id: int) -> Result<int, str> {
let value = using file = acquire(id)? {
defer print("body-defer")
file.id + 10
}
Result::Ok(value)
}
print(read(1).unwrap())
print(read(-1).is_err())
print(acquired)
fn early() -> int {
using file = Resource { id: 2 } { return 22 }
0
}
print(early())
fn fail() -> Result<int, str> { .Err("body") }
fn propagated() -> Result<int, str> {
let value = using file = Resource { id: 3 } { fail()? }
Result::Ok(value)
}
print(propagated().is_err())
var count = 0
:outer loop {
count += 1
using file = Resource { id: count + 3 } {
defer print("loop-defer")
if count == 1 { continue :outer }
break :outer
}
}
let tail = using outer = Resource { id: 6 } {
let inner = using inner = Resource { id: 7 } { inner.id }
inner + outer.id
}
print(tail)
@linear struct Owned { id: int }
impl core::cleanup::Cleanup for Owned {
fn close(self) { print("owned-close"); print(self.id) }
}
impl Owned {
fn finish(sink self) { self.close(); let Owned { .. } = self }
}
using owned = Owned { id: 8 } { 0 }
using owned = Owned { id: 9 } {
var __zolo_live_0 = true
owned.finish()
assert(__zolo_live_0)
0
}
fn consume(sink owned: Owned) { owned.close(); let Owned { .. } = owned }
fn seven() -> int { 7 }
fn consume_with(sink owned: Owned, number: int) { assert(number == 7); consume(owned) }
using owned = Owned { id: 10 } {
let __zolo_arg_0 = 13
consume_with(owned, seven())
assert(__zolo_arg_0 == 13)
0
}
let transferred = using owned = Owned { id: 11 } { owned }
consume(transferred)
// The implicit cleanup owns the original binding even when the body shadows it.
let shadow = using file = Resource { id: 12 } {
let file = Resource { id: 13 }
file.id
}
print(shadow)
// Generic sink transfer hands the resource to the caller and disarms cleanup.
fn moved<T: core::cleanup::Cleanup>(sink value: T) -> T {
using resource = value { resource }
}
consume(moved(Owned { id: 14 }))
macro scoped(value) { using resource = $value { consume(resource); 7 } }
print(scoped!(Owned { id: 15 }))
print(scoped!(Owned { id: 16 }))
// An owned generic factory temporary keeps its cleanup obligation.
fn acquire_owned() -> Owned { Owned { id: 17 } }
fn scoped_factory<T: core::cleanup::Cleanup>(factory: fn() -> T) -> int {
let acquired = factory()
using resource = acquired { 7 }
}
print(scoped_factory(acquire_owned))
Regras e comportamento
Handlers e escopos de recursos · Documentação
A partir de um checkout do repositório:
zolo examples/features/resource-scopes.zolo
Adquirindo vários recursos
O cabeçalho separado por vírgulas adquire os recursos em ordem e registra a liberação após cada aquisição bem-sucedida. A liberação executa na ordem inversa, inclusive se uma aquisição posterior falhar.
// Each successful acquisition installs cleanup before the next one starts.
struct File { name: str }
fn open(name: str) -> File { File { name } }
impl core::cleanup::Cleanup for File {
fn close(self) { print("close {self.name}") }
}
let copied = using source = open("source"), target = open("target") {
print("{source.name} -> {target.name}")
3
}
// expect: source -> target
// expect: close target
// expect: close source
print(copied) // expect: 3
Veja também