/// /// This file is part of ILNumerics Community Edition. /// /// ILNumerics Community Edition - high performance computing for applications. /// Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net /// /// ILNumerics Community Edition is free software: you can redistribute it and/or modify /// it under the terms of the GNU General Public License version 3 as published by /// the Free Software Foundation. /// /// ILNumerics Community Edition is distributed in the hope that it will be useful, /// but WITHOUT ANY WARRANTY; without even the implied warranty of /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the /// GNU General Public License for more details. /// /// You should have received a copy of the GNU General Public License /// along with ILNumerics Community Edition. See the file License.txt in the root /// of your distribution package. If not, see . /// /// In addition this software uses the following components and/or licenses: /// /// ================================================================================= /// The Open Toolkit Library License /// /// Copyright (c) 2006 - 2009 the Open Toolkit library. /// /// 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. /// /// ================================================================================= /// using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ILNumerics { /// /// An artificial scope class, used by the ILNumerics memory management /// public class ILScope : IDisposable { internal class ILThreadingContext { public Stack Arrays = new Stack(100); public Stack Scopes = new Stack(100); public void RegisterArray(ILBaseArray A) { if (Scopes.Count > 0) /* && A.EnterScope() ) */ { //ho: commented out, because otherwise common local arrays do return false and hence get not registered in implicit conversions here! Arrays.Push(A); Scopes.Peek().Count++; } } } [ThreadStatic] private static ILThreadingContext s_threadContext; /// /// Begins an artificial scope block within a local function block /// /// Any input arry, given as parameter for the current function /// A new scope /// The ILScope class plays an important role for the ILNumerics memory management. When writing functions in ILNumerics, /// ILScope is used, to define blocks of artificial scopes for local function blocks. ILNumerics ensures, no memory is left as garbage, once /// such a scope block was left. Furthermore, it garantees, input arrays are kept alive during the execution of the block. By following these /// simple rules, ILNumerics is able to optimize the execution of the algorithm regarding /// execution speed and memory footprint. /// The examples demonstrates a custom function in ILNumerics. It demonstrates the use of distinct array types in the function declaration and the use of /// artificial scopes. /// FreqPeaks(ILInArray inData, ILOutArray freq = null, double sampFreq = 44.1) { /// /// using (ILScope.Enter(inData)) { /// /// ILArray Data = check(inData); /// ILArray retLength = min(ceil(Data.Length / 2.0 + 1), 5.0); /// ILArray Window = stdWindowFunc(Data.Length); /// ILArray magnitudes = abs(fft(Data * Window)); /// magnitudes = magnitudes[r(0,end / 2 + 1)]; /// /// ILArray indices = empty(); /// ILArray sorted = sort(magnitudes, indices, descending:true); /// if (!isnull(freq)) /// freq.a = (sampFreq / 2.0 / magnitudes.Length * indices)[r(0,retLength-1)]; /// return magnitudes[r(0,retLength-1)]; /// } ///}]]> /// public static IDisposable Enter(params ILBaseArray[] inputArrays) { return new ILScope(inputArrays); } /// /// Begins an artificial scope block within a local function block /// /// Any input arry, given as parameter for the current function /// A new scope /// The ILScope class plays an important role for the ILNumerics memory management. When writing functions in ILNumerics, /// ILScope is used, to define blocks of artificial scopes for local function blocks. ILNumerics ensures, no memory is left as garbage, once /// such a scope block was left. Furthermore, it garantees, input arrays are kept alive during the execution of the block. By following these /// simple rules, ILNumerics is able to optimize the execution of the algorithm regarding /// execution speed and memory footprint. /// The examples demonstrates a custom function in ILNumerics. It demonstrates the use of distinct array types in the function declaration and the use of /// artificial scopes. /// FreqPeaks(ILInArray inData, ILOutArray freq = null, double sampFreq = 44.1) { /// /// using (ILScope.Enter(inData)) { /// /// ILArray Data = check(inData); /// ILArray retLength = min(ceil(Data.Length / 2.0 + 1), 5.0); /// ILArray Window = stdWindowFunc(Data.Length); /// ILArray magnitudes = abs(fft(Data * Window)); /// magnitudes = magnitudes[r(0,end / 2 + 1)]; /// /// ILArray indices = empty(); /// ILArray sorted = sort(magnitudes, indices, descending:true); /// if (!isnull(freq)) /// freq.a = (sampFreq / 2.0 / magnitudes.Length * indices)[r(0,retLength-1)]; /// return magnitudes[r(0,retLength-1)]; /// } ///}]]> /// public static IDisposable Enter(ILBaseArray inputArrays) { return new ILScope(inputArrays); } /// /// The threading context - individual for each thread /// internal static ILThreadingContext Context { get { ILThreadingContext ret = s_threadContext; if (ret == null) { s_threadContext = new ILThreadingContext(); ret = s_threadContext; } return ret; } } internal int Count = 0; internal ILScope(ILBaseArray array) { if (!object.Equals(array,null)) { Stack stack = Context.Arrays; int oldStackCount = stack.Count; if (array.EnterScope()) { stack.Push(array); } Count = stack.Count - oldStackCount; } Context.Scopes.Push(this); } internal ILScope(params ILBaseArray[] inputArrays) { if (inputArrays != null) { Stack stack = Context.Arrays; int oldStackCount = stack.Count; foreach (var a in inputArrays) { if (!object.Equals(a, null)) { if (a.EnterScope()) { stack.Push(a); } } } Count = stack.Count - oldStackCount; } Context.Scopes.Push(this); } #region IDisposable Members /// /// Dispose all arrays in this scope /// public void Dispose() { Stack stack = Context.Arrays; for (int i = Count; i-- > 0; ) { stack.Pop().LeaveScope(); } #if VERBOSE System.Diagnostics.Debug.Assert(object.Equals(Context.Scopes.Peek(), this)); System.Diagnostics.Debug.WriteLine ("Leaving scope {0} - disposing {1} arrays",Context.Scopes.Peek().GetHashCode(),Count); #endif Context.Scopes.Pop(); } #endregion } }