use std::ops::{Deref, DerefMut};
use parking_lot::{const_rwlock, RwLock, RwLockReadGuard, RwLockWriteGuard};
use crate::boxed::ZBox;
use crate::ffi::{_zend_executor_globals, ext_php_rs_executor_globals};
use crate::types::{ZendHashTable, ZendObject};
pub type ExecutorGlobals = _zend_executor_globals;
impl ExecutorGlobals {
pub fn get() -> GlobalReadGuard<Self> {
let globals = unsafe { ext_php_rs_executor_globals().as_ref() }
.expect("Static executor globals were invalid");
let guard = GLOBALS_LOCK.read();
GlobalReadGuard { globals, guard }
}
fn get_mut() -> GlobalWriteGuard<Self> {
let globals = unsafe { ext_php_rs_executor_globals().as_mut() }
.expect("Static executor globals were invalid");
let guard = GLOBALS_LOCK.write();
GlobalWriteGuard { globals, guard }
}
pub fn class_table(&self) -> Option<&ZendHashTable> {
unsafe { self.class_table.as_ref() }
}
pub fn take_exception() -> Option<ZBox<ZendObject>> {
let mut globals = Self::get_mut();
let mut exception_ptr = std::ptr::null_mut();
std::mem::swap(&mut exception_ptr, &mut globals.exception);
Some(unsafe { ZBox::from_raw(exception_ptr.as_mut()?) })
}
}
static GLOBALS_LOCK: RwLock<()> = const_rwlock(());
pub struct GlobalReadGuard<T: 'static> {
globals: &'static T,
#[allow(dead_code)]
guard: RwLockReadGuard<'static, ()>,
}
impl<T> Deref for GlobalReadGuard<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.globals
}
}
pub struct GlobalWriteGuard<T: 'static> {
globals: &'static mut T,
#[allow(dead_code)]
guard: RwLockWriteGuard<'static, ()>,
}
impl<T> Deref for GlobalWriteGuard<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.globals
}
}
impl<T> DerefMut for GlobalWriteGuard<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.globals
}
}