The SafeHandle
class allows the safe access to native resources under .NET with reference counting and cooperation from the P/Invoke marshaller to avoid premature disposal of handles that could lead to an application crash.
In some situation, it would be advantageous to notify the garbage collector that some native resource is using a lot of memory, for example, when the "handle" in question is a large buffer owned by a wrapped native library. The GC.AddMemoryPressure
may be used for this purpose; however, GC.RemoveMemoryPressure
must be called at the end of the lifetime of the "handle".
The two approaches seem to be incompatible: SafeHandle
is a CriticalFinalizerObject
and its ReleaseHandle
method runs in a Constrained Execution Region (CER). As GC.RemoveMemoryPressure
has no ReliabilityContractAttribute
, it must not be called from a CER (I guess at critical finalization time some parts of the GC concerned with memory pressure could be unavailable).
Two approaches came to my mind, both quite inelegant:
The SafeHandle could be wrapped into another object that has a non-critical finalizer (and Dispose method) that adds and removes the memory pressure. This has two deficiencies: firstly, someone could dispose the SafeHandle (it must be exposed to be passed to native methods) without disposing the wrapper, thus the memory pressure is overestimated. Secondly, the wrapper may become unreferenced while the SafeHandle is still alive, thus the memory pressure is underestimated (could be more severe).
The SafeHandle has a field of some non-critical finalizable type that manages the memory pressure. In this case, most problems from above are gone, however, the handle cannot dispose the memory pressure object in its Dispose or ReleaseHandle methods, as this would lead to a GC.RemoveMemoryPressure call in a CER. Another method (such as DisposeNoncriticial) could be provided, but this leads to a "slicing" issue when the handle is cast to IDisposable or used in a using block.
Is there a common pattern to create a SafeHandle with associated memory pressure?