Gist · 2
/ URL: https://kallithea.mmp.dnsalias.org/_admin/gists/2
Public Gist
drop時にwbが必要っぽい
upgrade時にwbをかければ救えるっポイけどどうなの?
Expires: in 18 days and 4 hours
added file: patch wb fail
patch wb fail
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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | diff --git a/ftllisp-object/src/object/gc.rs b/ftllisp-object/src/object/gc.rs
index aacd60e..1b479bb 100644
--- a/ftllisp-object/src/object/gc.rs
+++ b/ftllisp-object/src/object/gc.rs
@@ -473,10 +473,12 @@ mod test {
use super::{GCManaged, GCManagedWeak, GC};
use crate::object::{RFtlObj, WeakObj};
use crate::vector::VectorObject;
+ use num::FromPrimitive;
use parking_lot::{Mutex, RwLock};
use std::collections::{HashMap, HashSet};
use std::sync::LazyLock;
use std::sync::{Arc, Weak};
+ use std::thread::sleep;
use std::time::{Duration, Instant};
use std::{thread, usize};
@@ -1400,4 +1402,40 @@ mod test {
d.subsec_nanos()
);
}
+
+ #[test]
+ fn test_drop_during_gc() {
+ let _lock = LOCK_GCTEST.lock();
+ // let gc_instance = RFtlObj::gc_instance();
+ RFtlObj::gc_verbose(true);
+ let n = 1000000usize;
+ let mut fr = Vec::with_capacity(n);
+ let mut to = Vec::with_capacity(n);
+ let nil = RFtlObj::nil();
+ for _ in 0..n {
+ let x = RFtlObj::from_usize(n).unwrap().cons(&nil);
+ fr.push(x.cons(&nil));
+ to.push(nil.cons_mut(&nil));
+ }
+ RFtlObj::gc();
+ let to_weak = to.iter().map(|w| w.downgrade()).collect::<Vec<_>>();
+ let handle = thread::spawn(move || {
+ // GC中に長時間処理をシミュレート
+ for i in 0..n {
+ // carを取り出して取り出し元はdropさせる
+ let x = fr.pop().unwrap().car().unwrap();
+ // x.gc_write_barrier();
+ // 取り出したオブジェクトをtoにセットする
+ to[i].set_car(x.clone());
+ }
+ sleep(Duration::from_secs(5));
+ });
+ RFtlObj::gc();
+ assert!(to_weak
+ .iter()
+ .all(|w| w.upgrade().is_some_and(|o| o.car().is_some())));
+ handle.join().unwrap();
+ RFtlObj::gc();
+ RFtlObj::gc_verbose(false);
+ }
}
diff --git a/ftllisp-object/src/object/weak.rs b/ftllisp-object/src/object/weak.rs
index 4c0777c..31182fa 100644
--- a/ftllisp-object/src/object/weak.rs
+++ b/ftllisp-object/src/object/weak.rs
@@ -60,6 +60,14 @@ impl WeakObj {
}
}
+ #[inline]
+ pub fn upgrade_no_wb(&self) -> Option<RFtlObj> {
+ match &self.inner {
+ WeakOrStrong::Weak(w) => w.upgrade().map(|rc| RFtlObj::with_ptr(Pin::new(rc))),
+ WeakOrStrong::Strong(o) => o.clone(),
+ }
+ }
+
/// gc対象の強参照構造体の取得
///
/// GC対象以外はNone
@@ -144,8 +152,8 @@ impl Drop for WeakObj {
impl WeakObj {
/// 強参照に対するマップ処理
#[inline]
- pub fn map_upgrade<R>(&self, f: impl FnOnce(RFtlObj) -> R) -> Option<R> {
- self.upgrade().map(f)
+ pub fn map_upgrade_no_wb<R>(&self, f: impl FnOnce(RFtlObj) -> R) -> Option<R> {
+ self.upgrade_no_wb().map(f)
}
}
@@ -153,13 +161,13 @@ impl RwWeakObj {
/// 強参照の取得
#[inline]
pub fn upgrade(&self) -> Option<RFtlObj> {
- self.with_inner(|w| w.upgrade())
+ self.with_inner(|w| w.upgrade_no_wb())
}
/// 強参照に対するマップ処理
#[inline]
- pub fn map_upgrade<R>(&self, f: impl FnOnce(RFtlObj) -> R) -> Option<R> {
- self.with_inner(|w| w.map_upgrade(f))
+ pub fn map_upgrade_no_wb<R>(&self, f: impl FnOnce(RFtlObj) -> R) -> Option<R> {
+ self.with_inner(|w| w.map_upgrade_no_wb(f))
}
/// 強参照による置換
diff --git a/ftllisp-object/src/pair.rs b/ftllisp-object/src/pair.rs
index 550bce9..3fe5d3b 100644
--- a/ftllisp-object/src/pair.rs
+++ b/ftllisp-object/src/pair.rs
@@ -105,8 +105,8 @@ impl RFtlObj {
#[inline]
fn map_car<U>(&self, f: impl FnOnce(RFtlObj) -> U) -> Option<U> {
match self.as_pair()? {
- Pair::Immutable { car, cdr: _ } => car.map_upgrade(f),
- Pair::Mutable { car, cdr: _ } => car.map_upgrade(f),
+ Pair::Immutable { car, cdr: _ } => car.map_upgrade_no_wb(f),
+ Pair::Mutable { car, cdr: _ } => car.map_upgrade_no_wb(f),
}
}
@@ -119,8 +119,8 @@ impl RFtlObj {
#[inline]
pub fn map_cdr<R>(&self, f: impl FnOnce(RFtlObj) -> R) -> Option<R> {
match self.as_pair()? {
- Pair::Immutable { car: _, cdr } => cdr.map_upgrade(f),
- Pair::Mutable { car: _, cdr } => cdr.map_upgrade(f),
+ Pair::Immutable { car: _, cdr } => cdr.map_upgrade_no_wb(f),
+ Pair::Mutable { car: _, cdr } => cdr.map_upgrade_no_wb(f),
}
}
@@ -134,10 +134,10 @@ impl RFtlObj {
pub fn map_car_and_cdr<R>(&self, f: impl FnOnce(RFtlObj, RFtlObj) -> R) -> Option<R> {
match self.as_pair()? {
Pair::Immutable { car, cdr } => car
- .map_upgrade(|car| cdr.map_upgrade(|cdr| f(car, cdr)))
+ .map_upgrade_no_wb(|car| cdr.map_upgrade_no_wb(|cdr| f(car, cdr)))
.flatten(),
Pair::Mutable { car, cdr } => car
- .map_upgrade(|car| cdr.map_upgrade(|cdr| f(car, cdr)))
+ .map_upgrade_no_wb(|car| cdr.map_upgrade_no_wb(|cdr| f(car, cdr)))
.flatten(),
}
}
diff --git a/ftllisp-object/src/vector.rs b/ftllisp-object/src/vector.rs
index 82ed76d..b3c5751 100644
--- a/ftllisp-object/src/vector.rs
+++ b/ftllisp-object/src/vector.rs
@@ -41,7 +41,7 @@ impl Vector {
#[inline]
fn to_vec(&self) -> VecRFtlObj {
- self.with_inner(|v| v.iter().map(WeakObj::upgrade).collect::<Option<Vec<_>>>())
+ self.with_inner(|v| v.iter().map(WeakObj::upgrade_no_wb).collect::<Option<Vec<_>>>())
.expect("require vector element")
}
}
@@ -201,14 +201,14 @@ impl VectorObject for RFtlObj {
/// フォールバックあり
#[inline]
fn get(&self, i: usize, fallback: impl Into<Option<RFtlObj>>) -> Option<RFtlObj> {
- self.with_inner_vec(|vec| vec.get(i)?.upgrade())
+ self.with_inner_vec(|vec| vec.get(i)?.upgrade_no_wb())
.or_else(|| fallback.into())
}
/// 最終要素取得
#[inline]
fn last(&self) -> Option<RFtlObj> {
- self.with_inner_vec(|vec| vec.last()?.upgrade())
+ self.with_inner_vec(|vec| vec.last()?.upgrade_no_wb())
}
/// 要素設定
@@ -237,7 +237,7 @@ impl VectorObject for RFtlObj {
/// 不変ベクタまたはベクタ以外のオブジェクトの場合panic
#[inline]
fn pop(&self) -> Option<RFtlObj> {
- self.with_inner_vec_mut(|vec| vec.pop())?.upgrade()
+ self.with_inner_vec_mut(|vec| vec.pop())?.upgrade_no_wb()
}
/// リストオブジェクトに変換
|