Conceitos de Rust
Rust avançado, do sistema de tipos ao código unsafe, async e produção, medido no Rust 1.100 e baseado na documentação oficial, em livros e em papers, um conceito de cada vez.
Threads & Atomics
Send, Sync e Mutabilidade Interior
Send e Sync como auto traits, com uma tabela compilada de quais tipos da std os implementam, os erros E0277 reais de Rc, RefCell e Cell entre threads, a corrupção medida do contador de um Rc com um unsafe impl Send falso, UnsafeCell como única porta legal para a mutabilidade interior e o assembly que ela muda, tamanhos de Cell e RefCell e o panic de reentrância do RefCell, OnceLock e LazyLock (1.80) em corrida, envenenamento e deadlock reentrante, e unsafe impl Send e Sync escritos à mão com a pegadinha da captura disjunta da edição 2021, no Rust 1.100.0.
Atômicos e Ordenação de Memória
O modelo de memória do Rust, herdado do C++20, medido em arm64, com a instrução que cada ordering gera (ldapr para Acquire, ldar para SeqCst, ldadd, casal, dmb), testes litmus de store buffering em que Release/Acquire ainda mostra o resultado proibido dezenas de milhares de vezes a cada 10 milhões de rodadas e SeqCst ou um fence SeqCst mostram zero, message passing em que Relaxed falha raramente e Release/Acquire ou fences nunca falham, atualizações perdidas com load seguido de store, falhas espúrias de compare_exchange_weak só em builds LL/SC, e update/try_update (1.95) com fetch_update depreciado no 1.99, no Rust 1.100.0.
Async
Futures, Wakers e o Modelo de Poll
A trait Future com Poll, Context e Waker, o enum de estados que o compilador gera para um async fn (medido com size_of_val e -Zprint-type-sizes), por que o tamanho do future cresce com o que atravessa o .await e onde Box::pin ajuda, um executor block_on mínimo só com std (Wake e thread park) e o travamento silencioso de um Pending sem wake, inclusive como ele se disfarça de latência sob tokio::time::timeout.
Pin e Futures Autorreferenciais
Por que a máquina de estados de um async fn pode apontar para si mesma (medido em memória), a garantia de Pin e o auto trait Unpin, os erros reais do compilador ao chamar poll num future sem pin, pin! versus Box::pin, pinning estrutural e projeção com pin-project-lite (incluindo a proibição de Drop e o PinnedDrop) e o que acontece, nativamente e no Miri, quando código unsafe move um future já fixado, com o motivo do RFC 2349.
Por Dentro do Runtime do Tokio
Os schedulers current_thread e multi_thread, filas locais e global com work stealing medido, o LIFO slot, o orçamento cooperativo de 128 unidades com consume_budget, o driver de I/O sobre kqueue e epoll via mio, o timer de 1 ms, e o travamento medido de uma thread do runtime bloqueada com std::thread::sleep corrigido com spawn_blocking e block_in_place.
Async Traits e Async Closures
async fn em traits e RPITIT (1.75), o erro de Send ao fazer spawn em código genérico e as correções com -> impl Future + Send e trait_variant::make, return type notation ainda instável, por que dyn com métodos async não é dyn compatible, boxing com async-trait ou Pin<Box<dyn Future>> medido em alocações por chamada, e async closures com AsyncFn, AsyncFnMut e AsyncFnOnce (1.85) contra closures que devolvem futures.
Cancel Safety e Shutdown Gracioso
Drop como cancelamento, o que o tokio::select! faz com os ramos perdedores, JoinHandle que desanexa e abort, as listas de cancel safety da documentação do Tokio, a perda de dados medida com read_exact num loop de select! e a correção com read_buf, JoinSet, CancellationToken com child tokens, e shutdown gracioso com sinal, cancelamento em broadcast, TaskTracker e prazo, incluindo o SIGTERM que o ctrl_c não captura.