2012-10-17 102 views

回答

3

僅向TChan寫入引用,則不會複製有效負載。如果一直複製所有數據的效率太低,並且由於數據是不可變的(一般來說,您可以作弊),因此僅傳輸引用是安全的。

+0

你的意思是說引用得到默認複製,或者我應該這樣做嗎? – user1748906

+1

這是默認設置,您不需要採取任何額外措施。如前所述,由於數據是不可變的,因此共享它是安全的,所以不需要複製它。 –

+0

也許s /構造函數/一個參考/? –

2

要比丹尼爾精確一點(並且在他的評論中確認Daniels的懷疑):指向BinaryString構造函數的指針(你的意思是ByteString?)被寫入TVar。

讓我們通過檢查相關代碼進行確認。 TChan是在TVar建成,並使用writeTVar寫值,界河是GHC.Conc.Sync實現(通過GHC.ContControl.Concurrent.STM.TVar再出口):

-- |Write the supplied value into a TVar 
writeTVar :: TVar a -> a -> STM() 
writeTVar (TVar tvar#) val = STM $ \s1# -> 
    case writeTVar# tvar# val s1# of 
     s2# -> (# s2#,() #) 

的爭論只是一起功能writeTVar#,這是通過這是在實施rts/PrimOps.cmm一個原始操作:

stg_writeTVarzh 
{ 
    W_ trec; 
    W_ tvar; 
    W_ new_value; 

    /* Args: R1 = TVar closure */ 
    /*  R2 = New value */ 

    MAYBE_GC (R1_PTR & R2_PTR, stg_writeTVarzh); // Call to stmWriteTVar may allocate 
    trec = StgTSO_trec(CurrentTSO); 
    tvar = R1; 
    new_value = R2; 
    foreign "C" stmWriteTVar(MyCapability() "ptr", trec "ptr", tvar "ptr", new_value "ptr") []; 

    jump %ENTRY_CODE(Sp(0)); 
} 

此包裝下面的代碼在rts/STM.c

void stmWriteTVar(Capability *cap, 
        StgTRecHeader *trec, 
        StgTVar *tvar, 
        StgClosure *new_value) { 

    StgTRecHeader *entry_in = NULL; 
    TRecEntry *entry = NULL; 
    TRACE("%p : stmWriteTVar(%p, %p)", trec, tvar, new_value); 
    ASSERT (trec != NO_TREC); 
    ASSERT (trec -> state == TREC_ACTIVE || 
      trec -> state == TREC_CONDEMNED); 

    entry = get_entry_for(trec, tvar, &entry_in); 

    if (entry != NULL) { 
    if (entry_in == trec) { 
     // Entry found in our trec 
     entry -> new_value = new_value; 
    } else { 
     // Entry found in another trec 
     TRecEntry *new_entry = get_new_entry(cap, trec); 
     new_entry -> tvar = tvar; 
     new_entry -> expected_value = entry -> expected_value; 
     new_entry -> new_value = new_value; 
    } 
    } else { 
    // No entry found 
    StgClosure *current_value = read_current_value(trec, tvar); 
    TRecEntry *new_entry = get_new_entry(cap, trec); 
    new_entry -> tvar = tvar; 
    new_entry -> expected_value = current_value; 
    new_entry -> new_value = new_value; 
    } 

    TRACE("%p : stmWriteTVar done", trec); 
} 

而在這裏我們看到new_value是一個永遠不會被查看並存儲的指針。