C Sharp

Deterministic Finalization

With a bit of the history out of the way, let's define deterministic finalization. Once an object is determined to no longer be in use, its termination code executes and releases the references it holds to other objects. This termination process then naturally cascades through the graph of objects, starting from the topmost object. Ideally, this would work for both shared and single-use objects.

Note that there is no promise regarding time here. Once a GC thread discovers that a reference is no longer being used, that particular thread won't do anything else until the object termination code is executed. However, a CPU context switch can always occur during processing, meaning that an arbitrary-from the application's perspective-amount of time might pass before completion of this step.

As mentioned above, many situations exist in which an application might care about the timeliness or order of execution regarding the termination code. These situations are generally tied to resources, for which there is a high degree of contention. Here are some examples of resources that an object might need to release as soon as the object is no longer in use: -

  • Memory Freeing the memory for an object graph quickly returns the memory to the pool for use.

  • Window handles The footprint of the window object in the GC does not reflect the actual cost. There is some footprint inside the operating system to represent the window, and there might even be a limit, other than available memory, on the total number of window handles that can be allocated.

  • Database connections Concurrent database connections are frequently licensed, and therefore there might be a limited number of them available. It's important that these be returned to a pool promptly so that they can be reused.

  • Files Because there's a single instance of a given file and exclusive access is required for many operations, it's important that file handles be closed when not in use.