Skip to content

Commit 0f7cf44

Browse files
committed
Pool more types (fixes #31).
1 parent f550c56 commit 0f7cf44

File tree

8 files changed

+395
-351
lines changed

8 files changed

+395
-351
lines changed

LibTessDotNet/Sources/Dict.cs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,30 +39,58 @@ namespace LibTessDotNet
3939
{
4040
internal class Dict<TValue> where TValue : class
4141
{
42-
public class Node
42+
public class Node : Pooled<Node>
4343
{
4444
internal TValue _key;
4545
internal Node _prev, _next;
4646

4747
public TValue Key { get { return _key; } }
4848
public Node Prev { get { return _prev; } }
4949
public Node Next { get { return _next; } }
50+
51+
public void Init(IPool pool)
52+
{
53+
_key = null;
54+
_prev = null;
55+
_next = null;
56+
}
57+
58+
public void Reset(IPool pool)
59+
{
60+
_key = null;
61+
_prev = null;
62+
_next = null;
63+
}
5064
}
5165

5266
public delegate bool LessOrEqual(TValue lhs, TValue rhs);
5367

68+
private IPool _pool;
5469
private LessOrEqual _leq;
5570
Node _head;
5671

57-
public Dict(LessOrEqual leq)
72+
public bool Empty { get { return _head._next == _head; } }
73+
74+
public Dict(IPool pool, LessOrEqual leq)
5875
{
76+
_pool = pool;
5977
_leq = leq;
6078

61-
_head = new Node { _key = null };
79+
Init();
80+
}
81+
82+
public void Init()
83+
{
84+
_head = _pool.Get<Node>();
6285
_head._prev = _head;
6386
_head._next = _head;
6487
}
6588

89+
public void Reset()
90+
{
91+
_pool.Return(ref _head);
92+
}
93+
6694
public Node Insert(TValue key)
6795
{
6896
return InsertBefore(_head, key);
@@ -74,7 +102,8 @@ public Node InsertBefore(Node node, TValue key)
74102
node = node._prev;
75103
} while (node._key != null && !_leq(node._key, key));
76104

77-
var newNode = new Node { _key = key };
105+
var newNode = _pool.Get<Node>();
106+
newNode._key = key;
78107
newNode._next = node._next;
79108
node._next._prev = newNode;
80109
newNode._prev = node;
@@ -101,6 +130,7 @@ public void Remove(Node node)
101130
{
102131
node._next._prev = node._prev;
103132
node._prev._next = node._next;
133+
_pool.Return(ref node);
104134
}
105135
}
106136
}

LibTessDotNet/Sources/Mesh.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,18 +87,18 @@ public void Reset(IPool pool)
8787
for (MeshUtils.Face f = _fHead, fNext = _fHead; f._next != null; f = fNext)
8888
{
8989
fNext = f._next;
90-
pool.Return(f);
90+
pool.Return(ref f);
9191
}
9292
for (MeshUtils.Vertex v = _vHead, vNext = _vHead; v._next != null; v = vNext)
9393
{
9494
vNext = v._next;
95-
pool.Return(v);
95+
pool.Return(ref v);
9696
}
9797
for (MeshUtils.Edge e = _eHead, eNext = _eHead; e._next != null; e = eNext)
9898
{
9999
eNext = e._next;
100-
pool.Return(e._Sym);
101-
pool.Return(e);
100+
pool.Return(ref e._Sym);
101+
pool.Return(ref e);
102102
}
103103

104104
_vHead = null;
@@ -389,7 +389,7 @@ public void ZapFace(IPool pool, MeshUtils.Face fZap)
389389
fNext._prev = fPrev;
390390
fPrev._next = fNext;
391391

392-
pool.Return(fZap);
392+
pool.Return(ref fZap);
393393
}
394394

395395
public void MergeConvexFaces(IPool pool, int maxVertsPerFace)

LibTessDotNet/Sources/MeshUtils.cs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,7 @@ public interface ITypePool
127127
{
128128
private Queue<T> _pool = new Queue<T>();
129129

130-
private static readonly Func<T> OptimizedInstantiator = Expression.Lambda<Func<T>>(
131-
Expression.New(typeof(T))
132-
).Compile();
130+
private static readonly Func<T> Creator = Expression.Lambda<Func<T>>(Expression.New(typeof(T))).Compile();
133131

134132
public object Get()
135133
{
@@ -140,7 +138,7 @@ public object Get()
140138
return _pool.Dequeue();
141139
}
142140
}
143-
return OptimizedInstantiator.Invoke();
141+
return Creator();
144142
}
145143

