3.3 - אתחול חלקי ופעולות זיכרון גולמיות - פתרון
פתרון שימוש חוזר במסלול ההוצאה¶
המתודה clear משתמשת ב־pop כדי להסיר את הערך מן הטווח החי לפני השמדתו. כך גם אם destructor נכשל, הערך שכבר הוצא לא ייחשב שוב בבעלות הבאפר.
הוסיפו למימוש Buffer מן ההרצאה:
impl<T, const N: usize> Buffer<T, N> {
fn clear(&mut self) {
while let Some(value) = self.pop() {
drop(value);
}
}
}
השתמשו ב־main הבא לאחר הגדרת Buffer:
use std::cell::Cell;
use std::rc::Rc;
struct Tracked(Rc<Cell<usize>>);
impl Drop for Tracked {
fn drop(&mut self) { self.0.set(self.0.get() + 1); }
}
fn main() {
let drops = Rc::new(Cell::new(0));
let mut buffer = Buffer::<Tracked, 3>::new();
for _ in 0..3 {
assert!(buffer.push(Tracked(Rc::clone(&drops))).is_ok());
}
let removed = buffer.pop().unwrap();
assert_eq!(drops.get(), 0);
buffer.clear();
assert_eq!(drops.get(), 2);
drop(removed);
assert_eq!(drops.get(), 3);
drop(buffer);
assert_eq!(drops.get(), 3);
}
הערך שהוצא אינו מושמד עד drop המפורש שלו. קריאה גולמית נוספת מאותו תא הייתה יוצרת בעלות שנייה על אותו Rc בלי הגדלת מונה ההפניות שלו, והייתה מפרה את חוזי הטיפוס. העברת בעלות מחייבת גם עדכון מצב לוגי, לא רק העתקת בייטים.