forked from M-Labs/libfringe
Implement SliceStack.
This commit is contained in:
parent
e0ad79ea0c
commit
f8cf95f686
|
@ -27,6 +27,8 @@ extern crate std;
|
||||||
|
|
||||||
pub use stack::Stack;
|
pub use stack::Stack;
|
||||||
pub use stack::GuardedStack;
|
pub use stack::GuardedStack;
|
||||||
|
pub use stack::SliceStack;
|
||||||
|
|
||||||
pub use generator::Generator;
|
pub use generator::Generator;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
|
20
src/stack.rs
20
src/stack.rs
|
@ -1,7 +1,6 @@
|
||||||
// This file is part of libfringe, a low-level green threading library.
|
// This file is part of libfringe, a low-level green threading library.
|
||||||
// Copyright (c) edef <edef@edef.eu>
|
// Copyright (c) edef <edef@edef.eu>
|
||||||
// See the LICENSE file included in this distribution.
|
// See the LICENSE file included in this distribution.
|
||||||
//! Traits for stacks.
|
|
||||||
|
|
||||||
/// A trait for objects that hold ownership of a stack.
|
/// A trait for objects that hold ownership of a stack.
|
||||||
pub trait Stack {
|
pub trait Stack {
|
||||||
|
@ -20,3 +19,22 @@ pub trait Stack {
|
||||||
/// A guarded stack must guarantee that any access of data at addresses `limit()` to
|
/// A guarded stack must guarantee that any access of data at addresses `limit()` to
|
||||||
/// `limit().offset(4096)` will abnormally terminate the program.
|
/// `limit().offset(4096)` will abnormally terminate the program.
|
||||||
pub unsafe trait GuardedStack {}
|
pub unsafe trait GuardedStack {}
|
||||||
|
|
||||||
|
/// SliceStack holds a non-guarded stack allocated elsewhere and provided as a mutable
|
||||||
|
/// slice.
|
||||||
|
pub struct SliceStack<'a>(pub &'a mut [u8]);
|
||||||
|
|
||||||
|
impl<'a> Stack for SliceStack<'a> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn base(&self) -> *mut u8 {
|
||||||
|
// The slice cannot wrap around the address space, so the conversion from usize
|
||||||
|
// to isize will not wrap either.
|
||||||
|
let len: isize = self.0.len() as isize;
|
||||||
|
unsafe { self.limit().offset(len) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn limit(&self) -> *mut u8 {
|
||||||
|
self.0.as_ptr() as *mut u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// See the LICENSE file included in this distribution.
|
// See the LICENSE file included in this distribution.
|
||||||
extern crate fringe;
|
extern crate fringe;
|
||||||
|
|
||||||
use fringe::OsStack;
|
use fringe::{OsStack, SliceStack};
|
||||||
use fringe::generator::Generator;
|
use fringe::generator::Generator;
|
||||||
|
|
||||||
fn new_add_one() -> Generator<i32, i32, OsStack> {
|
fn new_add_one() -> Generator<i32, i32, OsStack> {
|
||||||
|
@ -59,3 +59,19 @@ fn panic_safety() {
|
||||||
let mut wrapper = Wrapper { gen: gen };
|
let mut wrapper = Wrapper { gen: gen };
|
||||||
wrapper.gen.resume(());
|
wrapper.gen.resume(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn with_slice_stack() {
|
||||||
|
let mut memory = [0; 1024];
|
||||||
|
let stack = SliceStack(&mut memory);
|
||||||
|
let mut add_one = unsafe {
|
||||||
|
Generator::unsafe_new(stack, move |yielder, mut input| {
|
||||||
|
loop {
|
||||||
|
if input == 0 { break }
|
||||||
|
input = yielder.generate(input + 1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
assert_eq!(add_one.resume(1), Some(2));
|
||||||
|
assert_eq!(add_one.resume(2), Some(3));
|
||||||
|
}
|
||||||
|
|
|
@ -3,17 +3,24 @@
|
||||||
// See the LICENSE file included in this distribution.
|
// See the LICENSE file included in this distribution.
|
||||||
extern crate fringe;
|
extern crate fringe;
|
||||||
|
|
||||||
use fringe::{Stack, OsStack};
|
use fringe::{Stack, SliceStack, OsStack};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_stack() {
|
fn slice_stack() {
|
||||||
|
let mut memory = [0; 1024];
|
||||||
|
let stack = SliceStack(&mut memory);
|
||||||
|
assert_eq!(stack.base() as isize - stack.limit() as isize, 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_os_stack() {
|
||||||
let stack = OsStack::new(0).unwrap();
|
let stack = OsStack::new(0).unwrap();
|
||||||
// Make sure the topmost page of the stack, at least, is accessible.
|
// Make sure the topmost page of the stack, at least, is accessible.
|
||||||
unsafe { *(stack.base().offset(-1)) = 0; }
|
unsafe { *(stack.base().offset(-1)) = 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn one_page_stack() {
|
fn one_page_os_stack() {
|
||||||
let stack = OsStack::new(4096).unwrap();
|
let stack = OsStack::new(4096).unwrap();
|
||||||
// Make sure the topmost page of the stack, at least, is accessible.
|
// Make sure the topmost page of the stack, at least, is accessible.
|
||||||
unsafe { *(stack.base().offset(-1)) = 0; }
|
unsafe { *(stack.base().offset(-1)) = 0; }
|
||||||
|
|
Loading…
Reference in New Issue