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}