1use core::ops::Deref;
4
5use alloc::{collections::btree_map::BTreeMap, sync::Arc};
6use axsync::Mutex;
7use axtask::{TaskExtRef, WaitQueue, current};
8
9pub struct FutexTable(Mutex<BTreeMap<usize, Arc<WaitQueue>>>);
11impl FutexTable {
12 pub fn new() -> Self {
14 Self(Mutex::new(BTreeMap::new()))
15 }
16
17 pub fn get(&self, addr: usize) -> Option<WaitQueueGuard> {
19 let wq = self.0.lock().get(&addr).cloned()?;
20 Some(WaitQueueGuard {
21 key: addr,
22 inner: wq,
23 })
24 }
25
26 pub fn get_or_insert(&self, addr: usize) -> WaitQueueGuard {
29 let mut table = self.0.lock();
30 let wq = table
31 .entry(addr)
32 .or_insert_with(|| Arc::new(WaitQueue::new()));
33 WaitQueueGuard {
34 key: addr,
35 inner: wq.clone(),
36 }
37 }
38}
39
40#[doc(hidden)]
41pub struct WaitQueueGuard {
42 key: usize,
43 inner: Arc<WaitQueue>,
44}
45impl Deref for WaitQueueGuard {
46 type Target = Arc<WaitQueue>;
47
48 fn deref(&self) -> &Self::Target {
49 &self.inner
50 }
51}
52impl Drop for WaitQueueGuard {
53 fn drop(&mut self) {
54 let curr = current();
55 let mut table = curr.task_ext().process_data().futex_table.0.lock();
56 if Arc::strong_count(&self.inner) == 1 && self.inner.is_empty() {
57 table.remove(&self.key);
58 }
59 }
60}