क्या स्टैक पर सेल्फ-रेफरेंशियल स्ट्रक्चर आवंटित करना संभव है? pin दस्तावेज़ एक उदाहरण दिखाता है ढेर पर एक संरचना पिन करने के लिए। मैंने संबंधित कोड लिखने के लिए इसका अनुसरण किया:

pub struct Cont {
    pub f: i32,
    // shall point to 'f' field
    ptr_f: NonNull<i32>,
}

impl Cont {
    pub fn read(&self) -> i32 {
        unsafe { *self.ptr_f.as_ref() }
    }

    pub fn pinned(value: i32) -> Pin<Self> {
        // ensures ptr_f = &f
    }
}

fn main() {
    let a = Cont::pinned(5);
    let b = Cont::pinned(12);

    assert_eq!(a.f, a.read());
    assert_eq!(b.f, b.read());
}

लेकिन मुझे नहीं पता कि Cont::pinned फ़ंक्शन कैसे लिखना है, या भले ही यह सही हस्ताक्षर हो (यदि संभव हो तो)।

2
Guillaume Lemaître 31 अक्टूबर 2020, 14:10

1 उत्तर

सबसे बढ़िया उत्तर

लेकिन मुझे नहीं पता कि Cont::pinned फ़ंक्शन कैसे लिखना है, या भले ही यह सही हस्ताक्षर हो (यदि संभव हो तो)।

Pin<P> का प्रकार पैरामीटर हमेशा एक सूचक या संदर्भ होता है; a Pin कभी भी अपने डेटा का स्वामी नहीं होता, सिवाय Box जैसे स्वामित्व वाले सूचक प्रकार के। यह देखते हुए कि आप मूल मान को स्टैक पर रखना चाहते हैं, उदाहरण में फ़ंक्शन का एनालॉग है:

fn pinned(value: i32) -> Pin<&mut Self>;

लेकिन यह संभव नहीं है क्योंकि कोई फ़ंक्शन उसके द्वारा बनाई गई किसी चीज़ का संदर्भ नहीं लौटा सकता - जब तक कि वह कुछ ढेर पर या स्थिर मेमोरी में संग्रहीत न हो। इसलिए, यदि आप एक स्टैक-आवंटित मान का Pin बनाना चाहते हैं, तो आपको पहले अनपिन किया गया मान बनाना होगा, ताकि पिन उसका संदर्भ दे सके।

शायद आप एक एपीआई डिज़ाइन करने का प्रयास कर सकते हैं जो पहले से ही स्टैक पर मौजूद कुछ डेटा को बदलकर Pin बनाता है:

let a: Option<Cont> = None;
let b: Option<Cont> = None;

let a = Cont::pinned(&mut a, 5);
let b = Cont::pinned(&mut b, 12);

लेकिन तब मान पिन से अधिक समय तक जीवित रहेगा और आप पिन गारंटी को केवल तभी लागू कर सकते हैं जब पिन लाइव हो, जिससे यह अस्वस्थ हो जाता है।

इसे ध्वनि बनाने के लिए, आपको किसी तरह यह लागू करने की आवश्यकता होगी कि पिन गिराए जाने के बाद मूल मूल्यों तक नहीं पहुंचा जा सकता है। इसके परिणामस्वरूप एक बहुत ही सीमित एपीआई होगा। उदाहरण के लिए:

fn main() {
    // setup_conts creates the pinned Cont values and calls the closure 
    setup_conts(5, 12, |a: Pin<&mut Cont>, b: Pin<&mut Cont>| {
        // a and b can only be used inside this closure
    })
}
2
Peter Hall 31 अक्टूबर 2020, 13:31