1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#[derive(Debug)]
pub enum AllocPolicy {
NeverRecycle,
RecycleLowest,
}
#[derive(Debug)]
pub enum ReleasePolicy {
DontTrack,
Tracked,
}
pub struct HandleManager {
alloc_policy: AllocPolicy,
release_policy: ReleasePolicy,
highest: usize,
highest_ever: Option<usize>,
freed: Vec<usize>,
}
impl Default for HandleManager {
fn default() -> Self {
HandleManager{
alloc_policy: AllocPolicy::RecycleLowest,
release_policy: ReleasePolicy::DontTrack,
highest: 0,
highest_ever: None,
freed: Vec::with_capacity(0),
}
}
}
impl HandleManager {
pub fn new() -> Self {
Default::default()
}
pub fn with_alloc_policy(mut self, policy: AllocPolicy) -> Self {
if self.highest_ever.is_some() {
panic!("Cannot change allocation policy once handles have been dispensed.")
}
self.alloc_policy = policy;
self
}
pub fn with_release_policy(mut self, policy: ReleasePolicy) -> Self {
if self.highest_ever.is_some() {
panic!("Cannot change release policy once handles have been dispensed.")
}
self.release_policy = policy;
self
}
fn simple_allocate(&mut self) -> Option<usize> {
let result = self.highest;
if result == std::usize::MAX {
None
} else {
self.highest += 1;
self.highest_ever = Some(result);
Some(result)
}
}
pub fn next(&mut self) -> Option<usize> {
match &self.release_policy {
ReleasePolicy::DontTrack => self.simple_allocate(),
ReleasePolicy::Tracked => {
match self.alloc_policy {
AllocPolicy::NeverRecycle => self.simple_allocate(),
AllocPolicy::RecycleLowest => {
if self.freed.len() > 0 {
Some(self.freed.remove(0))
} else {
self.simple_allocate()
}
}
}
}
}
}
pub fn is_used(&self, id: usize) -> bool {
match self.highest_ever {
None => false,
Some(x) => {
match &self.release_policy {
ReleasePolicy::DontTrack => {id <= x},
ReleasePolicy::Tracked => {
if id > x {
return false
}
match self.freed.iter().find(|x| **x == id) {
Some(_) => false,
None => true,
}
},
}
},
}
}
pub fn release(&mut self, handle: usize) -> Result<(),()> {
match &self.release_policy {
ReleasePolicy::DontTrack => Ok(()),
ReleasePolicy::Tracked => {
if self.is_used(handle) {
self.freed.push(handle);
let mut jambojuice = &mut self.freed[..];
jambojuice.sort_unstable();
Ok(())
} else {
Err(())
}
},
}
}
}
#[cfg(test)]
mod test;