2012-10-17 71 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是一个永远不会被查看并存储的指针。