//! Runtime, driver, async I/O, and channel primitives for RUIN.
//!
//! The crate is centered around a single-threaded event loop with explicit worker threads,
//! JavaScript-style microtask/macrotask scheduling and platform-specific async I/O backends.
//!
//! Most users will start with:
//!
//! - [`main`] or [`async_main`] for executable entry points
//! - [`run`], [`queue_task`], [`queue_microtask`], and [`queue_future`] for event-loop work
//! - [`fs`], [`net`], [`time`], and [`channel`] for async runtime services
//!
//! # Platform support
//!
//! `ruin-runtime` currently targets:
//! - Linux `x86_64`
//! - macOS `aarch64`
//!
//! RUIN runtime foundations.
//!
//! This crate provides a platform runtime substrate with a single-threaded runtime loop and
//! worker-thread task forwarding.

#![feature(thread_local)]

#[cfg(not(any(
    all(target_os = "linux", target_arch = "x86_64"),
    all(target_os = "macos", target_arch = "aarch64")
)))]
compile_error!("ruin-runtime currently supports Linux x86_64 and macOS aarch64.");

extern crate alloc;

pub(crate) mod trace_targets {
    pub const DRIVER: &str = "ruin_runtime::driver";
    pub const RUNTIME: &str = "ruin_runtime::runtime";
    pub const SCHEDULER: &str = "ruin_runtime::scheduler";

    #[cfg(debug_assertions)]
    pub const TIMER: &str = "ruin_runtime::timer";
    #[cfg(debug_assertions)]
    pub const ASYNC: &str = "ruin_runtime::async";
}

pub mod channel;
pub mod fd;
pub mod fs;
pub mod net;
#[doc(hidden)]
pub mod op;
#[doc(hidden)]
pub mod platform;
pub mod stdio;
#[doc(hidden)]
pub mod sys;
pub mod time;

/// Marks an `async fn main()` as the runtime entry point.
///
/// The macro generates a real Rust `main` that queues the returned future onto the main runtime
/// thread before calling [`run`].
pub use ruin_runtime_proc_macros::async_main;
/// Marks a synchronous `fn main()` as the runtime entry point.
///
/// The macro generates a real Rust `main` that queues the function body onto the main runtime
/// thread before calling [`run`].
pub use ruin_runtime_proc_macros::main;

/// Driver primitives re-exported from the active backend.
#[cfg(any(
    all(target_os = "linux", target_arch = "x86_64"),
    all(target_os = "macos", target_arch = "aarch64")
))]
pub use platform::current::driver::{
    Driver, ReadyEvents, ThreadNotifier, create, create_driver, monotonic_now,
};
/// Runtime/event-loop primitives re-exported from the active backend.
#[cfg(any(
    all(target_os = "linux", target_arch = "x86_64"),
    all(target_os = "macos", target_arch = "aarch64")
))]
pub use platform::current::runtime::{
    IntervalHandle, JoinHandle, ThreadHandle, TimeoutHandle, WorkerHandle, clear_interval,
    clear_timeout, current_thread_handle, queue_future, queue_microtask, queue_task, run,
    run_ready_tasks, run_until_stalled, set_interval, set_timeout, spawn_worker, yield_now,
};
/// Public mesh-allocator surface re-exported from the Linux x86_64 backend.
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub use platform::linux_x86_64::mesh_alloc::{
    ActiveMeshGuard, Arena, AtomicBitmap, BitIter, CLASS_TO_SIZE, CompactionAdvice,
    CompactionEstimate, CompactionRecommendation, CompactionSkipReason,
    DEFAULT_GLOBAL_MINIHEAP_CAPACITY, FutexMutex, GlobalMeshAllocator, MeshAllocator, MeshStats,
    MiniHeap, MiniHeapFlags, MiniHeapId, Mwc, Mwc64, NUM_SIZE_CLASSES, PageConfig, PlatformHooks,
    PlatformInstallError, RelaxedBitmap, RuntimeCompactionPolicy, RuntimeCompactionResult,
    ShuffleEntry, ShuffleVector, Span, ThreadLocalHeap, byte_size_for_class,
    ensure_fault_mediation_installed, install_platform_hooks, ok_to_proceed, page_count,
    page_shift, page_size, retry_on_efault, retry_on_efault_ptrs, round_up_to_page,
    runtime_slots_per_span, size_class_for,
};
/// Additional allocator helpers re-exported from the Linux x86_64 backend.
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub use platform::linux_x86_64::mesh_alloc::{FreelistId, bitmaps_meshable};

/// Returns the default global mesh allocator configuration for this crate.
///
/// This is useful when embedding the allocator in a `#[global_allocator]` static.
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub const fn default_global_allocator() -> GlobalMeshAllocator {
    GlobalMeshAllocator::with_default_config()
}

#[cfg(test)]
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
mod tests {
    use super::{MeshAllocator, page_size};

    #[test]
    fn mesh_allocator_smoke_test() {
        let mut allocator =
            MeshAllocator::new(page_size() * 1024, 256).expect("allocator should initialize");

        let small = allocator
            .allocate(64)
            .expect("small allocation should succeed");
        unsafe {
            small.write_bytes(0xAB, 64);
        }
        allocator.deallocate(small);

        let large_size = page_size() * 2;
        let large = allocator
            .allocate(large_size)
            .expect("large allocation should succeed");
        unsafe {
            large.write_bytes(0xCD, large_size);
        }
        allocator.deallocate(large);
    }
}
