use crate::scheduler;
use lazy_static::lazy_static;
use log::debug;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::time::{Duration, Instant};
lazy_static! {
static ref RUNTIME_STATE: Arc<RuntimeState> = Arc::new(RuntimeState::new());
}
static ACTIVE_GOROUTINES: AtomicUsize = AtomicUsize::new(0);
struct RuntimeState {
active_goroutines: AtomicUsize,
shutdown: AtomicBool,
start_time: Instant,
total_goroutines: AtomicUsize,
}
impl RuntimeState {
fn new() -> Self {
RuntimeState {
active_goroutines: AtomicUsize::new(0),
shutdown: AtomicBool::new(false),
start_time: Instant::now(),
total_goroutines: AtomicUsize::new(0),
}
}
#[allow(dead_code)]
fn inc_goroutine(&self) {
self.active_goroutines.fetch_add(1, Ordering::Relaxed);
self.total_goroutines.fetch_add(1, Ordering::Relaxed);
}
#[allow(dead_code)]
#[inline]
fn dec_goroutine(&self) {
self.active_goroutines.fetch_sub(1, Ordering::Relaxed);
}
fn active_count(&self) -> usize {
self.active_goroutines.load(Ordering::Relaxed)
}
fn total_count(&self) -> usize {
self.total_goroutines.load(Ordering::Relaxed)
}
}
pub struct Runtime;
impl Runtime {
pub fn init() {
debug!("🚀 GoRust Runtime v0.2.0 initialized");
debug!(" GOMAXPROCS={}", num_cpus::get());
scheduler::Scheduler::init();
Self::setup_signal_handler();
}
fn setup_signal_handler() {
let _ = ctrlc::set_handler(|| {
debug!("📡 Received Ctrl-C signal, initiating shutdown...");
scheduler::shutdown();
std::process::exit(0);
});
}
pub fn wait_for_all() {
debug!("⏳ Waiting for all goroutines to complete...");
let start = Instant::now();
let mut last_count = RUNTIME_STATE.active_count();
while RUNTIME_STATE.active_count() > 0 {
let current_count = RUNTIME_STATE.active_count();
if current_count != last_count {
last_count = current_count;
if cfg!(debug_assertions) {
debug!(" Active goroutines: {}", current_count);
}
}
std::thread::sleep(Duration::from_millis(10));
scheduler::yield_now();
}
debug!("✅ All goroutines completed in {:?}", start.elapsed());
}
pub fn shutdown() {
debug!("🛑 GoRust Runtime shutting down");
debug!(
" Total goroutines spawned: {}",
RUNTIME_STATE.total_count()
);
debug!(" Uptime: {:?}", RUNTIME_STATE.start_time.elapsed());
RUNTIME_STATE.shutdown.store(true, Ordering::Relaxed);
scheduler::print_scheduler_stats();
}
pub fn is_shutting_down() -> bool {
RUNTIME_STATE.shutdown.load(Ordering::Relaxed)
}
pub fn total_goroutines() -> usize {
RUNTIME_STATE.total_count()
}
pub fn uptime() -> Duration {
RUNTIME_STATE.start_time.elapsed()
}
#[inline]
pub fn track_goroutine() {
ACTIVE_GOROUTINES.fetch_add(1, Ordering::Relaxed);
}
#[inline]
pub fn untrack_goroutine() {
ACTIVE_GOROUTINES.fetch_sub(1, Ordering::Relaxed);
}
#[inline]
pub fn active_goroutines() -> usize {
ACTIVE_GOROUTINES.load(Ordering::Relaxed)
}
pub fn wait_and_shutdown() {
while Self::active_goroutines() > 0 {
std::thread::yield_now();
}
scheduler::shutdown();
}
}