Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Абстракции с нулевой стоимостью

Typestate — также хороший пример абстракций с нулевой стоимостью (zero cost abstractions): возможности перенести определённое поведение на этап выполнения компилятора или на этап анализа. Эти typestate не содержат никаких реальных данных и используются как маркеры. Поскольку они не содержат данных, у них нет реального представления в памяти во время выполнения:

use core::mem::size_of;

let _ = size_of::<Enabled>();    // == 0
let _ = size_of::<Input>();      // == 0
let _ = size_of::<PulledHigh>(); // == 0
let _ = size_of::<GpioConfig<Enabled, Input, PulledHigh>>(); // == 0

Типы нулевого размера

struct Enabled;

Структуры, определённые таким образом, называются типами нулевого размера (Zero Sized Types), поскольку они не содержат никаких реальных данных. Хотя на этапе компиляции эти типы ведут себя как «настоящие» — их можно копировать, перемещать, брать от них ссылки и т. д., — оптимизатор полностью удалит их.

В этом фрагменте кода:

pub fn into_input_high_z(self) -> GpioConfig<Enabled, Input, HighZ> {
    self.periph.modify(|_r, w| w.input_mode().high_z());
    GpioConfig {
        periph: self.periph,
        enabled: Enabled,
        direction: Input,
        mode: HighZ,
    }
}

Возвращаемый GpioConfig никогда не существует во время выполнения. Вызов этой функции, как правило, сводится к одной ассемблерной инструкции — записи константного значения регистра в нужное место регистра. Это означает, что построенный нами интерфейс typestate — абстракция с нулевой стоимостью: он не тратит больше процессорного времени, ОЗУ или места в коде на отслеживание состояния GpioConfig, и компилируется в тот же машинный код, что и прямой доступ к регистру.

Вложенность

В общем случае такие абстракции можно вкладывать сколько угодно глубоко. Пока все используемые компоненты — типы нулевого размера, вся структура не будет существовать во время выполнения.

Для сложных или глубоко вложенных структур может быть утомительно определять все возможные комбинации состояний. В таких случаях для генерации всех реализаций можно использовать макросы.