-
Notifications
You must be signed in to change notification settings - Fork 4.8k
/
ObjectPool.cs
125 lines (109 loc) · 3.92 KB
/
ObjectPool.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// 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<System.IntPtr, object>;
using PooledStack = System.Collections.Generic.Stack<Base.PooledObject>;
/// <summary>
/// Object pool to reuse objects, avoids allocation and GC pauses
/// </summary>
public static class ObjectPool
{
private static readonly Dictionary<Type, PooledStack> Pools = new Dictionary<Type, PooledStack>(TypeComparer.Default);
private static readonly Dictionary<Type, ObjectFactory> Factories = new Dictionary<Type, ObjectFactory>(TypeComparer.Default);
private class TypeComparer : IEqualityComparer<Type>
{
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<Base.PooledObject> 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<IntPtr, object> 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<ObjectFactory>(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);
}
/// <summary>
/// Get an object from the pool, should be released back
/// </summary>
/// <typeparam name="T">type of object</typeparam>
/// <param name="ptr">native handle</param>
/// <returns>an object of type <typeparamref name="T"/></returns>
public static T Get<T>(IntPtr ptr)
where T : Base.PooledObject
{
if (ptr == IntPtr.Zero)
{
throw new ArgumentNullException(nameof(ptr));
}
return Get(typeof(T), ptr) as T;
}
/// <summary>
/// Return an object to the pool
/// </summary>
/// <typeparam name="T">type of object</typeparam>
/// <param name="obj">object to return to pool</param>
public static void Release<T>(T obj)
where T : Base.PooledObject
{
var stack = GetPool(obj.GetType());
lock ((stack as ICollection).SyncRoot)
{
stack.Push(obj);
}
}
}
}