//----------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. // //----------------------------------------------------------------------- namespace Microsoft.Isam.Esent.Interop.Implementation { using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; /// /// A collection of GCHandles for pinned objects. The handles /// are freed when this object is disposed. /// [StructLayout(LayoutKind.Auto)] internal struct GCHandleCollection : IDisposable { /// /// The handles of the objects being pinned. /// private GCHandle[] handles; /// /// Handle count. /// private int count; /// /// Disposes of the object. /// public void Dispose() { if (null != this.handles) { for (int i = 0; i < this.count; i++) { this.handles[i].Free(); } this.handles = null; } } /// /// Add an object to the handle collection. This automatically /// pins the object. /// /// The object to pin. /// /// The address of the pinned object. This is valid until the /// GCHandleCollection is disposed. /// public IntPtr Add(object value) { if (null == value) { return IntPtr.Zero; } if (null == this.handles) { this.handles = new GCHandle[4]; // same as List } else if (this.count == this.handles.Length) { Array.Resize(ref this.handles, this.count * 2); } Debug.Assert(this.count < this.handles.Length, "Index out of bound"); GCHandle handle = GCHandle.Alloc(value, GCHandleType.Pinned); this.handles[this.count++] = handle; IntPtr pinned = handle.AddrOfPinnedObject(); Debug.Assert(IntPtr.Zero != pinned, "Pinned object has null address"); return pinned; } /// /// Set handle array capacity. /// /// Estimated handle count public void SetCapacity(int capacity) { if (null == this.handles) { this.handles = new GCHandle[capacity]; } } } }