#![allow(dead_code)]
use std::sync::Mutex as StdMutex;
use catallaxy_gc::{enter_native, install, leave_native, register_thread, unregister_thread, RootSource, Tracer};
use catallaxy_runtime::ops::Interop;
use catallaxy_runtime::{Mutator, RtResult, Sym, Value};
pub struct Host {
raw: *mut Mutator,
pub m: &'static mut Mutator,
finished: bool,
}
struct HandleRoots(*const Vec<Value>);
impl RootSource for HandleRoots {
fn trace_roots(&self, t: &mut Tracer) {
for &v in unsafe { &*self.0 } {
if v.is_ptr() {
t.mark(v.as_ptr());
}
}
}
}
impl Interop for Host {
fn mutator(&mut self) -> &mut Mutator {
self.m
}
fn call_method(&mut self, _: Value, _: Sym, _: &[Value]) -> RtResult<Option<Value>> {
Ok(None)
}
}
impl Host {
pub fn new() -> Self {
let rec = register_thread();
let raw = Box::into_raw(Box::new(Mutator::new(rec)));
let roots: Box<dyn RootSource> = Box::new(HandleRoots(unsafe { (*raw).handles_ptr() }));
let m = unsafe { &mut *raw };
unsafe { install(&m.rec, Box::into_raw(roots), m.heap_ptr()) };
leave_native(&m.rec);
Host { raw, m, finished: false }
}
pub fn gc(&mut self) {
catallaxy_gc::collect_now(&self.m.rec);
}
pub fn minor(&mut self) {
catallaxy_gc::collect_minor(&self.m.rec);
}
pub fn finish(mut self) {
self.unregister();
}
fn unregister(&mut self) {
if std::mem::replace(&mut self.finished, true) {
return;
}
enter_native(&self.m.rec);
unregister_thread(&self.m.rec);
self.m.release_pages();
let _ = self.raw;
}
}
impl Drop for Host {
fn drop(&mut self) {
self.unregister();
}
}
pub static SERIAL: StdMutex<()> = StdMutex::new(());
pub fn n(i: usize) -> usize {
if cfg!(miri) {
(i / 50).max(3)
} else {
i
}
}