wasmtime_runtime/
module_id.rs

1//! Unique IDs for modules in the runtime.
2
3use std::{
4    num::NonZeroU64,
5    sync::atomic::{AtomicU64, Ordering},
6};
7
8/// A unique identifier (within an engine or similar) for a compiled
9/// module.
10#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub struct CompiledModuleId(NonZeroU64);
12
13/// An allocator for compiled module IDs.
14pub struct CompiledModuleIdAllocator {
15    next: AtomicU64,
16}
17
18impl CompiledModuleIdAllocator {
19    /// Create a compiled-module ID allocator.
20    pub fn new() -> Self {
21        Self {
22            next: AtomicU64::new(1),
23        }
24    }
25
26    /// Allocate a new ID.
27    pub fn alloc(&self) -> CompiledModuleId {
28        // Note: why is `Relaxed` OK here?
29        //
30        // The only requirement we have is that IDs are unique. We
31        // don't care how one module's ID compares to another, i.e.,
32        // what order they come in. `Relaxed` means that this
33        // `fetch_add` operation does not have any particular
34        // synchronization (ordering) with respect to any other memory
35        // access in the program. However, `fetch_add` is always
36        // atomic with respect to other accesses to this variable
37        // (`self.next`). So we will always hand out separate, unique
38        // IDs correctly, just in some possibly arbitrary order (which
39        // is fine).
40        let id = self.next.fetch_add(1, Ordering::Relaxed);
41        CompiledModuleId(NonZeroU64::new(id).unwrap())
42    }
43}