wait_condition.rs 1.75 KB
Newer Older
Jeremy Soller's avatar
Jeremy Soller committed
1
2
use alloc::sync::Arc;
use alloc::vec::Vec;
Jeremy Soller's avatar
Jeremy Soller committed
3
4
use spin::{Mutex, RwLock};

jD91mZM2's avatar
jD91mZM2 committed
5
use crate::context::{self, Context};
Jeremy Soller's avatar
Jeremy Soller committed
6
7
8
9
10
11
12
13
14

#[derive(Debug)]
pub struct WaitCondition {
    contexts: Mutex<Vec<Arc<RwLock<Context>>>>
}

impl WaitCondition {
    pub fn new() -> WaitCondition {
        WaitCondition {
15
            contexts: Mutex::new(Vec::new())
Jeremy Soller's avatar
Jeremy Soller committed
16
17
18
19
        }
    }

    pub fn notify(&self) -> usize {
20
21
22
        let mut contexts = self.contexts.lock();
        let len = contexts.len();
        while let Some(context_lock) = contexts.pop() {
Jeremy Soller's avatar
Jeremy Soller committed
23
24
            context_lock.write().unblock();
        }
25
        len
Jeremy Soller's avatar
Jeremy Soller committed
26
27
    }

28
29
    pub fn wait(&self) -> bool {
        let id;
Jeremy Soller's avatar
Jeremy Soller committed
30
31
32
33
        {
            let context_lock = {
                let contexts = context::contexts();
                let context_lock = contexts.current().expect("WaitCondition::wait: no context");
34
                Arc::clone(&context_lock)
Jeremy Soller's avatar
Jeremy Soller committed
35
36
            };

37
38
39
40
41
            {
                let mut context = context_lock.write();
                id = context.id;
                context.block();
            }
Jeremy Soller's avatar
Jeremy Soller committed
42
43
44

            self.contexts.lock().push(context_lock);
        }
Jeremy Soller's avatar
Jeremy Soller committed
45

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
        unsafe { context::switch(); }

        let mut waited = true;

        {
            let mut contexts = self.contexts.lock();

            let mut i = 0;
            while i < contexts.len() {
                let remove = {
                    let context = contexts[i].read();
                    context.id == id
                };

                if remove {
                    contexts.remove(i);
                    waited = false;
                    break;
                } else {
                    i += 1;
                }
            }
        }

        waited
Jeremy Soller's avatar
Jeremy Soller committed
71
72
73
74
75
76
77
78
    }
}

impl Drop for WaitCondition {
    fn drop(&mut self){
        self.notify();
    }
}