harmos_runtime/operations/
lane.rs1use std::collections::BTreeMap;
18use std::sync::Arc;
19use tokio::sync::Semaphore;
21pub(crate) const RESIDENT: &str = "harmos.resident";
28
29#[derive(Clone, Copy, Debug, PartialEq, Eq)]
36pub struct Capacity {
37 width: usize,
38}
39
40#[derive(Clone, Debug, Default)]
41pub struct LaneSet {
42 entries: Vec<(&'static str, Capacity)>,
43}
44
45#[derive(Clone)]
46pub(crate) struct Admission {
47 name: &'static str,
48 width: usize,
49 semaphore: Arc<Semaphore>,
50}
51
52pub(crate) struct Lanes {
53 lanes: BTreeMap<&'static str, Admission>,
54}
55
56pub trait Lane: Copy + Eq + Send + Sync + 'static {
61 fn default_lane() -> Self;
62 fn name(&self) -> &'static str;
63 fn capacity(&self) -> Capacity;
64}
65
66impl Capacity {
69 pub const fn serial() -> Self {
70 Self { width: 1 }
71 }
72
73 pub const fn concurrent(width: usize) -> Self {
74 Self { width }
75 }
76
77 pub const fn unbounded() -> Self {
78 Self { width: usize::MAX }
79 }
80
81 pub(crate) const fn width(self) -> usize {
82 self.width
83 }
84}
85
86impl LaneSet {
87 pub fn declared(entries: impl IntoIterator<Item = (&'static str, Capacity)>) -> Self {
88 Self { entries: entries.into_iter().collect() }
89 }
90
91 pub(crate) fn entries(self) -> Vec<(&'static str, Capacity)> {
92 self.entries
93 }
94
95 pub(crate) fn extend(&mut self, other: Self) {
96 self.entries.extend(other.entries);
97 }
98}
99
100impl Admission {
101 pub(crate) fn name(&self) -> &'static str {
102 self.name
103 }
104
105 pub(crate) fn bounded(&self) -> bool {
106 self.width != usize::MAX
107 }
108
109 pub(crate) fn semaphore(&self) -> Arc<Semaphore> {
110 Arc::clone(&self.semaphore)
111 }
112}
113
114impl Lanes {
115 pub(crate) fn freeze(declared: LaneSet) -> Result<Self, String> {
116 let mut lanes = BTreeMap::from([(
117 RESIDENT,
118 Admission {
119 name: RESIDENT,
120 width: usize::MAX,
121 semaphore: Arc::new(Semaphore::new(Semaphore::MAX_PERMITS)),
122 },
123 )]);
124
125 for (name, capacity) in declared.entries() {
126 if name.is_empty() {
127 return Err("a lane name must not be empty".to_owned());
128 }
129 if capacity.width() == 0 {
130 return Err(format!("lane `{name}` must admit at least one job"));
131 }
132 let admission = Admission {
133 name,
134 width: capacity.width(),
135 semaphore: Arc::new(Semaphore::new(capacity.width().min(Semaphore::MAX_PERMITS))),
136 };
137 if lanes.insert(name, admission).is_some() {
138 return Err(format!("lane `{name}` is declared more than once"));
139 }
140 }
141
142 Ok(Self { lanes })
143 }
144
145 pub(crate) fn get(&self, name: &str) -> Option<Admission> {
146 self.lanes.get(name).cloned()
147 }
148}
149
150