// called automatically but only once from criticalhandle when this handle is disposing or finalizing
// see http://reflector.webtropy.com/default.aspx/4@0/4@0/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/clr/src/BCL/System/Runtime/InteropServices/CriticalHandle@cs/1305376/CriticalHandle@cs
// and http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.criticalhandle.releasehandle(v=vs.110).aspx
protected override bool ReleaseHandle()
{
// Invalid handles might occur if we throw in construction of one, after root is set, but before the handle has been acquired.
// In that case, release should just do nothing at all - there is nothing to release.
// Also, of course if we were called somehow with an invalid handle (should never happen except as stated above), it would not be a good idea to pass it to core
if (IsInvalid)
{
return(true);
}
try
{
// if we are a root object then we can safely assume that no more user threads are going this way:
// if we are a root object and in a finalizer thread , then we know that no more user threads will hit us
// if we are a root object and being called via dispose, then we know that the Table(or whatever) wrapper will block any further calls
// because we are closed(disposed)
// in both cases unbind the list using whatever thread we are on, then unbind ourselves
if (Root == null)
{
lock (_unbindListLock)
{
_noMoreUserThread = true; // note:resurrecting a root object will not work unless you set this to false again first
// this call could interleave with calls from finalizing children in other threads
// but they or we will wait because of the unbindlistlock taken above
RequestUnbind(this);
}
}
else
{
// as a child object we wil ask our root to unbind us (testing nomoreuserthread to determine if it can be done at once or we will just have to be put in an unbindlist)
// ask our root to unbind us (if it is itself finalizing) or put us into the unbind list (if it is still running)
// note that the this instance cannot and will never be aroot itself bc root != null
Root.RequestUnbind(this);
}
return(true);
}
catch (Exception)
{
// it would be really bad if we got an exception in here. We must not pass it on, but have to return false
return(false);
}
}