Devices are the abstraction Cairo employs for the rendering system used by a
[[cairo::surface_t]]. You can get the device of a surface using
[[cairo::surface::get_device]].

Devices are created using custom functions specific to the rendering system you
want to use. See the documentation for the surface types for those functions.

An important function that devices fulfill is sharing access to the rendering
system between Cairo and your application. If you want to access a device
directly that you used to draw to with Cairo, you must first call
[[flush]] to ensure that Cairo finishes all operations on the
device and resets it to a clean state.

Cairo also provides the functions [[acquire]] and [[release]] to synchronize
access to the rendering system in a multithreaded environment. This is done
internally, but can also be used by applications.

Putting this all together, a function that works with devices should look
something like this:

    fn my_device_modifying_function(device: cairo::device_t) void = {
        // Ensure the device is properly reset
        cairo::device::flush(device);
        // Try to acquire the device
        match(cairo::device::acquire(device)) {
        case void => void;
        case let e: cairo::error =>
        fmt::fatalf("Failed to acquire the device: {}", cairo::strerror(e));
        };
        // Release the device when done.
        defer cairo::device::release(device);
        // Do the custom operations on the device here.
        // But do not call any Cairo functions that might acquire devices.
    };

Please refer to the documentation of each backend for additional usage
requirements, guarantees provided, and interactions with existing surface API of
the device functions for surfaces of that type.
