libfringe/src/context.rs

64 lines
1.9 KiB
Rust

// 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.
use core::marker::PhantomData;
use void::Void;
use arch::Registers;
use stack;
use debug::StackId;
/// Context is the heart of libfringe.
/// A context represents a saved thread of execution, along with a stack.
/// It can be swapped into and out of with the swap method,
/// and once you're done with it, you can get the stack back through unwrap.
///
/// Every operation is unsafe, because libfringe can't make any guarantees
/// about the state of the context.
#[derive(Debug)]
pub struct Context<'a, Stack: stack::Stack> {
regs: Registers,
_stack_id: StackId,
stack: Stack,
_ref: PhantomData<&'a ()>
}
unsafe impl<'a, Stack> Send for Context<'a, Stack>
where Stack: stack::Stack + Send {}
impl<'a, Stack> Context<'a, Stack> where Stack: stack::Stack {
/// Create a new Context. When it is swapped into,
/// it will call the passed closure.
#[inline]
pub unsafe fn new<F>(mut stack: Stack, f: F) -> Context<'a, Stack>
where F: FnOnce() -> Void + Send + 'a {
let stack_id = StackId::register(&mut stack);
let regs = Registers::new(&mut stack, f);
Context {
regs: regs,
_stack_id: stack_id,
stack: stack,
_ref: PhantomData
}
}
/// Switch to the context, saving the current thread of execution there.
#[inline(always)]
pub unsafe fn swap(&mut self) {
Context::swap2(self, self)
}
/// Switch to in_ctx, saving the current thread of execution to out_ctx.
#[inline(always)]
pub unsafe fn swap2(out_ctx: *mut Context<'a, Stack>, in_ctx: *const Context<'a, Stack>) {
Registers::swap2(&mut (*out_ctx).regs, &(*in_ctx).regs)
}
/// Unwrap the context, returning the stack it contained.
#[inline]
pub unsafe fn unwrap(self) -> Stack {
self.stack
}
}