2

TChanを介してBinaryStringをブロードキャストする場合、Binary全体または参照のみがコピーされるのは何ですか?


バイナリ全体がコピーされた場合、参照のみを送信する方法は?

4

2 に答える 2

3

への参照のみが書き込まれTChan、ペイロードはコピーされません。すべてのデータを常にコピーするのは非常に非効率的です。また、データは不変であるため (一般に、不正行為が可能です)、参照のみを転送しても安全です。

于 2012-10-17T23:24:25.747 に答える
2

ダニエルよりももう少し正確に言うと (ダニエルのコメントでダニエルの疑いを確認してください): BinaryString のコンストラクターへのポインター (ByteString のことですか?) が TVar に書き込まれます。

関連するコードをチェックして確認しましょう。TChanに基づいて構築され、値を書き込むためにTVar使用します。これは で実装されます(および によって再エクスポートされます):writeTVarGHC.Conc.SyncGHC.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されることのないポインタであり、そのように格納されていることがわかります。

于 2012-10-18T09:42:55.630 に答える