1 /*
2  *  This file is part of the "GKMap".
3  *  GKMap project borrowed from GMap.NET (by radioman).
4  *
5  *  Copyright (C) 2009-2018 by radioman (email@radioman.lt).
6  *  This program is licensed under the FLAT EARTH License.
7  */
8 
9 using System;
10 using System.Collections.Generic;
11 
12 namespace GKMap
13 {
14     /// <summary>
15     /// matrix for tiles
16     /// </summary>
17     internal class TileMatrix : IDisposable
18     {
19         private List<Dictionary<GPoint, Tile>> fLevels;
20         private RWLock fLock;
21         private List<KeyValuePair<GPoint, Tile>> fTemp;
22 
TileMatrix()23         public TileMatrix()
24         {
25             fLevels = new List<Dictionary<GPoint, Tile>>(33);
26             fLock = new RWLock();
27             fTemp = new List<KeyValuePair<GPoint, Tile>>(44);
28 
29             for (int i = 0; i < fLevels.Capacity; i++) {
30                 fLevels.Add(new Dictionary<GPoint, Tile>(55, new GPointComparer()));
31             }
32         }
33 
ClearAllLevels()34         public void ClearAllLevels()
35         {
36             fLock.AcquireWriterLock();
37             try {
38                 foreach (var matrix in fLevels) {
39                     foreach (var t in matrix) {
40                         t.Value.Dispose();
41                     }
42                     matrix.Clear();
43                 }
44             } finally {
45                 fLock.ReleaseWriterLock();
46             }
47         }
48 
ClearLevel(int zoom)49         public void ClearLevel(int zoom)
50         {
51             fLock.AcquireWriterLock();
52             try {
53                 if (zoom < fLevels.Count) {
54                     var l = fLevels[zoom];
55 
56                     foreach (var t in l) {
57                         t.Value.Dispose();
58                     }
59 
60                     l.Clear();
61                 }
62             } finally {
63                 fLock.ReleaseWriterLock();
64             }
65         }
66 
ClearLevelAndPointsNotIn(int zoom, List<DrawTile> list)67         public void ClearLevelAndPointsNotIn(int zoom, List<DrawTile> list)
68         {
69             fLock.AcquireWriterLock();
70             try {
71                 if (zoom < fLevels.Count) {
72                     var l = fLevels[zoom];
73 
74                     fTemp.Clear();
75 
76                     foreach (var t in l) {
77                         if (!list.Exists(p => p.PosXY == t.Key)) {
78                             fTemp.Add(t);
79                         }
80                     }
81 
82                     foreach (var r in fTemp) {
83                         l.Remove(r.Key);
84                         r.Value.Dispose();
85                     }
86 
87                     fTemp.Clear();
88                 }
89             } finally {
90                 fLock.ReleaseWriterLock();
91             }
92         }
93 
ClearLevelsBelow(int zoom)94         public void ClearLevelsBelow(int zoom)
95         {
96             fLock.AcquireWriterLock();
97             try {
98                 if (zoom - 1 < fLevels.Count) {
99                     for (int i = zoom - 1; i >= 0; i--) {
100                         var l = fLevels[i];
101 
102                         foreach (var t in l) {
103                             t.Value.Dispose();
104                         }
105 
106                         l.Clear();
107                     }
108                 }
109             } finally {
110                 fLock.ReleaseWriterLock();
111             }
112         }
113 
ClearLevelsAbove(int zoom)114         public void ClearLevelsAbove(int zoom)
115         {
116             fLock.AcquireWriterLock();
117             try {
118                 if (zoom + 1 < fLevels.Count) {
119                     for (int i = zoom + 1; i < fLevels.Count; i++) {
120                         var l = fLevels[i];
121 
122                         foreach (var t in l) {
123                             t.Value.Dispose();
124                         }
125 
126                         l.Clear();
127                     }
128                 }
129             } finally {
130                 fLock.ReleaseWriterLock();
131             }
132         }
133 
EnterReadLock()134         public void EnterReadLock()
135         {
136             fLock.AcquireReaderLock();
137         }
138 
LeaveReadLock()139         public void LeaveReadLock()
140         {
141             fLock.ReleaseReaderLock();
142         }
143 
GetTileWithNoLock(int zoom, GPoint p)144         public Tile GetTileWithNoLock(int zoom, GPoint p)
145         {
146             Tile ret;
147             fLevels[zoom].TryGetValue(p, out ret);
148 
149             return ret;
150         }
151 
GetTileWithReadLock(int zoom, GPoint p)152         public Tile GetTileWithReadLock(int zoom, GPoint p)
153         {
154             Tile ret;
155 
156             fLock.AcquireReaderLock();
157             try {
158                 ret = GetTileWithNoLock(zoom, p);
159             } finally {
160                 fLock.ReleaseReaderLock();
161             }
162 
163             return ret;
164         }
165 
SetTile(Tile t)166         public void SetTile(Tile t)
167         {
168             fLock.AcquireWriterLock();
169             try {
170                 if (t.Zoom < fLevels.Count) {
171                     fLevels[t.Zoom][t.Pos] = t;
172                 }
173             } finally {
174                 fLock.ReleaseWriterLock();
175             }
176         }
177 
~TileMatrix()178         ~TileMatrix()
179         {
180             Dispose(false);
181         }
182 
Dispose(bool disposing)183         void Dispose(bool disposing)
184         {
185             if (fLock != null) {
186                 if (disposing) {
187                     ClearAllLevels();
188                 }
189 
190                 fLevels.Clear();
191                 fLevels = null;
192 
193                 fTemp.Clear();
194                 fTemp = null;
195 
196                 fLock.Dispose();
197                 fLock = null;
198             }
199         }
200 
Dispose()201         public void Dispose()
202         {
203             this.Dispose(true);
204             GC.SuppressFinalize(this);
205         }
206     }
207 }
208