2012-07-16 15 views
17

क्या कोई डेल्फी में कमजोर संदर्भ का स्पष्टीकरण प्रदान कर सकता है?"कमजोर संदर्भ": पृथ्वी पर स्पष्टीकरण की आवश्यकता

मैंने देखा कि अवधारणा का अक्सर कुछ पुस्तकालय/ढांचे स्रोत कोड में जांच की जाती है I scrutinize। मैं एक लिम्बो में हूं और इसकी स्पष्ट समझ समझना चाहता हूं।

उत्तर

34

इंटरफ़ेस संदर्भों द्वारा एक-दूसरे को संदर्भित करने वाले उदाहरण संदर्भ गणना आधारित इंटरफ़ेस कार्यान्वयन में एक दूसरे को जीवित रखते हैं।

एक कमजोर संदर्भ का प्रयोग "एक दूसरे को जीवित रखें" भालू गले को तोड़ने के लिए किया जाता है। यह संदर्भ गणना प्रणाली को रोकने के लिए एक शुद्ध सूचक के रूप में एक संदर्भ घोषित करके किया जाता है।

IFriend = Interface(IInterface) 
end; 

TFriend = class(TInterfacedObject, IFriend) 
private 
    FFriend: IFriend; 
end; 


var 
    Peter: IFriend; 
    John: IFriend; 
begin 
    Peter := TFriend.Create; 
    John := TFriend.Create; 

    Peter.Friend := John; 
    John.Friend := Peter; 
end; 

यहां तक ​​कि जब पीटर और जॉन दायरे से बाहर जाते हैं, उनके उदाहरणों के आसपास है क्योंकि उनके आपसी संदर्भ शून्य करने के लिए छोड़ने से उनके refcount रहता रखा जाता है।

समस्या और अधिक सामान्यतः समग्र पैटर्न में पाया जाता है (मूल - बच्चे के सम्बन्ध) जहां बच्चे माता-पिता के लिए एक वापस संदर्भ है:

ISomething = Interface(IInterface) 
end; 

TSomething = class(TInterfacedObject, ISomething) 
end; 

TParent = class(TSomething) 
    FChildren: TInterfacedList; 
end; 

TChild = class(TSomething) 
    FParent: ISomething; 
end; 

फिर से, माता-पिता और बच्चे eachother के चारों ओर रख सकते हैं क्योंकि उनके आपसी संदर्भ अपने रिफाउंट को शून्य से गिरने से रोकता है।

यह एक weak reference के साथ हल किया जाता है:

TChild = class(TSomething) 
    FParent: Pointer; 
end; 

FParent के रूप में घोषित करने से एक "शुद्ध" संदर्भ गिनती तंत्र माता-पिता के लिए वापस संदर्भ के लिए खेलने में नहीं आता है सूचक। जब कोई अभिभावक गुंजाइश से बाहर हो जाता है, तो इसकी संदर्भ संख्या अब शून्य हो सकती है क्योंकि उसके बच्चे अब शून्य से ऊपर की रेफरी गिनती नहीं रखते हैं।

नोट इस समाधान को आजीवन प्रबंधन पर सावधानीपूर्वक ध्यान देने की आवश्यकता है। बच्चों को माता-पिता के जीवनकाल से परे जीवित रखा जा सकता है जब इन वर्गों के "बाहरी" पर कुछ बच्चे के संदर्भ में रहता है। और जब बच्चे को मूल संदर्भ माना जाता है तो यह सभी प्रकार के दिलचस्प एवी के कारण हो सकता है, हमेशा वैध उदाहरण को इंगित करता है। यदि आपको इसकी ज़रूरत है, तो सुनिश्चित करें कि जब माता-पिता गुंजाइश से बाहर हो जाते हैं, तो इससे बच्चों को अपने बच्चों के अपने संदर्भों को नकारने से पहले उनके पीछे संदर्भ संदर्भित होते हैं।

+0

विवरण के लिए +1 और अपने प्रोफ़ाइल चित्र –

+0

@JanDoggen: :-) पशु हमेशा मेरी पसंदीदा मपेट –

10

