haskell和大二进制

时间:2012-10-17 23:20:39

标签: haskell io binary stm

当通过TChan广播BinaryString时,会复制整个Binary还是只复制引用?


如果整个二进制文件被复制,如何只发送引用?

2 个答案:

答案 0 :(得分:3)

只有引用被写入TChan,不会复制有效负载。复制所有数据总是非常低效,而且由于数据是不可变的(一般来说,你可以作弊),所以只传输引用是安全的。

答案 1 :(得分:2)

比Daniel更准确一点(并在评论中确认Daniels的怀疑):指向BinaryString构造函数的指针(你的意思是ByteString?)被写入TVar。

让我们通过检查相关代码来确认。 TChan基于TVar构建,并使用writeTVar来编写值,在GHC.Conc.Sync中实现(并由GHC.Cont和{{1重新导出] }}):

Control.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); } 是一个永远不会被查看的指针,并存储为指针。