//-----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation.
//
//-----------------------------------------------------------------------
namespace Microsoft.Isam.Esent.Interop
{
using System;
using System.Diagnostics;
///
/// This is the base class for all esent resource objects.
/// Subclasses of this class can allocate and release unmanaged
/// resources.
///
public abstract class EsentResource : IDisposable
{
///
/// True if a resource has been allocated.
///
private bool hasResource;
///
/// True if this object has been disposed.
///
private bool isDisposed;
///
/// Finalizes an instance of the EsentResource class.
///
~EsentResource()
{
this.Dispose(false);
}
///
/// Gets a value indicating whether the underlying resource
/// is currently allocated.
///
protected bool HasResource
{
get
{
return this.hasResource;
}
}
///
/// Dispose of this object, releasing the underlying
/// Esent resource.
///
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Called by Dispose and the finalizer.
///
///
/// True if called from Dispose.
///
protected virtual void Dispose(bool isDisposing)
{
if (isDisposing)
{
if (this.hasResource)
{
this.ReleaseResource();
Debug.Assert(!this.hasResource, "Resource was not freed");
}
this.isDisposed = true;
}
else
{
if (this.hasResource)
{
// We should not get to this point. The problem is that if
// we use finalizers to free esent resources they may end
// up being freed in the wrong order (e.g. JetEndSession is
// called before JetCloseTable). Freeing esent resources
// in the wrong order will generate EsentExceptions.
Trace.TraceWarning("Non-finalized ESENT resource {0}", this);
}
}
}
///
/// Throw an exception if this object has been disposed.
///
protected void CheckObjectIsNotDisposed()
{
if (this.isDisposed)
{
throw new ObjectDisposedException("EsentResource");
}
}
///
/// Called by a subclass when a resource is allocated.
///
protected void ResourceWasAllocated()
{
this.CheckObjectIsNotDisposed();
Debug.Assert(!this.hasResource, "Resource is already allocated");
this.hasResource = true;
}
///
/// Called by a subclass when a resource is freed.
///
protected void ResourceWasReleased()
{
Debug.Assert(this.hasResource, "Resource is not allocated");
this.CheckObjectIsNotDisposed();
this.hasResource = false;
}
///
/// Implemented by the subclass to release a resource.
///
protected abstract void ReleaseResource();
}
}