// Copyright (c) 2010-2018 SharpDX - Alexandre Mutel // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; using System.Collections.Generic; namespace SharpDX { /// /// A class to dispose instances and allocated unmanaged memory. /// public class DisposeCollector : DisposeBase { private List disposables; /// /// Gets the number of elements to dispose. /// /// The number of elements to dispose. public int Count { get { return disposables.Count; } } /// /// Disposes all object collected by this class and clear the list. The collector can still be used for collecting. /// /// If true, managed resources should be /// disposed of in addition to unmanaged resources. /// /// To completely dispose this instance and avoid further dispose, use method instead. /// public void DisposeAndClear(bool disposeManagedResources = true) { if (disposables == null) return; for (int i = disposables.Count - 1; i >= 0; i--) { var valueToDispose = disposables[i]; if (valueToDispose is IDisposable disposable) { if (disposeManagedResources) { disposable.Dispose(); } } else { Utilities.FreeMemory((IntPtr)valueToDispose); } disposables.RemoveAt(i); } disposables.Clear(); } /// /// Disposes of object resources. /// /// If true, managed resources should be /// disposed of in addition to unmanaged resources. protected override void Dispose(bool disposeManagedResources) { DisposeAndClear(disposeManagedResources); disposables = null; } /// /// Adds a object or a allocated using to the list of the objects to dispose. /// /// To dispose. /// If toDispose argument is not IDisposable or a valid memory pointer allocated by public T Collect(T toDispose) { if (!(toDispose is IDisposable || toDispose is IntPtr)) throw new ArgumentException("Argument must be IDisposable or IntPtr"); // Check memory alignment if (toDispose is IntPtr) { var memoryPtr = (IntPtr)(object)toDispose; if (!Utilities.IsMemoryAligned(memoryPtr)) throw new ArgumentException("Memory pointer is invalid. Memory must have been allocated with Utilties.AllocateMemory"); } if (!Equals(toDispose, default(T))) { if (disposables == null) disposables = new List(); if (!disposables.Contains(toDispose)) { disposables.Add(toDispose); } } return toDispose; } /// /// Dispose a disposable object and set the reference to null. Removes this object from this instance.. /// /// Object to dispose. public void RemoveAndDispose(ref T objectToDispose) { if (disposables != null) { Remove(objectToDispose); var disposableObject = objectToDispose as IDisposable; if (disposableObject != null) { // Dispose the component disposableObject.Dispose(); } else { var localData = (object)objectToDispose; var dataPointer = (IntPtr) localData; Utilities.FreeMemory(dataPointer); } objectToDispose = default(T); } } /// /// Removes a disposable object to the list of the objects to dispose. /// /// /// To dispose. public void Remove(T toDisposeArg) { if (disposables != null && disposables.Contains(toDisposeArg)) { disposables.Remove(toDisposeArg); } } } }