namespace GMap.NET.Internals { using System.Collections.Generic; using System.Threading; using System.Diagnostics; using System; /// /// matrix for tiles /// internal class TileMatrix : IDisposable { List> Levels = new List>(33); FastReaderWriterLock Lock = new FastReaderWriterLock(); public TileMatrix() { for(int i = 0; i < Levels.Capacity; i++) { Levels.Add(new Dictionary(55)); } } public void ClearAllLevels() { Lock.AcquireWriterLock(); try { foreach(var matrix in Levels) { foreach(var t in matrix) { t.Value.Dispose(); } matrix.Clear(); } } finally { Lock.ReleaseWriterLock(); } } public void ClearLevel(int zoom) { Lock.AcquireWriterLock(); try { if(zoom < Levels.Count) { var l = Levels[zoom]; foreach(var t in l) { t.Value.Dispose(); } l.Clear(); } } finally { Lock.ReleaseWriterLock(); } } List> tmp = new List>(44); public void ClearLevelAndPointsNotIn(int zoom, List list) { Lock.AcquireWriterLock(); try { if(zoom < Levels.Count) { var l = Levels[zoom]; tmp.Clear(); foreach(var t in l) { if(!list.Exists(p => p.PosXY == t.Key)) { tmp.Add(t); } } foreach(var r in tmp) { l.Remove(r.Key); r.Value.Dispose(); } tmp.Clear(); } } finally { Lock.ReleaseWriterLock(); } } public void ClearLevelsBelove(int zoom) { Lock.AcquireWriterLock(); try { if(zoom - 1 < Levels.Count) { for(int i = zoom - 1; i >= 0; i--) { var l = Levels[i]; foreach(var t in l) { t.Value.Dispose(); } l.Clear(); } } } finally { Lock.ReleaseWriterLock(); } } public void ClearLevelsAbove(int zoom) { Lock.AcquireWriterLock(); try { if(zoom + 1 < Levels.Count) { for(int i = zoom + 1; i < Levels.Count; i++) { var l = Levels[i]; foreach(var t in l) { t.Value.Dispose(); } l.Clear(); } } } finally { Lock.ReleaseWriterLock(); } } public void EnterReadLock() { Lock.AcquireReaderLock(); } public void LeaveReadLock() { Lock.ReleaseReaderLock(); } public Tile GetTileWithNoLock(int zoom, GPoint p) { Tile ret = Tile.Empty; //if(zoom < Levels.Count) { Levels[zoom].TryGetValue(p, out ret); } return ret; } public Tile GetTileWithReadLock(int zoom, GPoint p) { Tile ret = Tile.Empty; Lock.AcquireReaderLock(); try { ret = GetTileWithNoLock(zoom, p); } finally { Lock.ReleaseReaderLock(); } return ret; } public void SetTile(Tile t) { Lock.AcquireWriterLock(); try { if(t.Zoom < Levels.Count) { Levels[t.Zoom][t.Pos] = t; } } finally { Lock.ReleaseWriterLock(); } } #region IDisposable Members ~TileMatrix() { Dispose(false); } void Dispose(bool disposing) { if(Lock != null) { if(disposing) { ClearAllLevels(); } Levels.Clear(); Levels = null; tmp.Clear(); tmp = null; Lock.Dispose(); Lock = null; } } public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } #endregion } }