// This file is part of libfringe, a low-level green threading library. // Copyright (c) edef , // whitequark // See the LICENSE file included in this distribution. use stack; use debug; use arch; /// 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 { stack: Stack, stack_id: debug::StackId, stack_ptr: arch::StackPointer } unsafe impl Send for Context where Stack: stack::Stack + Send {} impl Context where Stack: stack::Stack { /// Create a new Context. When it is swapped into, it will call /// `f(arg)`, where `arg` is the argument passed to `swap`. pub unsafe fn new(stack: Stack, f: unsafe extern "C" fn(usize) -> !) -> Context { let stack_id = debug::StackId::register(&stack); let stack_ptr = arch::init(&stack, f); Context { stack: stack, stack_id: stack_id, stack_ptr: stack_ptr } } /// Unwrap the context, returning the stack it contained. pub unsafe fn unwrap(self) -> Stack { self.stack } } impl Context where OldStack: stack::Stack { /// Switch to in_ctx, saving the current thread of execution to out_ctx. #[inline(always)] pub unsafe fn swap(old_ctx: *mut Context, new_ctx: *const Context, arg: usize) -> usize where NewStack: stack::Stack { arch::swap(arg, &mut (*old_ctx).stack_ptr, &(*new_ctx).stack_ptr) } }