डेल्फी में डिफ़ॉल्ट रूप से, सभी संदर्भों को या तो कर रहे हैं:

  • weak referencespointer के लिए और class उदाहरण;
  • स्पष्ट प्रतिलिपि निम्न स्तर मूल्य प्रकार के लिएinteger, Int64, currency, double या record की तरह (और पुराने object या shortstring हटा दिया गया);
  • copy-on-write उच्च स्तरीय मूल्य प्रकार के लिए reference counting साथ (जैसेstring, widestring, variant या गतिशील सरणी);
  • मजबूत संदर्भinterface उदाहरणों के लिए संदर्भ गणना के साथ;

मजबूत संदर्भ गिनती के साथ मुख्य मुद्दा संभावित परिपत्र संदर्भ समस्या है। ऐसा तब होता है जब interface के पास एक मजबूत संदर्भ है, लेकिन लक्ष्य interface पर एक मजबूत सूचक वापस मूल है। यहां तक ​​कि जब सभी अन्य संदर्भ हटा दिए जाते हैं, तब भी वे एक दूसरे के पास रहेंगे और जारी नहीं किए जाएंगे। यह अप्रत्यक्ष रूप से, ऑब्जेक्ट्स की एक श्रृंखला द्वारा भी हो सकता है, जिसमें श्रृंखला में आखिरी वस्तु हो सकती है जो पहले की वस्तु को संदर्भित करती है।

उदाहरण के लिए निम्नलिखित इंटरफ़ेस परिभाषा देखें:

procedure TParent.SetChild(const Value: IChild); 
begin 
    FChild := Value; 
end; 

procedure TChild.SetParent(const Value: IParent); 
begin 
    FParent := Value; 
end; 

डेल्फी में, संदर्भ कॉपी चर का सबसे सामान्य प्रकार (यानी संस्करण, गतिशील:

IParent = interface 
    procedure SetChild(const Value: IChild); 
    function GetChild: IChild; 
    function HasChild: boolean; 
    property Child: IChild read GetChild write SetChild; 
    end; 

    IChild = interface 
    procedure SetParent(const Value: IParent); 
    function GetParent: IParent; 
    property Parent: IParent read GetParent write SetParent; 
    end; 

निम्नलिखित कार्यान्वयन निश्चित स्मृति रिसाव हो जाएगा सरणी या स्ट्रिंग) कॉपी-ऑन-राइट लागू करके इस समस्या को हल करें। दुर्भाग्यवश, यह पैटर्न इंटरफ़ेस पर लागू नहीं है, जो मान ऑब्जेक्ट्स नहीं हैं, लेकिन संदर्भ ऑब्जेक्ट्स, कार्यान्वयन कक्षा से बंधे हैं, जिन्हें कॉपी नहीं किया जा सकता है।

