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::GuardedStack;
|
||||
pub use stack::SliceStack;
|
||||
|
||||
pub use generator::Generator;
|
||||
|
||||
#[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.
|
||||
// Copyright (c) edef <edef@edef.eu>
|
||||
// See the LICENSE file included in this distribution.
|
||||
//! Traits for stacks.
|
||||
|
||||
/// A trait for objects that hold ownership of a 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
|
||||
/// `limit().offset(4096)` will abnormally terminate the program.
|
||||
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.
|
||||
extern crate fringe;
|
||||
|
||||
use fringe::OsStack;
|
||||
use fringe::{OsStack, SliceStack};
|
||||
use fringe::generator::Generator;
|
||||
|
||||
fn new_add_one() -> Generator<i32, i32, OsStack> {
|
||||
|
@ -59,3 +59,19 @@ fn panic_safety() {
|
|||
let mut wrapper = Wrapper { gen: gen };
|
||||
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.
|
||||
extern crate fringe;
|
||||
|
||||
use fringe::{Stack, OsStack};
|
||||
use fringe::{Stack, SliceStack, OsStack};
|
||||
|
||||
#[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();
|
||||
// Make sure the topmost page of the stack, at least, is accessible.
|
||||
unsafe { *(stack.base().offset(-1)) = 0; }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn one_page_stack() {
|
||||
fn one_page_os_stack() {
|
||||
let stack = OsStack::new(4096).unwrap();
|
||||
// Make sure the topmost page of the stack, at least, is accessible.
|
||||
unsafe { *(stack.base().offset(-1)) = 0; }
|
||||
|
|
Loading…
Reference in New Issue