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
use crate::{WeakArena, Arena, UploadError, DropFn};
use std::ptr::null_mut;
pub struct DropItem {
pub fun: DropFn,
pub data: *const u8,
pub next: *mut DropItem,
}
impl DropItem {
#[inline(always)]
pub unsafe fn execute(&self) {
(self.fun)(self.data);
}
}
struct NMetadata<T> {
value: T,
outlives: *mut DropItem,
}
impl<T> Drop for NMetadata<T> {
fn drop(&mut self) {
let mut outlives = self.outlives;
self.outlives = null_mut();
while outlives != null_mut() {
trace!("drop outlives");
unsafe {
(*outlives).execute();
let next = (*outlives).next;
(*outlives).next = null_mut();
outlives = next;
}
}
trace!("drop NMetadata");
}
}
pub struct N<T> {
_arena: WeakArena,
_ptr: *mut NMetadata<T>,
}
impl<T> N<T> {
pub fn new(arena: &Arena, value: T) -> Result<N<T>, UploadError> {
let wrapped = NMetadata { value, outlives: null_mut() };
let (item_ptr, _) = unsafe { arena.upload_auto_drop(wrapped)? };
Ok(N {
_arena: arena.to_weak_arena(),
_ptr: item_ptr,
})
}
pub fn expect(&self, message: &str) -> (Arena, &T) {
if let Some(arena) = self._arena.arena() {
(arena, &unsafe { std::mem::transmute::<*mut NMetadata<T>, &NMetadata<T>>(self._ptr) }.value)
} else {
panic!("{}", message);
}
}
pub fn val(&self) -> Option<&T> {
if self._arena.is_alive() {
Some(&unsafe { std::mem::transmute::<*mut NMetadata<T>, &NMetadata<T>>(self._ptr) }.value)
} else {
None
}
}
pub fn expect_mut(&self, message: &str) -> (Arena, &mut T) {
if let Some(arena) = self._arena.arena() {
(arena, &mut unsafe { std::mem::transmute::<*mut NMetadata<T>, &mut NMetadata<T>>(self._ptr) }.value)
} else {
panic!("{}", message);
}
}
pub fn var(&mut self) -> Option<&mut T> {
if self._arena.is_alive() {
Some(&mut unsafe { std::mem::transmute::<*mut NMetadata<T>, &mut NMetadata<T>>(self._ptr) }.value)
} else {
None
}
}
pub fn outlives<O>(&self, value: O) -> Result<N<O>, UploadError> {
match self._arena.arena() {
None => Err(UploadError::ArenaIsNotAlive),
Some(arena) => {
let wrapped = NMetadata { value, outlives: null_mut() };
let o_wrapper_ptr = unsafe { arena.upload_no_drop(wrapped)? };
let md = unsafe { std::mem::transmute::<*mut NMetadata<T>, &mut NMetadata<T>>(self._ptr) };
let drop_item = unsafe { arena.upload_no_drop(DropItem {
fun: |data| {
trace!("drop closure {:?}", data);
let o_ref = std::mem::transmute::<*const u8, &NMetadata<O>>(data);
let o = std::mem::transmute_copy::<NMetadata<O>, NMetadata<O>>(o_ref);
std::mem::drop(o);
},
data: o_wrapper_ptr as *const u8,
next: null_mut(),
}) }?;
if md.outlives == null_mut() {
md.outlives = drop_item;
} else { unsafe {
(*drop_item).next = md.outlives;
md.outlives = drop_item;
} }
Ok(N {
_arena: self._arena.clone(),
_ptr: o_wrapper_ptr,
})
},
}
}
}