146144
public void Return(object obj)
@@ -165,14 +163,16 @@ public abstract class IPool
165163
{
166164
public IPool()
167165
{
166+
Register<Mesh>(new DefaultTypePool<Mesh>());
168167
Register<MeshUtils.Vertex>(new DefaultTypePool<MeshUtils.Vertex>());
169168
Register<MeshUtils.Face>(new DefaultTypePool<MeshUtils.Face>());
170169
Register<MeshUtils.Edge>(new DefaultTypePool<MeshUtils.Edge>());
171170
Register<Tess.ActiveRegion>(new DefaultTypePool<Tess.ActiveRegion>());
171+
Register<Dict<Tess.ActiveRegion>.Node>(new DefaultTypePool<Dict<Tess.ActiveRegion>.Node>());
172172
}
173173
public abstract void Register<T>(ITypePool typePool) where T : class, Pooled<T>, new();
174174
public abstract T Get<T>() where T : class, Pooled<T>, new();
175-
public abstract void Return<T>(T obj) where T : class, Pooled<T>, new();
175+
public abstract void Return<T>(ref T obj) where T : class, Pooled<T>, new();
176176
}
177177

178178
public class NullPool : IPool
@@ -188,8 +188,9 @@ public override void Register<T>(ITypePool typePool)
188188
{
189189
}
190190

191-
public override void Return<T>(T obj)
191+
public override void Return<T>(ref T obj)
192192
{
193+
obj = null;
193194
}
194195
}
195196

@@ -217,13 +218,13 @@ public override T Get<T>()
217218
}
218219
if (obj == null)
219220
{
220-
obj = new T();
221+
throw new InvalidOperationException("Type not registered with type tool");
221222
}
222223
obj.Init(this);
223224
return obj;
224225
}
225226

226-
public override void Return<T>(T obj)
227+
public override void Return<T>(ref T obj)
227228
{
228229
if (obj == null)
229230
{
@@ -235,6 +236,7 @@ public override void Return<T>(T obj)
235236
{
236237
typePool.Return(obj);
237238
}
239+
obj = null;
238240
}
239241
}
240242

@@ -514,8 +516,8 @@ public static void KillEdge(IPool pool, Edge eDel)
514516
eNext._Sym._next = ePrev;
515517
ePrev._Sym._next = eNext;
516518

517-
pool.Return(eDel._Sym);
518-
pool.Return(eDel);
519+
pool.Return(ref eDel._Sym);
520+
pool.Return(ref eDel);
519521
}
520522

521523
/// <summary>
@@ -539,7 +541,7 @@ public static void KillVertex(IPool pool, Vertex vDel, Vertex newOrg)
539541
vNext._prev = vPrev;
540542
vPrev._next = vNext;
541543

542-
pool.Return(vDel);
544+
pool.Return(ref vDel);
543545
}
544546

545547
/// <summary>
@@ -563,7 +565,7 @@ public static void KillFace(IPool pool, Face fDel, Face newLFace)
563565
fNext._prev = fPrev;
564566
fPrev._next = fNext;
565567

566-
pool.Return(fDel);
568+
pool.Return(ref fDel);
567569
}
568570

569571
/// <summary>

LibTessDotNet/Sources/PriorityHeap.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ internal class PriorityHeap<TValue> where TValue : class
5050
{
5151
public delegate bool LessOrEqual(TValue lhs, TValue rhs);
5252

53-
protected class HandleElem
53+
internal class HandleElem
5454
{
5555
internal TValue _key;
5656
internal int _node;
@@ -78,7 +78,7 @@ public PriorityHeap(int initialSize, LessOrEqual leq)
7878
_initialized = false;
7979

8080
_nodes[1] = 1;
81-
_handles[1] = new HandleElem { _key = null };
81+
_handles[1] = new HandleElem();
8282
}
8383

8484
private void FloatDown(int curr)

LibTessDotNet/Sources/PriorityQueue.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public PriorityQueue(int initialSize, PriorityHeap<TValue>.LessOrEqual leq)
6565
_initialized = false;
6666
}
6767

68-
class StackItem
68+
struct StackItem
6969
{
7070
internal int p, r;
7171
};

LibTessDotNet/Sources/Sweep.cs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public void Init(IPool pool)
5858
public void Reset(IPool pool)
5959
{
6060
_eUp = null;
61-
_nodeUp = null;
61+
_nodeUp = null; // don't return to pool as Dict takes care of that
6262
_windingNumber = 0;
6363
_inside = false;
6464
_sentinel = false;
@@ -129,7 +129,7 @@ private void DeleteRegion(ActiveRegion reg)
129129
}
130130
reg._eUp._activeRegion = null;
131131
_dict.Remove(reg._nodeUp);
132-
_pool.Return(reg);
132+
_pool.Return(ref reg);
133133
}
134134

135135
/// <summary>
@@ -609,7 +609,7 @@ private bool CheckForIntersect(ActiveRegion regUp)
609609
{
610610
// Easy case -- intersection at one of the right endpoints
611611
CheckForRightSplice(regUp);
612-
_pool.Return(isect);
612+
_pool.Return(ref isect);
613613
return false;
614614
}
615615

