TChanを介してBinaryStringをブロードキャストする場合、Binary全体または参照のみがコピーされるのは何ですか?
バイナリ全体がコピーされた場合、参照のみを送信する方法は?
への参照のみが書き込まれTChan
、ペイロードはコピーされません。すべてのデータを常にコピーするのは非常に非効率的です。また、データは不変であるため (一般に、不正行為が可能です)、参照のみを転送しても安全です。
ダニエルよりももう少し正確に言うと (ダニエルのコメントでダニエルの疑いを確認してください): BinaryString のコンストラクターへのポインター (ByteString のことですか?) が TVar に書き込まれます。
関連するコードをチェックして確認しましょう。TChan
に基づいて構築され、値を書き込むためにTVar
使用します。これは で実装されます(および によって再エクスポートされます):writeTVar
GHC.Conc.Sync
GHC.Cont
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);
}
そして、これは参照new_value
されることのないポインタであり、そのように格納されていることがわかります。