// License: Apache 2.0. See LICENSE file in root directory. // Copyright(c) 2017 Intel Corporation. All Rights Reserved. namespace Intel.RealSense { using System; using System.Collections; using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; using ObjectFactory = System.Func; using PooledStack = System.Collections.Generic.Stack; /// /// Object pool to reuse objects, avoids allocation and GC pauses /// public static class ObjectPool { private static readonly Dictionary Pools = new Dictionary(TypeComparer.Default); private static readonly Dictionary Factories = new Dictionary(TypeComparer.Default); private class TypeComparer : IEqualityComparer { public static readonly TypeComparer Default = new TypeComparer(); public bool Equals(Type x, Type y) { return x == y; } public int GetHashCode(Type obj) { return obj.GetHashCode(); } } private static PooledStack GetPool(Type t) { Stack s; if (Pools.TryGetValue(t, out s)) { return s; } lock ((Pools as ICollection).SyncRoot) { return Pools[t] = new PooledStack(); } } private static object CreateInstance(Type t, IntPtr ptr) { Func factory; if (Factories.TryGetValue(t, out factory)) { return factory(ptr); } var ctorinfo = t.GetConstructor( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, new Type[] { typeof(IntPtr) }, null); var args = new ParameterExpression[] { Expression.Parameter(typeof(IntPtr), "ptr") }; var lambda = Expression.Lambda(Expression.New(ctorinfo, args), args).Compile(); lock ((Factories as ICollection).SyncRoot) { Factories[t] = lambda; } return lambda(ptr); } private static object Get(Type t, IntPtr ptr) { var stack = GetPool(t); lock ((stack as ICollection).SyncRoot) { if (stack.Count > 0) { Base.PooledObject obj; obj = stack.Pop(); obj.m_instance.Reset(ptr); obj.Initialize(); return obj; } } return CreateInstance(t, ptr); } /// /// Get an object from the pool, should be released back /// /// type of object /// native handle /// an object of type public static T Get(IntPtr ptr) where T : Base.PooledObject { if (ptr == IntPtr.Zero) { throw new ArgumentNullException(nameof(ptr)); } return Get(typeof(T), ptr) as T; } /// /// Return an object to the pool /// /// type of object /// object to return to pool public static void Release(T obj) where T : Base.PooledObject { var stack = GetPool(obj.GetType()); lock ((stack as ICollection).SyncRoot) { stack.Push(obj); } } } }