18

Is anybody has a pratical example of "long" weak reference (not short) ?

Is this only for internal usage ?

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Eric Ouellet
  • 10,996
  • 11
  • 84
  • 119

1 Answers1

18

Contrary to common perception, Finalize does not cause an object to be garbage-collected. Rather, if it's found to have no strong rooted references, a registered finalizer will prevent the object from being garbage-collected immediately. Instead, the object will be added to a strongly-rooted list of objects whose Finalize method should be run at first opportunity. When that occurs, all short weak references to the object will be invalidated, but long weak references will not.

If one has two or more objects that must be deconstructed in a particular sequence, it may be helpful for the one which must be deconstructed last to have a reference to the one which must be deconstructed first. This should be some form of weak reference, so that the former object (the one that will be deconstructed last) will not needlessly extend the lifetime of the latter object (which must be deconstructed before it), but if it were a short weak reference, it would become unusable just before it was needed. Making it a long weak reference avoids that problem.

Somewhat more generally, a short weak reference is appropriate in cases where one only wants to know about an object if it is in a usable state, while a long weak reference is often appropriate in cases where one needs to know about an object regardless of its state. As another example, suppose a remote database server can only interface with one connection object at a time, and the connection object has a finalizer which notifies the remote server that its services are not required. If a connection object is abandoned and an attempt is made to re-connect with that same server, the connection manager must be able to deal with three cases:

  • It has a WeakReference which holds a reference to the earlier connection object, and it's still good. In that case, code should simply start using it.

  • The earlier connection object's finalizer has run to completion and the remote server is ready for a new connection. In that case, code should simply create a new connection object.

  • The GC has noticed that the connection object was abandoned, and has scheduled it for finalization, but the finalizer has not yet run to completion. In that case, code must ensure that the old connection gets cleaned up before a new one can be established.

The first case can be handled via short WeakReference. Determining that the second or third applies requires a long WeakReference. Note that once a connection was enqueued for finalization the connection manager would not be interested in trying to reuse it, but would nonetheless still have to be aware of its existence.

supercat
  • 77,689
  • 9
  • 166
  • 211
  • Thanks a lot. Great answer. It also answers another question I had at the beginning of the week. I asked few questions at Stack Overflow but this answer is one of the best or the best I received. Thank you very very much. – Eric Ouellet Feb 28 '13 at 13:25
  • 1
    In your hypothetical connection manager scenario, how would I tell from the long WeakReference whether the object is scheduled for finalization or not (i.e. how could I tell case #1 apart from case #3)? I would just have a WeakReference object with a non-null target, but how could I tell what state it was in? – Mike Marynowski Aug 04 '13 at 05:24
  • 3
    @MikeMarynowski: One way would be to use two weak references, a long one and a short one. If the short one has died but the long one is still valid, the object has been scheduled to have its finalizer run. – supercat Aug 04 '13 at 14:17