ध्यान दें कि कचरा कलेक्टर आधारित भाषाओं (जावा या सी #) की तरह इस समस्या से, जब से वृत्तीय संदर्भ उनकी स्मृति मॉडल के आधार पर नियंत्रित किया जाता है ग्रस्त नहीं है: वस्तुओं जीवन भर स्मृति प्रबंधक द्वारा विश्व स्तर पर बनाए रखा है। बेशक, यह स्मृति उपयोग में वृद्धि करेगा, आवंटन और असाइनमेंट के दौरान अतिरिक्त कार्रवाइयों के कारण प्रक्रिया को धीमा कर देगा (सभी ऑब्जेक्ट्स और उनके संदर्भ आंतरिक सूचियों में बनाए रखा जाना चाहिए), और कचरा कलेक्टर कार्रवाई में प्रवेश करते समय एप्लिकेशन को धीमा कर सकता है।

कोई कचरा-संग्रह (जैसे डेल्फी) वाले भाषाओं के साथ एक आम समाधान कमजोर पॉइंटर्स का उपयोग करना है, जिसके द्वारा इंटरफ़ेस को संदर्भ गणना में वृद्धि किए बिना किसी संपत्ति को असाइन किया गया है। आसानी से एक कमजोर सूचक बनाने के लिए आदेश में, निम्न फ़ंक्शन का उपयोग किया जा सकता है:

procedure SetWeak(aInterfaceField: PIInterface; const aValue: IInterface); 
begin 
    PPointer(aInterfaceField)^ := Pointer(aValue); 
end; 

इसलिए, यह इस तरह के रूप में इस्तेमाल किया जा सकता है:

procedure TParent.SetChild(const Value: IChild); 
begin 
    SetWeak(@FChild,Value); 
end; 

procedure TChild.SetParent(const Value: IParent); 
begin 
    SetWeak(@FParent,Value); 
end; 

आप my blog post about weak references in Delphi पढ़ने की कोशिश कर सकते हैं - और उसके संबंधित स्रोत कोड: हमने सीधे कमजोर संदर्भ लागू किया है, और डेल्फी 6 से XE2 तक कमजोर संदर्भ इंटरफ़ेस "शून्यिंग" को कार्यान्वित किया है।

वास्तव में, कुछ मामलों में, आपको इंटरफ़ेस कमजोर फ़ील्ड को nil पर सेट करने की आवश्यकता होगी, यदि आप किसी भी एक्सेस उल्लंघन उल्लंघन से बचने के लिए अपने बच्चे के सामने संदर्भ उदाहरण जारी करते हैं। इसे "ज़ीरोइंग कमजोर पॉइंटर्स" कहा जाता है, और Apple implemented with the ARC model, और हमने डेल्फी में लागू करने का प्रयास किया।

+0

सी # भी है एक [WeakReference] (http://msdn.microsoft.com/de-de /library/system.weakreference.aspx) कक्षा किसी अन्य संदर्भ के बाद जीसी को उस ऑब्जेक्ट को साफ़ करने की अनुमति देने के लिए। –

+0

@StefanGlienke आप सही हैं, लेकिन एक जीसी दुनिया में, कमजोर संदर्भ कुछ हद तक विविध हैं, क्योंकि वे कचरा संग्रह स्वयं को पार करने के लिए उपयोग की जाने वाली एक विशेष प्रकार की कक्षा हैं। डेल्फी में, हमारे पास पास-पास करने के लिए कोई भी जीसी नहीं है, केवल अपनी ऑब्जेक्ट प्रबंधित करने वाली ऑब्जेक्ट का संदर्भ है। (ज़ीरोइंग) डेल्फी इंटरफेस में कमजोर पॉइंटर्स इस से कुछ हद तक कम स्तर पर हैं। –

+0

सहमत हुए, मैं बस यह इंगित करना चाहता था कि यह केवल डेल्फी समस्या नहीं है हालांकि जीसी क्रॉस/सर्कुलर संदर्भों को संभालने के बारे में बहुत अधिक स्मार्ट है। –

2

सबसे सामान्य मामले में strong reference एक संदर्भित उदाहरण के जीवनकाल को नियंत्रित करता है जबकि weak reference नहीं करता है। weak reference शब्द कचरा कलेक्टर, संदर्भ गिनती इंटरफेस या सामान्य वस्तुओं के संदर्भ में उपयोग किया जा सकता है।

उदाहरण के लिए, डेल्फी फॉर्म अपने सभी नियंत्रणों के संदर्भ रखता है; इन संदर्भों को मजबूत कहा जा सकता है क्योंकि जब एक फॉर्म नष्ट हो जाता है तो इसके नियंत्रण भी नष्ट हो जाते हैं। दूसरी तरफ, डेल्फी फॉर्म के नियंत्रण में एक रूप का संदर्भ है जिसका यह संबंधित है। इस संदर्भ को कमजोर कहा जा सकता है क्योंकि यह किसी भी रूप में किसी फ़ॉर्म के जीवनकाल को नियंत्रित नहीं करता है।

5

भी देखें

Automatic Reference Counting in Delphi Mobile Compilers

जो नए [weak] विशेषता के प्रलेखन में शामिल हैं:

एआरसी के लिए एक और महत्वपूर्ण अवधारणा कमजोर संदर्भ की भूमिका, जो आप उन्हें टैग करके बना सकते हैं [कमजोर] विशेषता के साथ।

+0

साझा करने के लिए धन्यवाद। – menjaraz

संबंधित मुद्दे