use core::sync::atomic::{AtomicI32, Ordering};

use log::debug;
use system_error::SystemError;

use crate::process::ProcessManager;

use super::wait_queue::WaitQueue;

/// @brief 信号量的结构体
#[derive(Debug)]
struct Semaphore {
    counter: AtomicI32,
    wait_queue: WaitQueue,
}

impl Semaphore {
    #[allow(dead_code)]
    #[inline]
    /// @brief 初始化信号量
    ///
    /// @param count 信号量的初始值
    /// @return 条件满足返回semaphore对象,条件不满足返回err信息
    fn new(counter: i32) -> Result<Self, SystemError> {
        if counter > 0 {
            Ok(Self {
                counter: AtomicI32::new(counter),
                wait_queue: WaitQueue::default(),
            })
        } else {
            return Err(SystemError::EOVERFLOW);
        }
    }

    #[allow(dead_code)]
    #[inline]
    fn down(&self) {
        loop {
            // 尝试占用一个计数
            if self.counter.fetch_sub(1, Ordering::Acquire) > 0 {
                return;
            }

            // 回滚，本次未成功
            self.counter.fetch_add(1, Ordering::Relaxed);

            // 资源不足，阻塞等待计数可用
            let _ = self.wait_queue.wait_event_uninterruptible(
                || self.counter.load(Ordering::Acquire) > 0,
                None::<fn()>,
            );
        }
    }

    #[allow(dead_code)]
    #[inline]
    fn up(&self) {
        // 判断有没有进程在等待资源
        if !self.wait_queue.is_empty() {
            self.counter.fetch_add(1, Ordering::Release);
        } else if !self.wait_queue.wakeup(None) {
            //如果唤醒失败,打印错误信息
            debug!(
                "Semaphore wakeup failed: current pid= {}, semaphore={:?}",
                ProcessManager::current_pcb().raw_pid().into(),
                self
            );
        }
    }
}