@@ -630,7 +630,7 @@ private bool CheckForIntersect(ActiveRegion regUp)
630630
eUp = RegionBelow(regUp)._eUp;
631631
FinishLeftRegions(RegionBelow(regUp), regLo);
632632
AddRightEdges(regUp, eUp._Oprev, eUp, eUp, true);
633-
_pool.Return(isect);
633+
_pool.Return(ref isect);
634634
return true;
635635
}
636636
if( dstUp == _event ) {
@@ -643,7 +643,7 @@ private bool CheckForIntersect(ActiveRegion regUp)
643643
regLo._eUp = eLo._Oprev;
644644
eLo = FinishLeftRegions(regLo, null);
645645
AddRightEdges(regUp, eLo._Onext, eUp._Rprev, e, true);
646-
_pool.Return(isect);
646+
_pool.Return(ref isect);
647647
return true;
648648
}
649649
// Special case: called from ConnectRightVertex. If either
@@ -664,7 +664,7 @@ private bool CheckForIntersect(ActiveRegion regUp)
664664
eLo._Org._t = _event._t;
665665
}
666666
// leave the rest for ConnectRightVertex
667-
_pool.Return(isect);
667+
_pool.Return(ref isect);
668668
return false;
669669
}
670670

@@ -680,7 +680,7 @@ private bool CheckForIntersect(ActiveRegion regUp)
680680
_mesh.Splice(_pool, eLo._Oprev, eUp);
681681
eUp._Org._s = isect._s;
682682
eUp._Org._t = isect._t;
683-
_pool.Return(isect);
683+
_pool.Return(ref isect);
684684
isect = null;
685685
eUp._Org._pqHandle = _pq.Insert(eUp._Org);
686686
if (eUp._Org._pqHandle._handle == PQHandle.Invalid)
@@ -933,7 +933,7 @@ private void ConnectLeftVertex(MeshUtils.Vertex vEvent)
933933
// Get a pointer to the active region containing vEvent
934934
tmp._eUp = vEvent._anEdge._Sym;
935935
var regUp = _dict.Find(tmp).Key;
936-
_pool.Return(tmp);
936+
_pool.Return(ref tmp);
937937
var regLo = RegionBelow(regUp);
938938
if (regLo == null)
939939
{
@@ -1064,7 +1064,14 @@ private void AddSentinel(Real smin, Real smax, Real t)
10641064
/// </summary>
10651065
private void InitEdgeDict()
10661066
{
1067-
_dict = new Dict<ActiveRegion>(EdgeLeq);
1067+
if (_dict == null)
1068+
{
1069+
_dict = new Dict<ActiveRegion>(_pool, EdgeLeq);
1070+
}
1071+
else
1072+
{
1073+
_dict.Init();
1074+
}
10681075

10691076
AddSentinel(-SentinelCoord, SentinelCoord, -SentinelCoord);
10701077
AddSentinel(-SentinelCoord, SentinelCoord, +SentinelCoord);
@@ -1089,7 +1096,8 @@ private void DoneEdgeDict()
10891096
DeleteRegion(reg);
10901097
}
10911098

1092-
_dict = null;
1099+
Debug.Assert(_dict.Empty);
1100+
_dict.Reset();
10931101
}
10941102

10951103
/// <summary>
@@ -1149,8 +1157,11 @@ private void InitPriorityQ()
11491157
}
11501158
// Make sure there is enough space for sentinels.
11511159
vertexCount += 8;
1152-
1153-
_pq = new PriorityQueue<MeshUtils.Vertex>(vertexCount, Geom.VertLeq);
1160+
1161+
if (_pq == null)
1162+
{
1163+
_pq = new PriorityQueue<MeshUtils.Vertex>(vertexCount, Geom.VertLeq);
1164+
}
11541165

11551166
vHead = _mesh._vHead;
11561167
for( v = vHead._next; v != vHead; v = v._next ) {
@@ -1165,7 +1176,7 @@ private void InitPriorityQ()
11651176

11661177
private void DonePriorityQ()
11671178
{
1168-
_pq = null;
1179+
Debug.Assert(_pq.Empty);
11691180
}
11701181

11711182
/// <summary>

LibTessDotNet/Sources/Tess.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -199,15 +199,16 @@ public Tess()
199199
}
200200
public Tess(IPool pool)
201201
{
202+
if (pool == null)
203+
{
204+
throw new ArgumentNullException("pool");
205+
}
206+
202207
_normal = Vec3.Zero;
203208
_bminX = _bminY = _bmaxX = _bmaxY = 0;
204209

205210
_windingRule = WindingRule.EvenOdd;
206211
_pool = pool;
207-
if (_pool == null)
208-
{
209-
_pool = new NullPool();
210-
}
211212
_mesh = null;
212213

213214
_vertices = null;
@@ -845,8 +846,7 @@ public void Tessellate(WindingRule windingRule = WindingRule.EvenOdd, ElementTyp
845846
OutputPolymesh(elementType, polySize);
846847
}
847848

848-
_pool.Return(_mesh);
849-
_mesh = null;
849+
_pool.Return(ref _mesh);
850850
}
851851
}
852852
}

0 commit comments

Comments
 (0)