Created
July 17, 2020 21:01
-
-
Save ekimekim/6a4e09729f5599ba5e7f8b85913f7e5c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Proof of concept for exploring an idea I had with using rust's type system | |
// to manage the di/ei instructions on a Gameboy (if I ever get rust-on-gb working). | |
// It works as follows: We have a zero-sized IntFlag object. It's zero sized | |
// because it is NOT actually maintaining the state. It mediates access to the state | |
// at compile time by being borrowed. | |
// Each function that MAY disable interrupts (either in itself or a child func) must | |
// take a &mut IntFlag. It can then borrow that for an IntDisableGuard, | |
// as long as it releases it before the original borrow's lifetime expires (ie. by returning). | |
mod int_disable { | |
// zero-sized singleton that is borrowed to mediate access | |
// TODO prevent more than 1 of these being constructed | |
pub struct IntFlag; | |
// Guard object that disables interrupts for its lifetime | |
pub struct IntDisableGuard<'a>{ | |
_flag: &'a mut IntFlag | |
} | |
impl IntFlag { | |
// Disables interrupts for the lifetime of the returned IntDisableGuard | |
pub fn disable(&mut self) -> IntDisableGuard { | |
println!("Disabled interrupts"); | |
IntDisableGuard { _flag: self } | |
} | |
} | |
impl<'a> Drop for IntDisableGuard<'a> { | |
fn drop(&mut self) { | |
println!("Enabled interrupts"); | |
} | |
} | |
} | |
fn main() { | |
let mut flag = int_disable::IntFlag{}; | |
middle(&mut flag); | |
} | |
fn middle(flag: &mut int_disable::IntFlag) { | |
disables(flag); | |
{ | |
let guard = flag.disable(); | |
// disables(flag); // does not compile | |
must_be_already_disabled(&guard); | |
releases(guard); | |
} | |
disables(flag); | |
} | |
fn disables(flag: &mut int_disable::IntFlag) { | |
println!("before"); | |
{ | |
let _disabled = flag.disable(); | |
println!("held"); | |
} | |
println!("after"); | |
} | |
fn must_be_already_disabled(_guard: &int_disable::IntDisableGuard) { | |
println!("while disabled"); | |
} | |
fn releases(_guard: int_disable::IntDisableGuard) { | |
println!("releasing"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment