Skip to content

Commit 6122c6a

Browse files
committed
📝 impl generator into_raw/from_raw
1 parent 302c996 commit 6122c6a

File tree

3 files changed

+54
-19
lines changed

3 files changed

+54
-19
lines changed

src/gen_impl.rs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,35 @@ pub struct Generator<'a, A, T> {
2626
gen: ManuallyDrop<StackBox<GeneratorImpl<'a, A, T>>>,
2727
}
2828

29+
unsafe impl<A, T> Send for Generator<'static, A, T> {}
30+
31+
impl<'a, A, T> Generator<'a, A, T> {
32+
/// Constructs a Generator from a raw pointer.
33+
///
34+
/// # Safety
35+
///
36+
/// This function is unsafe because improper use may lead to
37+
/// memory problems. For example, a double-free may occur if the
38+
/// function is called twice on the same raw pointer.
39+
#[inline]
40+
pub unsafe fn from_raw(raw: *mut usize) -> Self {
41+
let g = StackBox::from_raw(raw as *mut GeneratorImpl<'a, A, T>);
42+
let stack_ptr = raw.offset(g.size() as isize + 2);
43+
Generator {
44+
_stack: StackBox::from_raw(stack_ptr as *mut Stack),
45+
gen: ManuallyDrop::new(g),
46+
}
47+
}
48+
49+
/// Consumes the `Generator`, returning a wrapped raw pointer.
50+
#[inline]
51+
pub fn into_raw(g: Generator<'a, A, T>) -> *mut usize {
52+
let ret = g.gen.as_ptr() as *mut usize;
53+
std::mem::forget(g);
54+
ret
55+
}
56+
}
57+
2958
impl<'a, A, T> std::ops::Deref for Generator<'a, A, T> {
3059
type Target = GeneratorImpl<'a, A, T>;
3160

@@ -66,7 +95,7 @@ impl<'a, A, T> fmt::Debug for Generator<'a, A, T> {
6695
}
6796
}
6897

69-
impl<'a, A, T> std::ops::Drop for Generator<'a, A, T> {
98+
impl<'a, A, T> Drop for Generator<'a, A, T> {
7099
fn drop(&mut self) {
71100
unsafe { ManuallyDrop::drop(&mut self.gen) }
72101
}
@@ -99,8 +128,8 @@ impl<A> Gn<A> {
99128
let mut g = GeneratorImpl::<A, T>::new(&mut stack);
100129
g.scoped_init(f);
101130
Generator {
102-
gen: ManuallyDrop::new(g),
103131
_stack: stack,
132+
gen: ManuallyDrop::new(g),
104133
}
105134
}
106135
}
@@ -127,8 +156,8 @@ impl<A: Any> Gn<A> {
127156
g.init_context();
128157
g.init_code(f);
129158
Generator {
130-
gen: ManuallyDrop::new(g),
131159
_stack: stack,
160+
gen: ManuallyDrop::new(g),
132161
}
133162
}
134163
}
@@ -148,8 +177,6 @@ pub struct GeneratorImpl<'a, A, T> {
148177
phantom: PhantomData<&'a T>,
149178
}
150179

151-
unsafe impl<A, T> Send for GeneratorImpl<'static, A, T> {}
152-
153180
impl<'a, A: Any, T: Any> GeneratorImpl<'a, A, T> {
154181
/// create a new generator with default stack size
155182
fn init_context(&mut self) {

src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ mod yield_;
2626
pub use crate::gen_impl::{Generator, Gn};
2727
pub use crate::rt::{get_local_data, is_generator, Error};
2828
pub use crate::scope::Scope;
29-
pub use crate::stack::StackBox;
3029
pub use crate::yield_::{
3130
co_get_yield, co_set_para, co_yield_with, done, get_yield, yield_, yield_from, yield_with,
3231
};

src/stack/mod.rs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,16 @@ impl<T> StackBox<T> {
7171
ptr::write(self.ptr.as_ptr(), data);
7272
}
7373

74+
// get the stack ptr
75+
pub(crate) fn as_ptr(&self) -> *mut T {
76+
self.ptr.as_ptr()
77+
}
78+
79+
// get the stack ptr
80+
pub(crate) fn size(&self) -> usize {
81+
self.get_header().data_size
82+
}
83+
7484
/// Constructs a StackBox from a raw pointer.
7585
///
7686
/// # Safety
@@ -79,40 +89,40 @@ impl<T> StackBox<T> {
7989
/// memory problems. For example, a double-free may occur if the
8090
/// function is called twice on the same raw pointer.
8191
#[inline]
82-
pub unsafe fn from_raw(raw: *mut T) -> Self {
92+
pub(crate) unsafe fn from_raw(raw: *mut T) -> Self {
8393
StackBox {
8494
ptr: ptr::NonNull::new_unchecked(raw),
8595
}
8696
}
8797

88-
/// Consumes the `StackBox`, returning a wrapped raw pointer.
89-
#[inline]
90-
pub fn into_raw(b: StackBox<T>) -> *mut T {
91-
let ret = b.ptr.as_ptr();
92-
std::mem::forget(b);
93-
ret
94-
}
98+
// Consumes the `StackBox`, returning a wrapped raw pointer.
99+
// #[inline]
100+
// pub(crate) fn into_raw(b: StackBox<T>) -> *mut T {
101+
// let ret = b.ptr.as_ptr();
102+
// std::mem::forget(b);
103+
// ret
104+
// }
95105
}
96106

97107
pub struct Func {
98108
data: *mut (),
99109
size: usize,
100110
offset: *mut usize,
101-
is_called: bool,
102111
func: fn(*mut ()),
103112
drop: fn(*mut ()),
104113
}
105114

106115
impl Func {
107116
pub fn call_once(mut self) {
108-
(self.func)(self.data);
109-
self.is_called = true;
117+
let data = self.data;
118+
self.data = ptr::null_mut();
119+
(self.func)(data);
110120
}
111121
}
112122

113123
impl Drop for Func {
114124
fn drop(&mut self) {
115-
if !self.is_called {
125+
if !self.data.is_null() {
116126
(self.drop)(self.data);
117127
}
118128
unsafe { *self.offset -= self.size }
@@ -145,7 +155,6 @@ impl<F: FnOnce()> StackBox<F> {
145155
data: d.ptr.as_ptr() as *mut (),
146156
size: header.data_size + HEADER_SIZE,
147157
offset: header.offset,
148-
is_called: false,
149158
func: Self::call_once,
150159
drop: Self::drop_inner,
151160
};

0 commit comments

Comments
 (0)