use crate::{
prelude::*,
ruby::{self, VALUE},
};
#[inline]
pub fn start() {
unsafe { ruby::rb_gc_start() };
}
#[inline]
pub fn adjust_mem_usage(diff: isize) {
unsafe { ruby::rb_gc_adjust_memory_usage(diff) };
}
#[inline]
pub fn count() -> usize {
unsafe { ruby::rb_gc_count() }
}
#[inline]
pub fn disable() -> bool {
unsafe { ruby::rb_gc_disable() != 0 }
}
#[inline]
pub fn enable() -> bool {
unsafe { ruby::rb_gc_enable() != 0 }
}
#[inline]
pub fn disabled<F, O>(f: F) -> O
where F: FnOnce() -> O
{
disable();
let output = f();
enable();
output
}
#[inline]
pub unsafe fn force_recycle(obj: impl Object) {
ruby::rb_gc_force_recycle(obj.raw());
}
#[inline]
unsafe fn _stat_unchecked(key: AnyObject) -> usize {
ruby::rb_gc_stat(key.raw())
}
unsafe fn _stat(key: AnyObject) -> Result<usize> {
crate::protected_no_panic(|| _stat_unchecked(key))
}
#[inline]
pub fn stat(key: impl GcInfoKey) -> Result<usize> {
key.stat_gc()
}
#[inline]
pub unsafe fn stat_unchecked(key: impl GcInfoKey) -> usize {
key.stat_gc_unchecked()
}
#[inline]
unsafe fn _latest_info_unchecked(key: AnyObject) -> AnyObject {
AnyObject::from_raw(ruby::rb_gc_latest_gc_info(key.raw()))
}
unsafe fn _latest_info(key: AnyObject) -> Result<AnyObject> {
crate::protected_no_panic(|| _latest_info_unchecked(key))
}
#[inline]
pub fn latest_info(key: impl GcInfoKey) -> Result<AnyObject> {
key.latest_gc_info()
}
#[inline]
pub unsafe fn latest_info_unchecked(key: impl GcInfoKey) -> AnyObject {
key.latest_gc_info_unchecked()
}
#[inline]
pub fn mark(obj: impl Object) {
unsafe { ruby::rb_gc_mark(obj.raw()) };
}
#[inline]
pub fn mark_iter<I, O>(objs: I)
where
I: IntoIterator<Item = O>,
O: Object,
{
objs.into_iter().for_each(mark);
}
#[inline]
pub fn mark_maybe(obj: impl Object) {
unsafe { ruby::rb_gc_mark_maybe(obj.raw()) };
}
#[inline]
pub fn register_mark(obj: impl Object) {
unsafe { ruby::rb_gc_register_mark_object(obj.raw()) };
}
#[inline]
pub fn register(address: &impl Object) {
let address = address as *const _ as *const VALUE as *mut VALUE;
unsafe { ruby::rb_gc_register_address(address) };
}
#[inline]
pub fn unregister(address: &impl Object) {
let address = address as *const _ as *const VALUE as *mut VALUE;
unsafe { ruby::rb_gc_unregister_address(address) };
}
pub trait GcInfoKey: Sized {
#[inline]
fn stat_gc(self) -> Result<usize>;
unsafe fn stat_gc_unchecked(self) -> usize;
#[inline]
fn latest_gc_info(self) -> Result<AnyObject>;
unsafe fn latest_gc_info_unchecked(self) -> AnyObject;
}
impl GcInfoKey for Hash {
#[inline]
fn stat_gc(self) -> Result<usize> {
unsafe { _stat(self.into()) }
}
#[inline]
unsafe fn stat_gc_unchecked(self) -> usize {
_stat_unchecked(self.into())
}
#[inline]
fn latest_gc_info(self) -> Result<AnyObject> {
unsafe { _latest_info(self.into()) }
}
#[inline]
unsafe fn latest_gc_info_unchecked(self) -> AnyObject {
_latest_info_unchecked(self.into())
}
}
impl GcInfoKey for Symbol {
#[inline]
fn stat_gc(self) -> Result<usize> {
unsafe { _stat(self.into()) }
}
#[inline]
unsafe fn stat_gc_unchecked(self) -> usize {
_stat_unchecked(self.into())
}
#[inline]
fn latest_gc_info(self) -> Result<AnyObject> {
unsafe { _latest_info(self.into()) }
}
#[inline]
unsafe fn latest_gc_info_unchecked(self) -> AnyObject {
_latest_info_unchecked(self.into())
}
}
impl GcInfoKey for &str {
#[inline]
fn stat_gc(self) -> Result<usize> {
Symbol::from(self).stat_gc()
}
#[inline]
unsafe fn stat_gc_unchecked(self) -> usize {
Symbol::from(self).stat_gc_unchecked()
}
#[inline]
fn latest_gc_info(self) -> Result<AnyObject> {
Symbol::from(self).latest_gc_info()
}
#[inline]
unsafe fn latest_gc_info_unchecked(self) -> AnyObject {
Symbol::from(self).latest_gc_info_unchecked()
}
}
impl GcInfoKey for String {
#[inline]
fn stat_gc(self) -> Result<usize> {
Symbol::from(self).stat_gc()
}
#[inline]
unsafe fn stat_gc_unchecked(self) -> usize {
Symbol::from(self).stat_gc_unchecked()
}
#[inline]
fn latest_gc_info(self) -> Result<AnyObject> {
Symbol::from(self).latest_gc_info()
}
#[inline]
unsafe fn latest_gc_info_unchecked(self) -> AnyObject {
Symbol::from(self).latest_gc_info_unchecked()
}
}