2012-04-11 7 views
25

क्या कोई बता सकता है कि atomicModifyIORef कैसे काम करता है? विशेष रूप से:हास्केल: 'atomicModifyIORef' कैसे काम करता है?

(1) क्या यह लॉक की प्रतीक्षा करता है, या अगर विवाद होता है तो ऑप्टिमाइज़िक रूप से प्रयास करें और पुनः प्रयास करें (जैसे TVar)।
(2) atomicModifyIORef का हस्ताक्षर modifyIORef के हस्ताक्षर से अलग क्यों है? विशेष रूप से, यह अतिरिक्त चर b क्या है?

संपादित करें: मुझे लगता है कि मैंने जवाब दिया है (2), उस b में निकालने का एक मूल्य है (यदि आवश्यक नहीं है तो यह खाली हो सकता है)। एक थ्रेडेड प्रोग्राम में, मान जानने के लिए मामूली है, लेकिन एक बहुप्रचारित कार्यक्रम में, कोई यह जानना चाहता है कि फ़ंक्शन लागू होने के समय पिछले मूल्य क्या था। मुझे लगता है कि ऐसा क्यों modifyIORef इस अतिरिक्त वापसी मान (नहीं है के रूप में इस वापसी मान के साथ modifyIORef के इस तरह के प्रयोगों को शायद atomicModifyIORef वैसे भी उपयोग करना चाहिए। मैं अभी भी करने के लिए (1) यद्यपि।

उत्तर

10

atomicModifyIORef लेता जवाब में दिलचस्पी रखता हूँ है एक r :: IORef a और एक समारोह f :: a -> (a, b) और निम्नलिखित है:।।

यह r का मूल्य पढ़ता है और इस मान को f लागू होता है, (a',b) उपज फिर r नया मान a' जबकि b के साथ अद्यतन किया जाता है वापसी मान यह पढ़ने और लेखन का उपयोग परमाणु रूप से किया जाता है।

बेशक यह परमाणु केवल तभी काम करता है जब सभीr तक पहुंच atomicModifyIORef के माध्यम से किया जाता है। ध्यान दें कि आप स्रोत को देखकर यह जानकारी पा सकते हैं [1]।

[1] http://hackage.haskell.org/packages/archive/base/latest/doc/html/src/Data-IORef.html#atomicModifyIORef

+3

क्या यह लॉकिंग करता है या यह आशावादी है? जीएचसी संस्करण बस एक जीएचसी आदिम कहता है। – Clinton

+1

ध्यान दें कि आलस्य के कारण, 'atomicModifyIORef' को केवल वर्तमान मूल्य को एक थंक पर इंगित करना है, वास्तविक कार्य में कुछ देर बाद इसे पढ़ने तक देरी हो रही है। AFAIK, यह अधिकांश प्लेटफार्मों पर एक सीएएस की तरह कुछ संकलित करता है।एक इंटरलॉक एक्सचेंज (कैस) लूप के माध्यम से – hammar

+10

आशावादी। https://github.com/ghc/ghc/blob/45740c29b24ea78b885d3b9f737a8bdc00265f7c/rts/PrimOps.cmm#L364 –

27

यह एक ताला के लिए प्रतीक्षा करता है, या आशावादी कोशिश करते हैं और हो, तो विवाद (Tvar की तरह) का प्रयास करें।

atomicModifyIORef, जिस पर आप हैं अंतर्निहित हार्डवेयर वास्तुकला पर एक ताला अनुदेश का उपयोग करता है एक परमाणु फैशन में एक आवंटित हास्केल वस्तु के लिए सूचक स्वैप करने के लिए।

stg_atomicModifyMutVarzh 
{ 
... 

retry: 
    x = StgMutVar_var(mv); 
    StgThunk_payload(z,1) = x; 
#ifdef THREADED_RTS 
    (h) = foreign "C" cas(mv + SIZEOF_StgHeader + OFFSET_StgMutVar_var, x, y) []; 
    if (h != x) { goto retry; } 
#else 
    StgMutVar_var(mv) = y; 
#endif 
... 
} 

है यही कारण है, यह स्वैप करने की कोशिश करेंगे:

86 पर यह cas intruction, atomicModifyMutVar# के माध्यम से भाषा के लिए एक आदिम रूप में सामने आ रहा है, जो के रूप में सीएमएम में एक क्रम सेवा के रूप में कार्यान्वित किया जाता है का उपयोग करता है , और अन्यथा पुनः प्रयास करें।

एक आदिम शो कैसे हम धातु के लिए नीचे लाने के रूप में कैस के कार्यान्वयन:

/* 
* Compare-and-swap. Atomically does this: 
*/ 
EXTERN_INLINE StgWord cas(StgVolatilePtr p, StgWord o, StgWord n); 

/* 
* CMPXCHG - the single-word atomic compare-and-exchange instruction. Used 
* in the STM implementation. 
*/ 
EXTERN_INLINE StgWord 
cas(StgVolatilePtr p, StgWord o, StgWord n) 
{ 
#if i386_HOST_ARCH || x86_64_HOST_ARCH 
    __asm__ __volatile__ (
     "lock\ncmpxchg %3,%1" 
      :"=a"(o), "=m" (*(volatile unsigned int *)p) 
      :"0" (o), "r" (n)); 
    return o; 
#elif arm_HOST_ARCH && defined(arm_HOST_ARCH_PRE_ARMv6) 
    StgWord r; 
    arm_atomic_spin_lock(); 
    r = *p; 
    if (r == o) { *p = n; } 
    arm_atomic_spin_unlock(); 
    return r; 
#elif !defined(WITHSMP) 
    StgWord result; 
    result = *p; 
    if (result == o) { 
     *p = n; 
    } 
    return result; 

तो आप देख सकते हैं कि यह इंटेल में एक परमाणु अनुदेश का उपयोग करने, अन्य आर्किटेक्चर विभिन्न तंत्रों हो जाएगा पर सक्षम है उपयोग किया गया। रनटाइम फिर से प्रयास करेगा।

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