1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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
71
72
73
74
75
76
77
78
79
80
use std::sync::{RwLock, Once};
use crate::gc::LocalGarbageCollector;
use crate::gc::sync::GlobalGarbageCollector;
use std::{thread, time};

use std::thread::JoinHandle;

use std::sync::atomic::{AtomicBool, Ordering};

lazy_static! {
    pub static ref BASIC_STRATEGY_LOCAL_GCS: RwLock<Vec<&'static LocalGarbageCollector>> = {
        RwLock::new(Vec::new())
    };
    pub static ref BASIC_STRATEGY_GLOBAL_GC: RwLock<Option<&'static GlobalGarbageCollector>> = {
        RwLock::new(None)
    };
    pub static ref APPLICATION_ACTIVE: AtomicBool = {
        AtomicBool::new(true)
    };
    pub static ref BACKGROUND_THREADS: RwLock<Vec<JoinHandle<()>>> = {
        RwLock::new(Vec::new())
    };
}
static START_BASIC_GC_STRATEGY: Once = Once::new();

pub struct ApplicationCleanup;
impl Drop for ApplicationCleanup {
    fn drop(&mut self) {
        let app_active = &(*APPLICATION_ACTIVE);
        app_active.store(false, Ordering::Release);
        let mut bthreads = (&*BACKGROUND_THREADS).write().unwrap();
        while (*bthreads).len() > 0 {
            let bthread = (*bthreads).pop().unwrap();
            bthread.join();
        }
    }
}

pub fn basic_gc_strategy_start() {
    START_BASIC_GC_STRATEGY.call_once(|| {
        let bthreads = &(*BACKGROUND_THREADS);
        bthreads.write().unwrap().push(
            thread::spawn(move || {
                let app_active = &(*APPLICATION_ACTIVE);
                while app_active.load(Ordering::Acquire) {
                    let ten_secs = time::Duration::from_millis(500);
                    thread::sleep(ten_secs);
                    {
                        if let Some(global_gc) = *(*BASIC_STRATEGY_GLOBAL_GC).read().unwrap() {
                            unsafe {
                                global_gc.collect();
                            }
                        }
                    }
                    {
                        let local_gcs_read_guard = (*BASIC_STRATEGY_LOCAL_GCS).read().unwrap();
                        let local_gcs = &(*local_gcs_read_guard);
                        unsafe {
                            for local_gc in local_gcs.into_iter() {
                                local_gc.collect();
                            }
                        }
                    }
                }
                if let Some(global_gc) = *(*BASIC_STRATEGY_GLOBAL_GC).read().unwrap() {
                    unsafe {
                        global_gc.collect();
                    }
                }
                let local_gcs_read_guard = (*BASIC_STRATEGY_LOCAL_GCS).read().unwrap();
                let local_gcs = &(*local_gcs_read_guard);
                unsafe {
                    for local_gc in local_gcs.into_iter() {
                        local_gc.collect();
                    }
                }
            })
        );
    });
}