Skip to content

Commit

Permalink
fix(lib): make Executor thread-safe
Browse files Browse the repository at this point in the history
  • Loading branch information
SaadiSave committed Dec 13, 2024
1 parent 513cab2 commit fd6493a
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 41 deletions.
69 changes: 37 additions & 32 deletions lib/src/exec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ pub use debug::DebugInfo;
///
/// Boxed for convenience.
pub struct Io {
pub read: BufReader<Box<dyn Read>>,
pub write: Box<dyn Write>,
pub read: BufReader<Box<dyn Read + Send + Sync>>,
pub write: Box<dyn Write + Send + Sync>,
}

/// Quickly makes an [`Io`] struct
Expand Down Expand Up @@ -427,34 +427,39 @@ impl Debug for Executor {
}

#[cfg(test)]
#[test]
fn exec() {
use crate::parse;
use std::collections::BTreeMap;

let prog: BTreeMap<usize, ExecInst> = BTreeMap::from(
// Division algorithm from examples/division.pasm
[
(0, ExecInst::new(0, arith::inc, "202".into())),
(1, ExecInst::new(0, arith::add, "203,201".into())),
(2, ExecInst::new(0, cmp::cmp, "203,204".into())),
(3, ExecInst::new(0, cmp::jpn, "0".into())),
(4, ExecInst::new(0, mov::ldd, "202".into())),
(5, ExecInst::new(0, io::end, "".into())),
],
);

let mem: BTreeMap<usize, usize> =
BTreeMap::from([(200, 0), (201, 5), (202, 0), (203, 0), (204, 15)]);

let mut exec = Executor::new(
"None",
prog,
Context::new(Memory::new(mem)),
DebugInfo::default(),
);

exec.exec::<parse::DefaultSet>();

assert_eq!(exec.ctx.acc, 3);
mod tests {
use super::*;

#[test]
fn ensure_send_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<Executor>();
}

#[test]
fn exec() {
let prog =
// Division algorithm from examples/division.pasm
[
(0, ExecInst::new(0, arith::inc, "202".into())),
(1, ExecInst::new(0, arith::add, "203,201".into())),
(2, ExecInst::new(0, cmp::cmp, "203,204".into())),
(3, ExecInst::new(0, cmp::jpn, "0".into())),
(4, ExecInst::new(0, mov::ldd, "202".into())),
(5, ExecInst::new(0, io::end, "".into())),
].into();

let mem = [(200, 0), (201, 5), (202, 0), (203, 0), (204, 15)].into();

let mut exec = Executor::new(
"None",
prog,
Context::new(Memory::new(mem)),
DebugInfo::default(),
);

exec.exec::<crate::parse::DefaultSet>();

assert_eq!(exec.ctx.acc, 3);
}
}
11 changes: 7 additions & 4 deletions lib/test_stdio.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
use std::string::FromUtf8Error;
use std::{io, rc::Rc, sync::RwLock};
use std::{
io,
sync::{Arc, RwLock},
};

#[derive(Clone)]
#[repr(transparent)]
pub struct TestStdio(Rc<RwLock<Vec<u8>>>);
pub struct TestStdio(Arc<RwLock<Vec<u8>>>);

impl TestStdio {
pub fn new(s: impl std::ops::Deref<Target = [u8]>) -> Self {
Self(Rc::new(RwLock::new(s.to_vec())))
Self(Arc::new(RwLock::new(s.to_vec())))
}

pub fn to_vec(&self) -> Vec<u8> {
Expand Down Expand Up @@ -41,7 +44,7 @@ impl io::Read for TestStdio {
if r_lock.is_empty() {
return Err(Error::new(UnexpectedEof, "Input is empty"));
}

buf.write(&r_lock)?
};

Expand Down
12 changes: 7 additions & 5 deletions lib/tests/int_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ include!("../test_stdio.rs");
mod extension {
use super::TestStdio;
use cambridge_asm::parse::Core;
use std::io::Write;

inst! {
ext (ctx) {
Expand Down Expand Up @@ -51,14 +52,15 @@ NONE:

/// Using a completely custom instruction set
mod custom {
use super::TestStdio;
use cambridge_asm::exec::RtError;
use std::io::Write;

use super::TestStdio;
inst! {
from (ctx, op) {
match op {
Fail(from) => writeln!(ctx.io.write, "From {from}").unwrap(),
Null => writeln!(ctx.io.write, "From Pseudoassembly").unwrap(),
Fail(from) => writeln!(ctx.io.write, "From {from}")?,
Null => writeln!(ctx.io.write, "From Pseudoassembly")?,
_ => return Err(RtError::InvalidOperand)
}
}
Expand All @@ -67,8 +69,8 @@ mod custom {
inst! {
greet (ctx, op) {
match op {
Fail(msg) => writeln!(ctx.io.write, "Hello, {msg}!").unwrap(),
Null => writeln!(ctx.io.write, "Hello!").unwrap(),
Fail(msg) => writeln!(ctx.io.write, "Hello, {msg}!")?,
Null => writeln!(ctx.io.write, "Hello!")?,
_ => return Err(RtError::InvalidOperand)
}
}
Expand Down

0 comments on commit fd6493a

Please sign in to comment.