2

以下に示すように、 ではtwisted.spread.flavors.RemoteCache.unjellyFor、 というダミー オブジェクトを作成し、 をcProxy返すのではなく、それをクライアント コードの残りの部分に返しselfます。

def unjellyFor(self, unjellier, jellyList):
    if unjellier.invoker is None:
        return setInstanceState(self, unjellier, jellyList)
    self.broker = unjellier.invoker
    self.luid = jellyList[1]
    cProxy = _newDummyLike(self)
    # XXX questionable whether this was a good design idea...
    init = getattr(cProxy, "__init__", None)
    if init:
        init()
    unjellier.invoker.cacheLocally(jellyList[1], self)
    cProxy.setCopyableState(unjellier.unjelly(jellyList[2]))
    # Might have changed due to setCopyableState method; we'll assume that
    # it's bad form to do so afterwards.
    self.__dict__ = cProxy.__dict__
    # chomp, chomp -- some existing code uses "self.__dict__ =", some uses
    # "__dict__.update".  This is here in order to handle both cases.
    self.broker = unjellier.invoker
    self.luid = jellyList[1]
    return cProxy

_newDummyLike の本体は次のようになります。

def _newDummyLike(instance):
    """
    Create a new instance like C{instance}.

    The new instance has the same class and instance dictionary as the given
    instance.

    @return: The new instance.
    """
    if isinstance(instance.__class__, type):
        # New-style class
        dummy = _DummyNewStyle()
    else:
        # Classic class
        dummy = _Dummy()
    dummy.__class__ = instance.__class__
    dummy.__dict__ = instance.__dict__
    return dummy

ダミー オブジェクトはそのandを「実際の」オブジェクトとcProxy共有しているため、ダミーを作成する意味がまったくわかりません。なぜダミーが作成されたのですか?__dict____class__

4

2 に答える 2

2

これらの「ダミー」オブジェクトの目的は、分散ガベージ コレクションです。

まず、 a の単純なケースを考えてみましょうCopyable。シリアル化するたびに、ピアは新しい を取得しますRemoteCopy。シンプル - 追跡するものは何もありません。いつCopyableでも簡単にガベージ コレクションを実行できます。

次に、Referenceable. シリアル化するたびに、ピアは新しい を取得しますRemoteReference。ここで問題があります。ピアがまだ を持っている場合、ピアは のRemoteReferenceメソッドを呼び出すことができるはずですReferenceable。これは、ブローカーが への強い参照を保持していることを意味しますReferenceableRemoteReference少しトリッキーですが、それでもかなり単純です。 でがガベージ コレクションされるたびに、送信者にそのが参照されなくなったことを伝えるメッセージRemoteReference.__del__を送信します。カウントが 0 になると、強い参照が削除され、自然にガベージ コレクションが行われる可能性があります。これが機能するのは、 aが事実上不変であるためです。含まれているのは、問題のオブジェクトの不透明な識別子、ブローカーへの参照だけで、他には何もありません。decrefReferenceableRemoteReference

最後に、Cacheable. ここで、本当の難問にぶつかります。をシリアル化し、後で同じものが再度送信されているかどうかを判断できるようにするために、への強力な参照を維持する必要がCacheableあります。しかし、ワイヤの反対側では、への暗黙の参照がなくなるかどうかを通知する が必要な もブローカからの強い参照を持っています。BrokerCacheableCacheableRemoteCache__del__CacheableCacheableRemoteCache

これは循環参照であり、悪いものです。ガベージ コレクションを取得するアプリケーションに渡すものが、サーバーがRemoteCache. それが可能であり、循環参照 (このコードは python の GC より前のものであることを思い出してください!) を破ることができます。しかし、内部状態 ( )を共有するアプリケーション オブジェクトを与えることで、一貫性の錯覚を維持することができます。このように、__del__RemoteCache__dict____del__RemoteCacheオブジェクトはガベージコレクションを取得し、それぞれがメッセージを送信selfし、ブローカーからの強力な参照を使用して「実際の」オブジェクト (例では) を残します。これは「ゼロ番目」の参照になります。これが、最初にもコピーされる理由です。 (同じキャッシュ可能オブジェクトへの繰り返し参照がデシリアライズされる呼び出しサイトが他に 1 つしかないことがわかります_newDummyLike- 毎回新しいプロキシ オブジェクトを取得します)。

うまくいけば、これはより理にかなっています!

于 2016-07-26T10:08:47.433 に答える
1

これは、必要なオブジェクトを作成するための単なるトリックです。完全に任意のユーザー定義型の新しいインスタンスを作成するのは困難です。その にどの引数を渡します__init__か? __init__望ましくない副作用がある場合はどうなりますか?代わりにそのメソッドを使用できるかもしれませんが、それ__new__はどのような引数を取りますか? あるいは、__new__メソッドさえないか、__new__副作用があるかもしれません...など。

それをすべて理解することは不可能かもしれませんが、このトリックは非常に単純で簡単です。

于 2014-05-02T11:49:08.013 に答える