diff options
author | John Hurliman | 2010-09-10 12:04:12 -0700 |
---|---|---|
committer | John Hurliman | 2010-09-10 12:04:12 -0700 |
commit | dd277a0d02f1aa79f4fcb5d108cbc696e90500c2 (patch) | |
tree | 7e396d347e43504ec23c59c3749f995f15c2e254 /OpenSim/Region/Framework/Scenes/EntityManager.cs | |
parent | * Run SimianGrid session updates asynchronously instead of from the main hear... (diff) | |
download | opensim-SC_OLD-dd277a0d02f1aa79f4fcb5d108cbc696e90500c2.zip opensim-SC_OLD-dd277a0d02f1aa79f4fcb5d108cbc696e90500c2.tar.gz opensim-SC_OLD-dd277a0d02f1aa79f4fcb5d108cbc696e90500c2.tar.bz2 opensim-SC_OLD-dd277a0d02f1aa79f4fcb5d108cbc696e90500c2.tar.xz |
First pass at cleaning up thread safety in EntityManager and SceneGraph
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/EntityManager.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/EntityManager.cs | 210 |
1 files changed, 50 insertions, 160 deletions
diff --git a/OpenSim/Region/Framework/Scenes/EntityManager.cs b/OpenSim/Region/Framework/Scenes/EntityManager.cs index 099fcce..85d0a4f 100644 --- a/OpenSim/Region/Framework/Scenes/EntityManager.cs +++ b/OpenSim/Region/Framework/Scenes/EntityManager.cs | |||
@@ -34,187 +34,89 @@ using OpenMetaverse; | |||
34 | 34 | ||
35 | namespace OpenSim.Region.Framework.Scenes | 35 | namespace OpenSim.Region.Framework.Scenes |
36 | { | 36 | { |
37 | public class EntityManager : IEnumerable<EntityBase> | 37 | public class EntityManager //: IEnumerable<EntityBase> |
38 | { | 38 | { |
39 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 39 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
40 | private readonly Dictionary<UUID,EntityBase> m_eb_uuid = new Dictionary<UUID, EntityBase>(); | 40 | private readonly DoubleDictionary<UUID, uint, EntityBase> m_entities = new DoubleDictionary<UUID, uint, EntityBase>(); |
41 | private readonly Dictionary<uint, EntityBase> m_eb_localID = new Dictionary<uint, EntityBase>(); | ||
42 | //private readonly Dictionary<UUID, ScenePresence> m_pres_uuid = new Dictionary<UUID, ScenePresence>(); | ||
43 | private readonly Object m_lock = new Object(); | ||
44 | 41 | ||
45 | [Obsolete("Use Add() instead.")] | 42 | public int Count |
46 | public void Add(UUID id, EntityBase eb) | ||
47 | { | 43 | { |
48 | Add(eb); | 44 | get { return m_entities.Count; } |
49 | } | 45 | } |
50 | 46 | ||
51 | public void Add(EntityBase entity) | 47 | public void Add(EntityBase entity) |
52 | { | 48 | { |
53 | lock (m_lock) | 49 | m_entities.Add(entity.UUID, entity.LocalId, entity); |
54 | { | ||
55 | try | ||
56 | { | ||
57 | m_eb_uuid.Add(entity.UUID, entity); | ||
58 | m_eb_localID.Add(entity.LocalId, entity); | ||
59 | } | ||
60 | catch(Exception e) | ||
61 | { | ||
62 | m_log.ErrorFormat("Add Entity failed: {0}", e.Message); | ||
63 | } | ||
64 | } | ||
65 | } | ||
66 | |||
67 | public void InsertOrReplace(EntityBase entity) | ||
68 | { | ||
69 | lock (m_lock) | ||
70 | { | ||
71 | try | ||
72 | { | ||
73 | m_eb_uuid[entity.UUID] = entity; | ||
74 | m_eb_localID[entity.LocalId] = entity; | ||
75 | } | ||
76 | catch(Exception e) | ||
77 | { | ||
78 | m_log.ErrorFormat("Insert or Replace Entity failed: {0}", e.Message); | ||
79 | } | ||
80 | } | ||
81 | } | 50 | } |
82 | 51 | ||
83 | public void Clear() | 52 | public void Clear() |
84 | { | 53 | { |
85 | lock (m_lock) | 54 | m_entities.Clear(); |
86 | { | ||
87 | m_eb_uuid.Clear(); | ||
88 | m_eb_localID.Clear(); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | public int Count | ||
93 | { | ||
94 | get | ||
95 | { | ||
96 | return m_eb_uuid.Count; | ||
97 | } | ||
98 | } | 55 | } |
99 | 56 | ||
100 | public bool ContainsKey(UUID id) | 57 | public bool ContainsKey(UUID id) |
101 | { | 58 | { |
102 | try | 59 | return m_entities.ContainsKey(id); |
103 | { | ||
104 | return m_eb_uuid.ContainsKey(id); | ||
105 | } | ||
106 | catch | ||
107 | { | ||
108 | return false; | ||
109 | } | ||
110 | } | 60 | } |
111 | 61 | ||
112 | public bool ContainsKey(uint localID) | 62 | public bool ContainsKey(uint localID) |
113 | { | 63 | { |
114 | try | 64 | return m_entities.ContainsKey(localID); |
115 | { | ||
116 | return m_eb_localID.ContainsKey(localID); | ||
117 | } | ||
118 | catch | ||
119 | { | ||
120 | return false; | ||
121 | } | ||
122 | } | 65 | } |
123 | 66 | ||
124 | public bool Remove(uint localID) | 67 | public bool Remove(uint localID) |
125 | { | 68 | { |
126 | lock (m_lock) | 69 | return m_entities.Remove(localID); |
127 | { | ||
128 | try | ||
129 | { | ||
130 | bool a = false; | ||
131 | EntityBase entity; | ||
132 | if (m_eb_localID.TryGetValue(localID, out entity)) | ||
133 | a = m_eb_uuid.Remove(entity.UUID); | ||
134 | |||
135 | bool b = m_eb_localID.Remove(localID); | ||
136 | return a && b; | ||
137 | } | ||
138 | catch (Exception e) | ||
139 | { | ||
140 | m_log.ErrorFormat("Remove Entity failed for {0}", localID, e); | ||
141 | return false; | ||
142 | } | ||
143 | } | ||
144 | } | 70 | } |
145 | 71 | ||
146 | public bool Remove(UUID id) | 72 | public bool Remove(UUID id) |
147 | { | 73 | { |
148 | lock (m_lock) | 74 | return m_entities.Remove(id); |
149 | { | ||
150 | try | ||
151 | { | ||
152 | bool a = false; | ||
153 | EntityBase entity; | ||
154 | if (m_eb_uuid.TryGetValue(id, out entity)) | ||
155 | a = m_eb_localID.Remove(entity.LocalId); | ||
156 | |||
157 | bool b = m_eb_uuid.Remove(id); | ||
158 | return a && b; | ||
159 | } | ||
160 | catch (Exception e) | ||
161 | { | ||
162 | m_log.ErrorFormat("Remove Entity failed for {0}", id, e); | ||
163 | return false; | ||
164 | } | ||
165 | } | ||
166 | } | 75 | } |
167 | 76 | ||
168 | public List<EntityBase> GetAllByType<T>() | 77 | public EntityBase[] GetAllByType<T>() |
169 | { | 78 | { |
170 | List<EntityBase> tmp = new List<EntityBase>(); | 79 | List<EntityBase> tmp = new List<EntityBase>(); |
171 | 80 | ||
172 | lock (m_lock) | 81 | m_entities.ForEach( |
173 | { | 82 | delegate(EntityBase entity) |
174 | try | ||
175 | { | 83 | { |
176 | foreach (KeyValuePair<UUID, EntityBase> pair in m_eb_uuid) | 84 | if (entity is T) |
177 | { | 85 | tmp.Add(entity); |
178 | if (pair.Value is T) | ||
179 | { | ||
180 | tmp.Add(pair.Value); | ||
181 | } | ||
182 | } | ||
183 | } | 86 | } |
184 | catch (Exception e) | 87 | ); |
185 | { | ||
186 | m_log.ErrorFormat("GetAllByType failed for {0}", e); | ||
187 | tmp = null; | ||
188 | } | ||
189 | } | ||
190 | 88 | ||
191 | return tmp; | 89 | return tmp.ToArray(); |
192 | } | 90 | } |
193 | 91 | ||
194 | public List<EntityBase> GetEntities() | 92 | public EntityBase[] GetEntities() |
195 | { | 93 | { |
196 | lock (m_lock) | 94 | List<EntityBase> tmp = new List<EntityBase>(m_entities.Count); |
197 | { | 95 | m_entities.ForEach(delegate(EntityBase entity) { tmp.Add(entity); }); |
198 | return new List<EntityBase>(m_eb_uuid.Values); | 96 | return tmp.ToArray(); |
199 | } | 97 | } |
98 | |||
99 | public void ForEach(Action<EntityBase> action) | ||
100 | { | ||
101 | m_entities.ForEach(action); | ||
102 | } | ||
103 | |||
104 | public EntityBase Find(Predicate<EntityBase> predicate) | ||
105 | { | ||
106 | return m_entities.FindValue(predicate); | ||
200 | } | 107 | } |
201 | 108 | ||
202 | public EntityBase this[UUID id] | 109 | public EntityBase this[UUID id] |
203 | { | 110 | { |
204 | get | 111 | get |
205 | { | 112 | { |
206 | lock (m_lock) | 113 | EntityBase entity; |
207 | { | 114 | m_entities.TryGetValue(id, out entity); |
208 | EntityBase entity; | 115 | return entity; |
209 | if (m_eb_uuid.TryGetValue(id, out entity)) | ||
210 | return entity; | ||
211 | else | ||
212 | return null; | ||
213 | } | ||
214 | } | 116 | } |
215 | set | 117 | set |
216 | { | 118 | { |
217 | InsertOrReplace(value); | 119 | Add(value); |
218 | } | 120 | } |
219 | } | 121 | } |
220 | 122 | ||
@@ -222,50 +124,38 @@ namespace OpenSim.Region.Framework.Scenes | |||
222 | { | 124 | { |
223 | get | 125 | get |
224 | { | 126 | { |
225 | lock (m_lock) | 127 | EntityBase entity; |
226 | { | 128 | m_entities.TryGetValue(localID, out entity); |
227 | EntityBase entity; | 129 | return entity; |
228 | if (m_eb_localID.TryGetValue(localID, out entity)) | ||
229 | return entity; | ||
230 | else | ||
231 | return null; | ||
232 | } | ||
233 | } | 130 | } |
234 | set | 131 | set |
235 | { | 132 | { |
236 | InsertOrReplace(value); | 133 | Add(value); |
237 | } | 134 | } |
238 | } | 135 | } |
239 | 136 | ||
240 | public bool TryGetValue(UUID key, out EntityBase obj) | 137 | public bool TryGetValue(UUID key, out EntityBase obj) |
241 | { | 138 | { |
242 | lock (m_lock) | 139 | return m_entities.TryGetValue(key, out obj); |
243 | { | ||
244 | return m_eb_uuid.TryGetValue(key, out obj); | ||
245 | } | ||
246 | } | 140 | } |
247 | 141 | ||
248 | public bool TryGetValue(uint key, out EntityBase obj) | 142 | public bool TryGetValue(uint key, out EntityBase obj) |
249 | { | 143 | { |
250 | lock (m_lock) | 144 | return m_entities.TryGetValue(key, out obj); |
251 | { | ||
252 | return m_eb_localID.TryGetValue(key, out obj); | ||
253 | } | ||
254 | } | 145 | } |
255 | 146 | ||
256 | /// <summary> | 147 | /// <summary> |
257 | /// This could be optimised to work on the list 'live' rather than making a safe copy and iterating that. | 148 | /// This could be optimised to work on the list 'live' rather than making a safe copy and iterating that. |
258 | /// </summary> | 149 | /// </summary> |
259 | /// <returns></returns> | 150 | /// <returns></returns> |
260 | public IEnumerator<EntityBase> GetEnumerator() | 151 | //public IEnumerator<EntityBase> GetEnumerator() |
261 | { | 152 | //{ |
262 | return GetEntities().GetEnumerator(); | 153 | // return GetEntities().GetEnumerator(); |
263 | } | 154 | //} |
264 | 155 | ||
265 | IEnumerator IEnumerable.GetEnumerator() | 156 | //IEnumerator IEnumerable.GetEnumerator() |
266 | { | 157 | //{ |
267 | return GetEnumerator(); | 158 | // return GetEnumerator(); |
268 | } | 159 | //} |
269 | |||
270 | } | 160 | } |
271 | } | 161 | } |