-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathexercise_10_3_2.rs
107 lines (81 loc) · 2.37 KB
/
exercise_10_3_2.rs
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
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Handle(usize);
enum Slot<T> {
Free(Handle),
Occupied(T),
}
const NIL: Handle = Handle(usize::MAX);
pub struct ObjectPool<T> {
memory: Vec<Slot<T>>,
free: Handle,
}
impl<T> Default for ObjectPool<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> ObjectPool<T> {
#[must_use]
pub fn new() -> Self {
Self {
memory: Vec::new(),
free: NIL,
}
}
pub fn allocate_object(&mut self, value: T) -> Handle {
if self.free == NIL {
// We have more space!
let x = self.memory.len();
self.memory.push(Slot::Occupied(value));
Handle(x)
} else {
let x = self.free;
if let Slot::Free(next_handle) = self.memory[self.free.0] {
self.free = next_handle;
} else {
unreachable!();
}
self.memory[x.0] = Slot::Occupied(value);
x
}
}
pub fn free_object(&mut self, x: Handle) {
self.memory[x.0] = Slot::Free(self.free);
self.free = x;
}
#[must_use]
pub fn get(&self, handle: Handle) -> Option<&T> {
if let Slot::Occupied(value) = &self.memory[handle.0] {
Some(value)
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use super::ObjectPool;
#[test]
fn test_object_pool_allocate() {
let mut pool = ObjectPool::new();
let handle_1 = pool.allocate_object(42);
assert_eq!(pool.get(handle_1).copied(), Some(42));
let handle_2 = pool.allocate_object(7);
assert_eq!(pool.get(handle_1).copied(), Some(42));
assert_eq!(pool.get(handle_2).copied(), Some(7));
let handle_3 = pool.allocate_object(8);
assert_eq!(pool.get(handle_1).copied(), Some(42));
assert_eq!(pool.get(handle_2).copied(), Some(7));
assert_eq!(pool.get(handle_3).copied(), Some(8));
}
#[test]
fn test_object_pool_free() {
let mut pool = ObjectPool::new();
let handle_1 = pool.allocate_object(3);
let handle_2 = pool.allocate_object(5);
pool.free_object(handle_1);
let handle_3 = pool.allocate_object(7);
assert_eq!(pool.get(handle_2).copied(), Some(5));
assert_eq!(pool.get(handle_3).copied(), Some(7));
}
}