aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorCasperW2009-11-27 18:29:03 +0100
committerCasperW2009-11-30 21:17:15 +0100
commit9888f95068373f1bfdb289e85560a7d873d22696 (patch)
tree406867a636ba643eb91d7af860a8b01b73e11a51 /OpenSim/Region
parentMerge branch 'master' into careminster (diff)
downloadopensim-SC_OLD-9888f95068373f1bfdb289e85560a7d873d22696.zip
opensim-SC_OLD-9888f95068373f1bfdb289e85560a7d873d22696.tar.gz
opensim-SC_OLD-9888f95068373f1bfdb289e85560a7d873d22696.tar.bz2
opensim-SC_OLD-9888f95068373f1bfdb289e85560a7d873d22696.tar.xz
Convert multiple lock()s which directly hinder script performance in linksets to ReaderWriterLockSlim.
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs400
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs11
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs415
3 files changed, 531 insertions, 295 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 26a843e..fb34ddc 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -98,6 +98,66 @@ namespace OpenSim.Region.Framework.Scenes
98 private bool m_hasGroupChanged = false; 98 private bool m_hasGroupChanged = false;
99 private long timeFirstChanged; 99 private long timeFirstChanged;
100 private long timeLastChanged; 100 private long timeLastChanged;
101 private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim();
102
103 public void lockPartsForRead(bool locked)
104 {
105 if (locked)
106 {
107 if (m_partsLock.RecursiveReadCount > 0)
108 {
109 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
110 m_partsLock.ExitReadLock();
111 }
112 if (m_partsLock.RecursiveWriteCount > 0)
113 {
114 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed.");
115 m_partsLock.ExitWriteLock();
116 }
117
118 while (!m_partsLock.TryEnterReadLock(60000))
119 {
120 m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire READ lock of m_parts in SceneObjectGroup. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
121 if (m_partsLock.IsWriteLockHeld)
122 {
123 m_partsLock = new System.Threading.ReaderWriterLockSlim();
124 }
125 }
126 }
127 else
128 {
129 m_partsLock.ExitReadLock();
130 }
131 }
132 public void lockPartsForWrite(bool locked)
133 {
134 if (locked)
135 {
136 if (m_partsLock.RecursiveReadCount > 0)
137 {
138 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
139 m_partsLock.ExitReadLock();
140 }
141 if (m_partsLock.RecursiveWriteCount > 0)
142 {
143 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
144 m_partsLock.ExitWriteLock();
145 }
146
147 while (!m_partsLock.TryEnterWriteLock(60000))
148 {
149 m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
150 if (m_partsLock.IsWriteLockHeld)
151 {
152 m_partsLock = new System.Threading.ReaderWriterLockSlim();
153 }
154 }
155 }
156 else
157 {
158 m_partsLock.ExitWriteLock();
159 }
160 }
101 161
102 public bool HasGroupChanged 162 public bool HasGroupChanged
103 { 163 {
@@ -243,13 +303,16 @@ namespace OpenSim.Region.Framework.Scenes
243 set 303 set
244 { 304 {
245 m_regionHandle = value; 305 m_regionHandle = value;
246 lock (m_parts) 306 lockPartsForRead(true);
247 { 307 {
248 foreach (SceneObjectPart part in m_parts.Values) 308 foreach (SceneObjectPart part in m_parts.Values)
249 { 309 {
310
250 part.RegionHandle = m_regionHandle; 311 part.RegionHandle = m_regionHandle;
312
251 } 313 }
252 } 314 }
315 lockPartsForRead(false);
253 } 316 }
254 } 317 }
255 318
@@ -275,13 +338,16 @@ namespace OpenSim.Region.Framework.Scenes
275 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 338 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
276 } 339 }
277 340
278 lock (m_parts) 341 lockPartsForRead(true);
279 { 342 {
280 foreach (SceneObjectPart part in m_parts.Values) 343 foreach (SceneObjectPart part in m_parts.Values)
281 { 344 {
345
282 part.GroupPosition = val; 346 part.GroupPosition = val;
347
283 } 348 }
284 } 349 }
350 lockPartsForRead(false);
285 351
286 //if (m_rootPart.PhysActor != null) 352 //if (m_rootPart.PhysActor != null)
287 //{ 353 //{
@@ -432,13 +498,16 @@ namespace OpenSim.Region.Framework.Scenes
432 498
433 public void SetFromItemID(UUID AssetId) 499 public void SetFromItemID(UUID AssetId)
434 { 500 {
435 lock (m_parts) 501 lockPartsForRead(true);
436 { 502 {
437 foreach (SceneObjectPart part in m_parts.Values) 503 foreach (SceneObjectPart part in m_parts.Values)
438 { 504 {
505
439 part.FromItemID = AssetId; 506 part.FromItemID = AssetId;
507
440 } 508 }
441 } 509 }
510 lockPartsForRead(false);
442 } 511 }
443 512
444 public UUID GetFromItemID() 513 public UUID GetFromItemID()
@@ -505,10 +574,11 @@ namespace OpenSim.Region.Framework.Scenes
505 Vector3 maxScale = Vector3.Zero; 574 Vector3 maxScale = Vector3.Zero;
506 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 575 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
507 576
508 lock (m_parts) 577 lockPartsForRead(true);
509 { 578 {
510 foreach (SceneObjectPart part in m_parts.Values) 579 foreach (SceneObjectPart part in m_parts.Values)
511 { 580 {
581
512 Vector3 partscale = part.Scale; 582 Vector3 partscale = part.Scale;
513 Vector3 partoffset = part.OffsetPosition; 583 Vector3 partoffset = part.OffsetPosition;
514 584
@@ -519,8 +589,11 @@ namespace OpenSim.Region.Framework.Scenes
519 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 589 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
520 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; 590 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
521 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; 591 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
592
522 } 593 }
523 } 594 }
595 lockPartsForRead(false);
596
524 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 597 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
525 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 598 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
526 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 599 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -536,10 +609,11 @@ namespace OpenSim.Region.Framework.Scenes
536 609
537 EntityIntersection result = new EntityIntersection(); 610 EntityIntersection result = new EntityIntersection();
538 611
539 lock (m_parts) 612 lockPartsForRead(true);
540 { 613 {
541 foreach (SceneObjectPart part in m_parts.Values) 614 foreach (SceneObjectPart part in m_parts.Values)
542 { 615 {
616
543 // Temporary commented to stop compiler warning 617 // Temporary commented to stop compiler warning
544 //Vector3 partPosition = 618 //Vector3 partPosition =
545 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 619 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -567,8 +641,10 @@ namespace OpenSim.Region.Framework.Scenes
567 result.distance = inter.distance; 641 result.distance = inter.distance;
568 } 642 }
569 } 643 }
644
570 } 645 }
571 } 646 }
647 lockPartsForRead(false);
572 return result; 648 return result;
573 } 649 }
574 650
@@ -581,10 +657,11 @@ namespace OpenSim.Region.Framework.Scenes
581 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 657 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
582 { 658 {
583 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; 659 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f;
584 lock (m_parts) 660 lockPartsForRead(true);
585 { 661 {
586 foreach (SceneObjectPart part in m_parts.Values) 662 foreach (SceneObjectPart part in m_parts.Values)
587 { 663 {
664
588 Vector3 worldPos = part.GetWorldPosition(); 665 Vector3 worldPos = part.GetWorldPosition();
589 Vector3 offset = worldPos - AbsolutePosition; 666 Vector3 offset = worldPos - AbsolutePosition;
590 Quaternion worldRot; 667 Quaternion worldRot;
@@ -643,6 +720,8 @@ namespace OpenSim.Region.Framework.Scenes
643 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 720 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
644 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 721 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
645 722
723
724
646 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 725 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
647 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 726 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
648 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 727 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -814,6 +893,7 @@ namespace OpenSim.Region.Framework.Scenes
814 minZ = backBottomLeft.Z; 893 minZ = backBottomLeft.Z;
815 } 894 }
816 } 895 }
896 lockPartsForRead(false);
817 897
818 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); 898 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
819 899
@@ -842,17 +922,20 @@ namespace OpenSim.Region.Framework.Scenes
842 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 922 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
843 923
844 // Capture script state while holding the lock 924 // Capture script state while holding the lock
845 lock (m_parts) 925 lockPartsForRead(true);
846 { 926 {
847 foreach (SceneObjectPart part in m_parts.Values) 927 foreach (SceneObjectPart part in m_parts.Values)
848 { 928 {
929
849 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 930 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates();
850 foreach (UUID itemid in pstates.Keys) 931 foreach (UUID itemid in pstates.Keys)
851 { 932 {
852 states.Add(itemid, pstates[itemid]); 933 states.Add(itemid, pstates[itemid]);
853 } 934 }
935
854 } 936 }
855 } 937 }
938 lockPartsForRead(false);
856 939
857 if (states.Count > 0) 940 if (states.Count > 0)
858 { 941 {
@@ -1014,13 +1097,16 @@ namespace OpenSim.Region.Framework.Scenes
1014 1097
1015 public override void UpdateMovement() 1098 public override void UpdateMovement()
1016 { 1099 {
1017 lock (m_parts) 1100 lockPartsForRead(true);
1018 { 1101 {
1019 foreach (SceneObjectPart part in m_parts.Values) 1102 foreach (SceneObjectPart part in m_parts.Values)
1020 { 1103 {
1104
1021 part.UpdateMovement(); 1105 part.UpdateMovement();
1106
1022 } 1107 }
1023 } 1108 }
1109 lockPartsForRead(false);
1024 } 1110 }
1025 1111
1026 public ushort GetTimeDilation() 1112 public ushort GetTimeDilation()
@@ -1064,7 +1150,7 @@ namespace OpenSim.Region.Framework.Scenes
1064 /// <param name="part"></param> 1150 /// <param name="part"></param>
1065 public void AddPart(SceneObjectPart part) 1151 public void AddPart(SceneObjectPart part)
1066 { 1152 {
1067 lock (m_parts) 1153 lockPartsForWrite(true);
1068 { 1154 {
1069 part.SetParent(this); 1155 part.SetParent(this);
1070 m_parts.Add(part.UUID, part); 1156 m_parts.Add(part.UUID, part);
@@ -1074,6 +1160,7 @@ namespace OpenSim.Region.Framework.Scenes
1074 if (part.LinkNum == 2 && RootPart != null) 1160 if (part.LinkNum == 2 && RootPart != null)
1075 RootPart.LinkNum = 1; 1161 RootPart.LinkNum = 1;
1076 } 1162 }
1163 lockPartsForWrite(false);
1077 } 1164 }
1078 1165
1079 /// <summary> 1166 /// <summary>
@@ -1081,28 +1168,33 @@ namespace OpenSim.Region.Framework.Scenes
1081 /// </summary> 1168 /// </summary>
1082 private void UpdateParentIDs() 1169 private void UpdateParentIDs()
1083 { 1170 {
1084 lock (m_parts) 1171 lockPartsForRead(true);
1085 { 1172 {
1086 foreach (SceneObjectPart part in m_parts.Values) 1173 foreach (SceneObjectPart part in m_parts.Values)
1087 { 1174 {
1175
1088 if (part.UUID != m_rootPart.UUID) 1176 if (part.UUID != m_rootPart.UUID)
1089 { 1177 {
1090 part.ParentID = m_rootPart.LocalId; 1178 part.ParentID = m_rootPart.LocalId;
1091 } 1179 }
1180
1092 } 1181 }
1093 } 1182 }
1183 lockPartsForRead(false);
1094 } 1184 }
1095 1185
1096 public void RegenerateFullIDs() 1186 public void RegenerateFullIDs()
1097 { 1187 {
1098 lock (m_parts) 1188 lockPartsForRead(true);
1099 { 1189 {
1100 foreach (SceneObjectPart part in m_parts.Values) 1190 foreach (SceneObjectPart part in m_parts.Values)
1101 { 1191 {
1192
1102 part.UUID = UUID.Random(); 1193 part.UUID = UUID.Random();
1103 1194
1104 } 1195 }
1105 } 1196 }
1197 lockPartsForRead(false);
1106 } 1198 }
1107 1199
1108 // helper provided for parts. 1200 // helper provided for parts.
@@ -1183,29 +1275,33 @@ namespace OpenSim.Region.Framework.Scenes
1183 1275
1184 DetachFromBackup(); 1276 DetachFromBackup();
1185 1277
1186 lock (m_parts) 1278 lockPartsForRead(true);
1279 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1280 lockPartsForRead(false);
1281
1282 foreach (SceneObjectPart part in values)
1187 { 1283 {
1188 foreach (SceneObjectPart part in m_parts.Values)
1189 {
1190// part.Inventory.RemoveScriptInstances(); 1284// part.Inventory.RemoveScriptInstances();
1191 1285
1192 ScenePresence[] avatars = Scene.GetScenePresences(); 1286 ScenePresence[] avatars = Scene.GetScenePresences();
1193 for (int i = 0; i < avatars.Length; i++) 1287 for (int i = 0; i < avatars.Length; i++)
1288 {
1289 if (avatars[i].ParentID == LocalId)
1194 { 1290 {
1195 if (avatars[i].ParentID == LocalId) 1291 avatars[i].StandUp();
1196 { 1292 }
1197 avatars[i].StandUp();
1198 }
1199 1293
1200 if (!silent) 1294 if (!silent)
1201 { 1295 {
1202 part.UpdateFlag = 0; 1296 part.UpdateFlag = 0;
1203 if (part == m_rootPart) 1297 if (part == m_rootPart)
1204 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1298 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1205 }
1206 } 1299 }
1207 } 1300 }
1301
1208 } 1302 }
1303
1304
1209 } 1305 }
1210 1306
1211 public void AddScriptLPS(int count) 1307 public void AddScriptLPS(int count)
@@ -1230,17 +1326,20 @@ namespace OpenSim.Region.Framework.Scenes
1230 1326
1231 scriptEvents aggregateScriptEvents=0; 1327 scriptEvents aggregateScriptEvents=0;
1232 1328
1233 lock (m_parts) 1329 lockPartsForRead(true);
1234 { 1330 {
1235 foreach (SceneObjectPart part in m_parts.Values) 1331 foreach (SceneObjectPart part in m_parts.Values)
1236 { 1332 {
1333
1237 if (part == null) 1334 if (part == null)
1238 continue; 1335 continue;
1239 if (part != RootPart) 1336 if (part != RootPart)
1240 part.ObjectFlags = objectflagupdate; 1337 part.ObjectFlags = objectflagupdate;
1241 aggregateScriptEvents |= part.AggregateScriptEvents; 1338 aggregateScriptEvents |= part.AggregateScriptEvents;
1339
1242 } 1340 }
1243 } 1341 }
1342 lockPartsForRead(false);
1244 1343
1245 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1344 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1246 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1345 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1273,42 +1372,52 @@ namespace OpenSim.Region.Framework.Scenes
1273 /// <param name="m_physicalPrim"></param> 1372 /// <param name="m_physicalPrim"></param>
1274 public void ApplyPhysics(bool m_physicalPrim) 1373 public void ApplyPhysics(bool m_physicalPrim)
1275 { 1374 {
1276 lock (m_parts) 1375 lockPartsForRead(true);
1376
1377 if (m_parts.Count > 1)
1277 { 1378 {
1278 if (m_parts.Count > 1) 1379 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1380 lockPartsForRead(false);
1381 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1382 foreach (SceneObjectPart part in values)
1279 { 1383 {
1280 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1384
1281 foreach (SceneObjectPart part in m_parts.Values) 1385 if (part.LocalId != m_rootPart.LocalId)
1282 { 1386 {
1283 if (part.LocalId != m_rootPart.LocalId) 1387 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1284 {
1285 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1286 }
1287 } 1388 }
1288 1389
1289 // Hack to get the physics scene geometries in the right spot
1290 ResetChildPrimPhysicsPositions();
1291 }
1292 else
1293 {
1294 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1295 } 1390 }
1391 // Hack to get the physics scene geometries in the right spot
1392 ResetChildPrimPhysicsPositions();
1393 }
1394 else
1395 {
1396 lockPartsForRead(false);
1397 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1296 } 1398 }
1297 } 1399 }
1298 1400
1299 public void SetOwnerId(UUID userId) 1401 public void SetOwnerId(UUID userId)
1300 { 1402 {
1301 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1403 ForEachPart(delegate(SceneObjectPart part)
1404 {
1405
1406 part.OwnerID = userId;
1407
1408 });
1302 } 1409 }
1303 1410
1304 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1411 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1305 { 1412 {
1306 lock (m_parts) 1413 lockPartsForRead(true);
1414 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1415 lockPartsForRead(false);
1416 foreach (SceneObjectPart part in values)
1307 { 1417 {
1308 foreach (SceneObjectPart part in m_parts.Values) 1418
1309 { 1419 whatToDo(part);
1310 whatToDo(part); 1420
1311 }
1312 } 1421 }
1313 } 1422 }
1314 1423
@@ -1407,14 +1516,17 @@ namespace OpenSim.Region.Framework.Scenes
1407 { 1516 {
1408 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1517 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1409 1518
1410 lock (m_parts) 1519 lockPartsForRead(true);
1411 { 1520 {
1412 foreach (SceneObjectPart part in m_parts.Values) 1521 foreach (SceneObjectPart part in m_parts.Values)
1413 { 1522 {
1523
1414 if (part != RootPart) 1524 if (part != RootPart)
1415 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1525 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1526
1416 } 1527 }
1417 } 1528 }
1529 lockPartsForRead(false);
1418 } 1530 }
1419 1531
1420 /// <summary> 1532 /// <summary>
@@ -1509,10 +1621,11 @@ namespace OpenSim.Region.Framework.Scenes
1509 1621
1510 List<SceneObjectPart> partList; 1622 List<SceneObjectPart> partList;
1511 1623
1512 lock (m_parts) 1624 lockPartsForRead(true);
1513 { 1625
1514 partList = new List<SceneObjectPart>(m_parts.Values); 1626 partList = new List<SceneObjectPart>(m_parts.Values);
1515 } 1627
1628 lockPartsForRead(false);
1516 1629
1517 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1630 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1518 { 1631 {
@@ -1835,10 +1948,11 @@ namespace OpenSim.Region.Framework.Scenes
1835 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 1948 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1836 newPart.SetParent(this); 1949 newPart.SetParent(this);
1837 1950
1838 lock (m_parts) 1951 lockPartsForWrite(true);
1839 { 1952 {
1840 m_parts.Add(newPart.UUID, newPart); 1953 m_parts.Add(newPart.UUID, newPart);
1841 } 1954 }
1955 lockPartsForWrite(false);
1842 1956
1843 SetPartAsNonRoot(newPart); 1957 SetPartAsNonRoot(newPart);
1844 1958
@@ -1901,7 +2015,7 @@ namespace OpenSim.Region.Framework.Scenes
1901 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2015 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1902 // return; 2016 // return;
1903 2017
1904 lock (m_parts) 2018 lockPartsForRead(true);
1905 { 2019 {
1906 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2020 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1907 2021
@@ -1919,34 +2033,43 @@ namespace OpenSim.Region.Framework.Scenes
1919 2033
1920 foreach (SceneObjectPart part in m_parts.Values) 2034 foreach (SceneObjectPart part in m_parts.Values)
1921 { 2035 {
2036
1922 part.SendScheduledUpdates(); 2037 part.SendScheduledUpdates();
2038
1923 } 2039 }
1924 } 2040 }
2041 lockPartsForRead(false);
1925 } 2042 }
1926 2043
1927 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2044 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
1928 { 2045 {
1929 RootPart.AddFullUpdateToAvatar(presence); 2046 RootPart.AddFullUpdateToAvatar(presence);
1930 2047
1931 lock (m_parts) 2048 lockPartsForRead(true);
1932 { 2049 {
1933 foreach (SceneObjectPart part in m_parts.Values) 2050 foreach (SceneObjectPart part in m_parts.Values)
1934 { 2051 {
2052
1935 if (part != RootPart) 2053 if (part != RootPart)
1936 part.AddFullUpdateToAvatar(presence); 2054 part.AddFullUpdateToAvatar(presence);
2055
1937 } 2056 }
1938 } 2057 }
2058 lockPartsForRead(false);
1939 } 2059 }
1940 2060
1941 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2061 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1942 { 2062 {
1943 lock (m_parts) 2063 lockPartsForRead(true);
1944 { 2064 {
1945 foreach (SceneObjectPart part in m_parts.Values) 2065 foreach (SceneObjectPart part in m_parts.Values)
1946 { 2066 {
2067
1947 part.AddTerseUpdateToAvatar(presence); 2068 part.AddTerseUpdateToAvatar(presence);
2069
1948 } 2070 }
1949 } 2071 }
2072 lockPartsForRead(false);
1950 } 2073 }
1951 2074
1952 /// <summary> 2075 /// <summary>
@@ -1957,14 +2080,17 @@ namespace OpenSim.Region.Framework.Scenes
1957 checkAtTargets(); 2080 checkAtTargets();
1958 RootPart.ScheduleFullUpdate(); 2081 RootPart.ScheduleFullUpdate();
1959 2082
1960 lock (m_parts) 2083 lockPartsForRead(true);
1961 { 2084 {
1962 foreach (SceneObjectPart part in m_parts.Values) 2085 foreach (SceneObjectPart part in m_parts.Values)
1963 { 2086 {
2087
1964 if (part != RootPart) 2088 if (part != RootPart)
1965 part.ScheduleFullUpdate(); 2089 part.ScheduleFullUpdate();
2090
1966 } 2091 }
1967 } 2092 }
2093 lockPartsForRead(false);
1968 } 2094 }
1969 2095
1970 /// <summary> 2096 /// <summary>
@@ -1972,13 +2098,16 @@ namespace OpenSim.Region.Framework.Scenes
1972 /// </summary> 2098 /// </summary>
1973 public void ScheduleGroupForTerseUpdate() 2099 public void ScheduleGroupForTerseUpdate()
1974 { 2100 {
1975 lock (m_parts) 2101 lockPartsForRead(true);
1976 { 2102 {
1977 foreach (SceneObjectPart part in m_parts.Values) 2103 foreach (SceneObjectPart part in m_parts.Values)
1978 { 2104 {
2105
1979 part.ScheduleTerseUpdate(); 2106 part.ScheduleTerseUpdate();
2107
1980 } 2108 }
1981 } 2109 }
2110 lockPartsForRead(false);
1982 } 2111 }
1983 2112
1984 /// <summary> 2113 /// <summary>
@@ -1991,14 +2120,17 @@ namespace OpenSim.Region.Framework.Scenes
1991 2120
1992 RootPart.SendFullUpdateToAllClients(); 2121 RootPart.SendFullUpdateToAllClients();
1993 2122
1994 lock (m_parts) 2123 lockPartsForRead(true);
1995 { 2124 {
1996 foreach (SceneObjectPart part in m_parts.Values) 2125 foreach (SceneObjectPart part in m_parts.Values)
1997 { 2126 {
2127
1998 if (part != RootPart) 2128 if (part != RootPart)
1999 part.SendFullUpdateToAllClients(); 2129 part.SendFullUpdateToAllClients();
2130
2000 } 2131 }
2001 } 2132 }
2133 lockPartsForRead(false);
2002 } 2134 }
2003 2135
2004 /// <summary> 2136 /// <summary>
@@ -2029,14 +2161,15 @@ namespace OpenSim.Region.Framework.Scenes
2029 { 2161 {
2030 if (IsDeleted) 2162 if (IsDeleted)
2031 return; 2163 return;
2032 2164
2033 lock (m_parts) 2165 lockPartsForRead(true);
2034 { 2166 {
2035 foreach (SceneObjectPart part in m_parts.Values) 2167 foreach (SceneObjectPart part in m_parts.Values)
2036 { 2168 {
2037 part.SendTerseUpdateToAllClients(); 2169 part.SendTerseUpdateToAllClients();
2038 } 2170 }
2039 } 2171 }
2172 lockPartsForRead(false);
2040 } 2173 }
2041 2174
2042 #endregion 2175 #endregion
@@ -2050,16 +2183,18 @@ namespace OpenSim.Region.Framework.Scenes
2050 /// <returns>null if no child part with that linknum or child part</returns> 2183 /// <returns>null if no child part with that linknum or child part</returns>
2051 public SceneObjectPart GetLinkNumPart(int linknum) 2184 public SceneObjectPart GetLinkNumPart(int linknum)
2052 { 2185 {
2053 lock (m_parts) 2186 lockPartsForRead(true);
2054 { 2187 {
2055 foreach (SceneObjectPart part in m_parts.Values) 2188 foreach (SceneObjectPart part in m_parts.Values)
2056 { 2189 {
2057 if (part.LinkNum == linknum) 2190 if (part.LinkNum == linknum)
2058 { 2191 {
2192 lockPartsForRead(false);
2059 return part; 2193 return part;
2060 } 2194 }
2061 } 2195 }
2062 } 2196 }
2197 lockPartsForRead(false);
2063 2198
2064 return null; 2199 return null;
2065 } 2200 }
@@ -2087,17 +2222,19 @@ namespace OpenSim.Region.Framework.Scenes
2087 public SceneObjectPart GetChildPart(uint localID) 2222 public SceneObjectPart GetChildPart(uint localID)
2088 { 2223 {
2089 //m_log.DebugFormat("Entered looking for {0}", localID); 2224 //m_log.DebugFormat("Entered looking for {0}", localID);
2090 lock (m_parts) 2225 lockPartsForRead(true);
2091 { 2226 {
2092 foreach (SceneObjectPart part in m_parts.Values) 2227 foreach (SceneObjectPart part in m_parts.Values)
2093 { 2228 {
2094 //m_log.DebugFormat("Found {0}", part.LocalId); 2229 //m_log.DebugFormat("Found {0}", part.LocalId);
2095 if (part.LocalId == localID) 2230 if (part.LocalId == localID)
2096 { 2231 {
2232 lockPartsForRead(false);
2097 return part; 2233 return part;
2098 } 2234 }
2099 } 2235 }
2100 } 2236 }
2237 lockPartsForRead(false);
2101 2238
2102 return null; 2239 return null;
2103 } 2240 }
@@ -2127,17 +2264,19 @@ namespace OpenSim.Region.Framework.Scenes
2127 public bool HasChildPrim(uint localID) 2264 public bool HasChildPrim(uint localID)
2128 { 2265 {
2129 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2266 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2130 lock (m_parts) 2267 lockPartsForRead(true);
2131 { 2268 {
2132 foreach (SceneObjectPart part in m_parts.Values) 2269 foreach (SceneObjectPart part in m_parts.Values)
2133 { 2270 {
2134 //m_log.DebugFormat("Found {0}", part.LocalId); 2271 //m_log.DebugFormat("Found {0}", part.LocalId);
2135 if (part.LocalId == localID) 2272 if (part.LocalId == localID)
2136 { 2273 {
2274 lockPartsForRead(false);
2137 return true; 2275 return true;
2138 } 2276 }
2139 } 2277 }
2140 } 2278 }
2279 lockPartsForRead(false);
2141 2280
2142 return false; 2281 return false;
2143 } 2282 }
@@ -2187,53 +2326,57 @@ namespace OpenSim.Region.Framework.Scenes
2187 if (m_rootPart.LinkNum == 0) 2326 if (m_rootPart.LinkNum == 0)
2188 m_rootPart.LinkNum = 1; 2327 m_rootPart.LinkNum = 1;
2189 2328
2190 lock (m_parts) 2329 lockPartsForWrite(true);
2191 { 2330
2192 m_parts.Add(linkPart.UUID, linkPart); 2331 m_parts.Add(linkPart.UUID, linkPart);
2332
2333 lockPartsForWrite(false);
2193 2334
2194 // Insert in terms of link numbers, the new links 2335 // Insert in terms of link numbers, the new links
2195 // before the current ones (with the exception of 2336 // before the current ones (with the exception of
2196 // the root prim. Shuffle the old ones up 2337 // the root prim. Shuffle the old ones up
2197 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2338 lockPartsForRead(true);
2339 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2340 {
2341 if (kvp.Value.LinkNum != 1)
2198 { 2342 {
2199 if (kvp.Value.LinkNum != 1) 2343 // Don't update root prim link number
2200 { 2344 kvp.Value.LinkNum += objectGroup.PrimCount;
2201 // Don't update root prim link number
2202 kvp.Value.LinkNum += objectGroup.PrimCount;
2203 }
2204 } 2345 }
2346 }
2347 lockPartsForRead(false);
2205 2348
2206 linkPart.LinkNum = 2; 2349 linkPart.LinkNum = 2;
2207 2350
2208 linkPart.SetParent(this); 2351 linkPart.SetParent(this);
2209 linkPart.AddFlag(PrimFlags.CreateSelected); 2352 linkPart.AddFlag(PrimFlags.CreateSelected);
2210 2353
2211 //if (linkPart.PhysActor != null) 2354 //if (linkPart.PhysActor != null)
2212 //{ 2355 //{
2213 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2356 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2214 2357
2215 //linkPart.PhysActor = null; 2358 //linkPart.PhysActor = null;
2216 //} 2359 //}
2217 2360
2218 //TODO: rest of parts 2361 //TODO: rest of parts
2219 int linkNum = 3; 2362 int linkNum = 3;
2220 foreach (SceneObjectPart part in objectGroup.Children.Values) 2363 foreach (SceneObjectPart part in objectGroup.Children.Values)
2364 {
2365 if (part.UUID != objectGroup.m_rootPart.UUID)
2221 { 2366 {
2222 if (part.UUID != objectGroup.m_rootPart.UUID) 2367 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2223 {
2224 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2225 }
2226 part.ClearUndoState();
2227 } 2368 }
2369 part.ClearUndoState();
2228 } 2370 }
2229 2371
2230 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2372 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2231 objectGroup.m_isDeleted = true; 2373 objectGroup.m_isDeleted = true;
2374
2375 objectGroup.lockPartsForWrite(true);
2232 2376
2233 lock (objectGroup.m_parts) 2377 objectGroup.m_parts.Clear();
2234 { 2378
2235 objectGroup.m_parts.Clear(); 2379 objectGroup.lockPartsForWrite(false);
2236 }
2237 2380
2238 // Can't do this yet since backup still makes use of the root part without any synchronization 2381 // Can't do this yet since backup still makes use of the root part without any synchronization
2239// objectGroup.m_rootPart = null; 2382// objectGroup.m_rootPart = null;
@@ -2292,11 +2435,12 @@ namespace OpenSim.Region.Framework.Scenes
2292 Quaternion worldRot = linkPart.GetWorldRotation(); 2435 Quaternion worldRot = linkPart.GetWorldRotation();
2293 2436
2294 // Remove the part from this object 2437 // Remove the part from this object
2295 lock (m_parts) 2438 lockPartsForWrite(true);
2296 { 2439 {
2297 m_parts.Remove(linkPart.UUID); 2440 m_parts.Remove(linkPart.UUID);
2298 } 2441 }
2299 2442 lockPartsForWrite(false);
2443 lockPartsForRead(true);
2300 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2444 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2301 RootPart.LinkNum = 0; 2445 RootPart.LinkNum = 0;
2302 else 2446 else
@@ -2307,6 +2451,7 @@ namespace OpenSim.Region.Framework.Scenes
2307 p.LinkNum--; 2451 p.LinkNum--;
2308 } 2452 }
2309 } 2453 }
2454 lockPartsForRead(false);
2310 2455
2311 linkPart.ParentID = 0; 2456 linkPart.ParentID = 0;
2312 linkPart.LinkNum = 0; 2457 linkPart.LinkNum = 0;
@@ -2624,22 +2769,23 @@ namespace OpenSim.Region.Framework.Scenes
2624 2769
2625 if (selectionPart != null) 2770 if (selectionPart != null)
2626 { 2771 {
2627 lock (m_parts) 2772 lockPartsForRead(true);
2773 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2774 lockPartsForRead(false);
2775 foreach (SceneObjectPart part in parts)
2628 { 2776 {
2629 foreach (SceneObjectPart part in m_parts.Values) 2777 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2630 { 2778 {
2631 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0) 2779 UsePhysics = false; // Reset physics
2632 { 2780 break;
2633 UsePhysics = false; // Reset physics
2634 break;
2635 }
2636 } 2781 }
2782 }
2637 2783
2638 foreach (SceneObjectPart part in m_parts.Values) 2784 foreach (SceneObjectPart part in parts)
2639 { 2785 {
2640 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2786 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2641 }
2642 } 2787 }
2788
2643 } 2789 }
2644 } 2790 }
2645 2791
@@ -2863,7 +3009,7 @@ namespace OpenSim.Region.Framework.Scenes
2863 prevScale.Z *= z; 3009 prevScale.Z *= z;
2864 part.Resize(prevScale); 3010 part.Resize(prevScale);
2865 3011
2866 lock (m_parts) 3012 lockPartsForRead(true);
2867 { 3013 {
2868 foreach (SceneObjectPart obPart in m_parts.Values) 3014 foreach (SceneObjectPart obPart in m_parts.Values)
2869 { 3015 {
@@ -2882,6 +3028,7 @@ namespace OpenSim.Region.Framework.Scenes
2882 } 3028 }
2883 } 3029 }
2884 } 3030 }
3031 lockPartsForRead(false);
2885 3032
2886 if (part.PhysActor != null) 3033 if (part.PhysActor != null)
2887 { 3034 {
@@ -2962,7 +3109,7 @@ namespace OpenSim.Region.Framework.Scenes
2962 axDiff *= Quaternion.Inverse(partRotation); 3109 axDiff *= Quaternion.Inverse(partRotation);
2963 diff = axDiff; 3110 diff = axDiff;
2964 3111
2965 lock (m_parts) 3112 lockPartsForRead(true);
2966 { 3113 {
2967 foreach (SceneObjectPart obPart in m_parts.Values) 3114 foreach (SceneObjectPart obPart in m_parts.Values)
2968 { 3115 {
@@ -2972,6 +3119,7 @@ namespace OpenSim.Region.Framework.Scenes
2972 } 3119 }
2973 } 3120 }
2974 } 3121 }
3122 lockPartsForRead(false);
2975 3123
2976 AbsolutePosition = newPos; 3124 AbsolutePosition = newPos;
2977 3125
@@ -3089,7 +3237,7 @@ namespace OpenSim.Region.Framework.Scenes
3089 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3237 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3090 } 3238 }
3091 3239
3092 lock (m_parts) 3240 lockPartsForRead(true);
3093 { 3241 {
3094 foreach (SceneObjectPart prim in m_parts.Values) 3242 foreach (SceneObjectPart prim in m_parts.Values)
3095 { 3243 {
@@ -3107,6 +3255,7 @@ namespace OpenSim.Region.Framework.Scenes
3107 } 3255 }
3108 } 3256 }
3109 } 3257 }
3258 lockPartsForRead(false);
3110 3259
3111 m_rootPart.ScheduleTerseUpdate(); 3260 m_rootPart.ScheduleTerseUpdate();
3112 } 3261 }
@@ -3205,7 +3354,7 @@ namespace OpenSim.Region.Framework.Scenes
3205 if (atTargets.Count > 0) 3354 if (atTargets.Count > 0)
3206 { 3355 {
3207 uint[] localids = new uint[0]; 3356 uint[] localids = new uint[0];
3208 lock (m_parts) 3357 lockPartsForRead(true);
3209 { 3358 {
3210 localids = new uint[m_parts.Count]; 3359 localids = new uint[m_parts.Count];
3211 int cntr = 0; 3360 int cntr = 0;
@@ -3215,6 +3364,7 @@ namespace OpenSim.Region.Framework.Scenes
3215 cntr++; 3364 cntr++;
3216 } 3365 }
3217 } 3366 }
3367 lockPartsForRead(false);
3218 3368
3219 for (int ctr = 0; ctr < localids.Length; ctr++) 3369 for (int ctr = 0; ctr < localids.Length; ctr++)
3220 { 3370 {
@@ -3233,7 +3383,7 @@ namespace OpenSim.Region.Framework.Scenes
3233 { 3383 {
3234 //trigger not_at_target 3384 //trigger not_at_target
3235 uint[] localids = new uint[0]; 3385 uint[] localids = new uint[0];
3236 lock (m_parts) 3386 lockPartsForRead(true);
3237 { 3387 {
3238 localids = new uint[m_parts.Count]; 3388 localids = new uint[m_parts.Count];
3239 int cntr = 0; 3389 int cntr = 0;
@@ -3243,7 +3393,8 @@ namespace OpenSim.Region.Framework.Scenes
3243 cntr++; 3393 cntr++;
3244 } 3394 }
3245 } 3395 }
3246 3396 lockPartsForRead(false);
3397
3247 for (int ctr = 0; ctr < localids.Length; ctr++) 3398 for (int ctr = 0; ctr < localids.Length; ctr++)
3248 { 3399 {
3249 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3400 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3256,19 +3407,20 @@ namespace OpenSim.Region.Framework.Scenes
3256 public float GetMass() 3407 public float GetMass()
3257 { 3408 {
3258 float retmass = 0f; 3409 float retmass = 0f;
3259 lock (m_parts) 3410 lockPartsForRead(true);
3260 { 3411 {
3261 foreach (SceneObjectPart part in m_parts.Values) 3412 foreach (SceneObjectPart part in m_parts.Values)
3262 { 3413 {
3263 retmass += part.GetMass(); 3414 retmass += part.GetMass();
3264 } 3415 }
3265 } 3416 }
3417 lockPartsForRead(false);
3266 return retmass; 3418 return retmass;
3267 } 3419 }
3268 3420
3269 public void CheckSculptAndLoad() 3421 public void CheckSculptAndLoad()
3270 { 3422 {
3271 lock (m_parts) 3423 lockPartsForRead(true);
3272 { 3424 {
3273 if (!IsDeleted) 3425 if (!IsDeleted)
3274 { 3426 {
@@ -3293,6 +3445,7 @@ namespace OpenSim.Region.Framework.Scenes
3293 } 3445 }
3294 } 3446 }
3295 } 3447 }
3448 lockPartsForRead(false);
3296 } 3449 }
3297 3450
3298 protected void AssetReceived(string id, Object sender, AssetBase asset) 3451 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3313,7 +3466,7 @@ namespace OpenSim.Region.Framework.Scenes
3313 /// <param name="client"></param> 3466 /// <param name="client"></param>
3314 public void SetGroup(UUID GroupID, IClientAPI client) 3467 public void SetGroup(UUID GroupID, IClientAPI client)
3315 { 3468 {
3316 lock (m_parts) 3469 lockPartsForRead(true);
3317 { 3470 {
3318 foreach (SceneObjectPart part in m_parts.Values) 3471 foreach (SceneObjectPart part in m_parts.Values)
3319 { 3472 {
@@ -3323,7 +3476,7 @@ namespace OpenSim.Region.Framework.Scenes
3323 3476
3324 HasGroupChanged = true; 3477 HasGroupChanged = true;
3325 } 3478 }
3326 3479 lockPartsForRead(false);
3327 ScheduleGroupForFullUpdate(); 3480 ScheduleGroupForFullUpdate();
3328 } 3481 }
3329 3482
@@ -3342,11 +3495,12 @@ namespace OpenSim.Region.Framework.Scenes
3342 3495
3343 public void SetAttachmentPoint(byte point) 3496 public void SetAttachmentPoint(byte point)
3344 { 3497 {
3345 lock (m_parts) 3498 lockPartsForRead(true);
3346 { 3499 {
3347 foreach (SceneObjectPart part in m_parts.Values) 3500 foreach (SceneObjectPart part in m_parts.Values)
3348 part.SetAttachmentPoint(point); 3501 part.SetAttachmentPoint(point);
3349 } 3502 }
3503 lockPartsForRead(false);
3350 } 3504 }
3351 3505
3352 #region ISceneObject 3506 #region ISceneObject
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index ec771e3..267928b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -2950,8 +2950,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2950 return m_host.OwnerID.ToString(); 2950 return m_host.OwnerID.ToString();
2951 } 2951 }
2952 2952
2953 [DebuggerNonUserCode]
2953 public void llInstantMessage(string user, string message) 2954 public void llInstantMessage(string user, string message)
2954 { 2955 {
2956 UUID result;
2957 if (!UUID.TryParse(user, out result))
2958 {
2959 throw new Exception(String.Format("An invalid key of '{0} was passed to llInstantMessage", user));
2960 return;
2961 }
2962
2963
2955 m_host.AddScriptLPS(1); 2964 m_host.AddScriptLPS(1);
2956 2965
2957 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 2966 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -2966,7 +2975,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2966 UUID friendTransactionID = UUID.Random(); 2975 UUID friendTransactionID = UUID.Random();
2967 2976
2968 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 2977 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
2969 2978
2970 GridInstantMessage msg = new GridInstantMessage(); 2979 GridInstantMessage msg = new GridInstantMessage();
2971 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 2980 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
2972 msg.toAgentID = new Guid(user); // toAgentID.Guid; 2981 msg.toAgentID = new Guid(user); // toAgentID.Guid;
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index d997ea3..49c69ab 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -101,6 +101,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
101 private Dictionary<UUID, IScriptInstance> m_Scripts = 101 private Dictionary<UUID, IScriptInstance> m_Scripts =
102 new Dictionary<UUID, IScriptInstance>(); 102 new Dictionary<UUID, IScriptInstance>();
103 103
104 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
105
104 // Maps the asset ID to the assembly 106 // Maps the asset ID to the assembly
105 107
106 private Dictionary<UUID, string> m_Assemblies = 108 private Dictionary<UUID, string> m_Assemblies =
@@ -122,6 +124,65 @@ namespace OpenSim.Region.ScriptEngine.XEngine
122 private ScriptCompileQueue m_CompileQueue = new ScriptCompileQueue(); 124 private ScriptCompileQueue m_CompileQueue = new ScriptCompileQueue();
123 IWorkItemResult m_CurrentCompile = null; 125 IWorkItemResult m_CurrentCompile = null;
124 126
127 private void lockScriptsForRead(bool locked)
128 {
129 if (locked)
130 {
131 if (m_scriptsLock.RecursiveReadCount > 0)
132 {
133 m_log.Error("[XEngine.m_Scripts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
134 m_scriptsLock.ExitReadLock();
135 }
136 if (m_scriptsLock.RecursiveWriteCount > 0)
137 {
138 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
139 m_scriptsLock.ExitWriteLock();
140 }
141
142 while (!m_scriptsLock.TryEnterReadLock(60000))
143 {
144 m_log.Error("[XEngine.m_Scripts] Thread lock detected while trying to aquire READ lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
145 if (m_scriptsLock.IsWriteLockHeld)
146 {
147 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
148 }
149 }
150 }
151 else
152 {
153 m_scriptsLock.ExitReadLock();
154 }
155 }
156 private void lockScriptsForWrite(bool locked)
157 {
158 if (locked)
159 {
160 if (m_scriptsLock.RecursiveReadCount > 0)
161 {
162 m_log.Error("[XEngine.m_Scripts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
163 m_scriptsLock.ExitReadLock();
164 }
165 if (m_scriptsLock.RecursiveWriteCount > 0)
166 {
167 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
168 m_scriptsLock.ExitWriteLock();
169 }
170
171 while (!m_scriptsLock.TryEnterWriteLock(60000))
172 {
173 m_log.Error("[XEngine.m_Scripts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
174 if (m_scriptsLock.IsWriteLockHeld)
175 {
176 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
177 }
178 }
179 }
180 else
181 {
182 m_scriptsLock.ExitWriteLock();
183 }
184 }
185
125 public string ScriptEngineName 186 public string ScriptEngineName
126 { 187 {
127 get { return "XEngine"; } 188 get { return "XEngine"; }
@@ -261,43 +322,45 @@ namespace OpenSim.Region.ScriptEngine.XEngine
261 322
262 public void RemoveRegion(Scene scene) 323 public void RemoveRegion(Scene scene)
263 { 324 {
264 lock (m_Scripts) 325 lockScriptsForRead(true);
326 foreach (IScriptInstance instance in m_Scripts.Values)
265 { 327 {
266 foreach (IScriptInstance instance in m_Scripts.Values) 328 // Force a final state save
329 //
330 if (m_Assemblies.ContainsKey(instance.AssetID))
267 { 331 {
268 // Force a final state save 332 string assembly = m_Assemblies[instance.AssetID];
269 // 333 instance.SaveState(assembly);
270 if (m_Assemblies.ContainsKey(instance.AssetID)) 334 }
271 {
272 string assembly = m_Assemblies[instance.AssetID];
273 instance.SaveState(assembly);
274 }
275 335
276 // Clear the event queue and abort the instance thread 336 // Clear the event queue and abort the instance thread
277 // 337 //
278 instance.ClearQueue(); 338 instance.ClearQueue();
279 instance.Stop(0); 339 instance.Stop(0);
280 340
281 // Release events, timer, etc 341 // Release events, timer, etc
282 // 342 //
283 instance.DestroyScriptInstance(); 343 instance.DestroyScriptInstance();
284 344
285 // Unload scripts and app domains 345 // Unload scripts and app domains
286 // Must be done explicitly because they have infinite 346 // Must be done explicitly because they have infinite
287 // lifetime 347 // lifetime
288 // 348 //
289 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 349 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
290 if (m_DomainScripts[instance.AppDomain].Count == 0) 350 if (m_DomainScripts[instance.AppDomain].Count == 0)
291 { 351 {
292 m_DomainScripts.Remove(instance.AppDomain); 352 m_DomainScripts.Remove(instance.AppDomain);
293 UnloadAppDomain(instance.AppDomain); 353 UnloadAppDomain(instance.AppDomain);
294 }
295 } 354 }
296 m_Scripts.Clear();
297 m_PrimObjects.Clear();
298 m_Assemblies.Clear();
299 m_DomainScripts.Clear();
300 } 355 }
356 lockScriptsForRead(false);
357 lockScriptsForWrite(true);
358 m_Scripts.Clear();
359 lockScriptsForWrite(false);
360 m_PrimObjects.Clear();
361 m_Assemblies.Clear();
362 m_DomainScripts.Clear();
363
301 lock (m_ScriptEngines) 364 lock (m_ScriptEngines)
302 { 365 {
303 m_ScriptEngines.Remove(this); 366 m_ScriptEngines.Remove(this);
@@ -356,22 +419,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
356 419
357 List<IScriptInstance> instances = new List<IScriptInstance>(); 420 List<IScriptInstance> instances = new List<IScriptInstance>();
358 421
359 lock (m_Scripts) 422 lockScriptsForRead(true);
360 { 423 foreach (IScriptInstance instance in m_Scripts.Values)
361 foreach (IScriptInstance instance in m_Scripts.Values)
362 instances.Add(instance); 424 instances.Add(instance);
363 } 425 lockScriptsForRead(false);
364 426
365 foreach (IScriptInstance i in instances) 427 foreach (IScriptInstance i in instances)
366 { 428 {
367 string assembly = String.Empty; 429 string assembly = String.Empty;
368 430
369 lock (m_Scripts) 431
370 {
371 if (!m_Assemblies.ContainsKey(i.AssetID)) 432 if (!m_Assemblies.ContainsKey(i.AssetID))
372 continue; 433 continue;
373 assembly = m_Assemblies[i.AssetID]; 434 assembly = m_Assemblies[i.AssetID];
374 } 435
375 436
376 i.SaveState(assembly); 437 i.SaveState(assembly);
377 } 438 }
@@ -673,172 +734,183 @@ namespace OpenSim.Region.ScriptEngine.XEngine
673 return false; 734 return false;
674 } 735 }
675 736
676 lock (m_Scripts) 737
738
739 ScriptInstance instance = null;
740 // Create the object record
741 lockScriptsForRead(true);
742 if ((!m_Scripts.ContainsKey(itemID)) ||
743 (m_Scripts[itemID].AssetID != assetID))
677 { 744 {
678 ScriptInstance instance = null; 745 lockScriptsForRead(false);
679 // Create the object record
680 746
681 if ((!m_Scripts.ContainsKey(itemID)) || 747 UUID appDomain = assetID;
682 (m_Scripts[itemID].AssetID != assetID))
683 {
684 UUID appDomain = assetID;
685 748
686 if (part.ParentGroup.IsAttachment) 749 if (part.ParentGroup.IsAttachment)
687 appDomain = part.ParentGroup.RootPart.UUID; 750 appDomain = part.ParentGroup.RootPart.UUID;
688 751
689 if (!m_AppDomains.ContainsKey(appDomain)) 752 if (!m_AppDomains.ContainsKey(appDomain))
753 {
754 try
690 { 755 {
691 try 756 AppDomainSetup appSetup = new AppDomainSetup();
692 { 757 // appSetup.ApplicationBase = Path.Combine(
693 AppDomainSetup appSetup = new AppDomainSetup(); 758 // "ScriptEngines",
694// appSetup.ApplicationBase = Path.Combine( 759 // m_Scene.RegionInfo.RegionID.ToString());
695// "ScriptEngines", 760
696// m_Scene.RegionInfo.RegionID.ToString()); 761 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
697 762 Evidence evidence = new Evidence(baseEvidence);
698 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 763
699 Evidence evidence = new Evidence(baseEvidence); 764 AppDomain sandbox;
700 765 if (m_AppDomainLoading)
701 AppDomain sandbox; 766 sandbox = AppDomain.CreateDomain(
702 if (m_AppDomainLoading) 767 m_Scene.RegionInfo.RegionID.ToString(),
703 sandbox = AppDomain.CreateDomain( 768 evidence, appSetup);
704 m_Scene.RegionInfo.RegionID.ToString(), 769 else
705 evidence, appSetup); 770 sandbox = AppDomain.CurrentDomain;
706 else 771
707 sandbox = AppDomain.CurrentDomain; 772 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
708 773 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
709 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 774 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
710 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 775 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
711 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 776 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
712 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 777 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
713 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 778 //sandbox.SetAppDomainPolicy(sandboxPolicy);
714 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 779
715 //sandbox.SetAppDomainPolicy(sandboxPolicy); 780 m_AppDomains[appDomain] = sandbox;
716 781
717 m_AppDomains[appDomain] = sandbox; 782 m_AppDomains[appDomain].AssemblyResolve +=
718 783 new ResolveEventHandler(
719 m_AppDomains[appDomain].AssemblyResolve += 784 AssemblyResolver.OnAssemblyResolve);
720 new ResolveEventHandler( 785 m_DomainScripts[appDomain] = new List<UUID>();
721 AssemblyResolver.OnAssemblyResolve);
722 m_DomainScripts[appDomain] = new List<UUID>();
723 }
724 catch (Exception e)
725 {
726 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
727 m_ScriptErrorMessage += "Exception creating app domain:\n";
728 m_ScriptFailCount++;
729 lock (m_AddingAssemblies)
730 {
731 m_AddingAssemblies[assembly]--;
732 }
733 return false;
734 }
735 } 786 }
736 m_DomainScripts[appDomain].Add(itemID); 787 catch (Exception e)
737
738 instance = new ScriptInstance(this, part,
739 itemID, assetID, assembly,
740 m_AppDomains[appDomain],
741 part.ParentGroup.RootPart.Name,
742 item.Name, startParam, postOnRez,
743 stateSource, m_MaxScriptQueue);
744
745 m_log.DebugFormat("[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}",
746 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, part.ParentGroup.RootPart.AbsolutePosition.ToString());
747
748 if (presence != null)
749 { 788 {
750 ShowScriptSaveResponse(item.OwnerID, 789 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
751 assetID, "Compile successful", true); 790 m_ScriptErrorMessage += "Exception creating app domain:\n";
791 m_ScriptFailCount++;
792 lock (m_AddingAssemblies)
793 {
794 m_AddingAssemblies[assembly]--;
795 }
796 return false;
752 } 797 }
798 }
799 m_DomainScripts[appDomain].Add(itemID);
753 800
754 instance.AppDomain = appDomain; 801 instance = new ScriptInstance(this, part,
755 instance.LineMap = linemap; 802 itemID, assetID, assembly,
803 m_AppDomains[appDomain],
804 part.ParentGroup.RootPart.Name,
805 item.Name, startParam, postOnRez,
806 stateSource, m_MaxScriptQueue);
756 807
757 m_Scripts[itemID] = instance; 808 m_log.DebugFormat("[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}",
758 } 809 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, part.ParentGroup.RootPart.AbsolutePosition.ToString());
759 810
760 lock (m_PrimObjects) 811 if (presence != null)
761 { 812 {
762 if (!m_PrimObjects.ContainsKey(localID)) 813 ShowScriptSaveResponse(item.OwnerID,
763 m_PrimObjects[localID] = new List<UUID>(); 814 assetID, "Compile successful", true);
815 }
764 816
765 if (!m_PrimObjects[localID].Contains(itemID)) 817 instance.AppDomain = appDomain;
766 m_PrimObjects[localID].Add(itemID); 818 instance.LineMap = linemap;
819 lockScriptsForWrite(true);
820 m_Scripts[itemID] = instance;
821 lockScriptsForWrite(false);
822 }
823 else
824 {
825 lockScriptsForRead(false);
826 }
827 lock (m_PrimObjects)
828 {
829 if (!m_PrimObjects.ContainsKey(localID))
830 m_PrimObjects[localID] = new List<UUID>();
767 831
768 } 832 if (!m_PrimObjects[localID].Contains(itemID))
833 m_PrimObjects[localID].Add(itemID);
769 834
770 if (!m_Assemblies.ContainsKey(assetID)) 835 }
771 m_Assemblies[assetID] = assembly;
772 836
773 lock (m_AddingAssemblies) 837 if (!m_Assemblies.ContainsKey(assetID))
774 { 838 m_Assemblies[assetID] = assembly;
775 m_AddingAssemblies[assembly]--;
776 }
777 839
778 if (instance!=null) 840 lock (m_AddingAssemblies)
779 instance.Init(); 841 {
842 m_AddingAssemblies[assembly]--;
780 } 843 }
844
845 if (instance!=null)
846 instance.Init();
847
781 return true; 848 return true;
782 } 849 }
783 850
784 public void OnRemoveScript(uint localID, UUID itemID) 851 public void OnRemoveScript(uint localID, UUID itemID)
785 { 852 {
786 lock (m_Scripts) 853 lockScriptsForRead(true);
854 // Do we even have it?
855 if (!m_Scripts.ContainsKey(itemID))
787 { 856 {
788 // Do we even have it? 857 lockScriptsForRead(false);
789 if (!m_Scripts.ContainsKey(itemID)) 858 return;
790 return; 859 }
860
791 861
792 IScriptInstance instance=m_Scripts[itemID]; 862 IScriptInstance instance=m_Scripts[itemID];
793 m_Scripts.Remove(itemID); 863 lockScriptsForRead(false);
864 lockScriptsForWrite(true);
865 m_Scripts.Remove(itemID);
866 lockScriptsForWrite(false);
867 instance.ClearQueue();
868 instance.Stop(0);
794 869
795 instance.ClearQueue(); 870 SceneObjectPart part =
796 instance.Stop(0); 871 m_Scene.GetSceneObjectPart(localID);
797 872
798 SceneObjectPart part = 873 if (part != null)
799 m_Scene.GetSceneObjectPart(localID); 874 part.RemoveScriptEvents(itemID);
800
801 if (part != null)
802 part.RemoveScriptEvents(itemID);
803 875
804// bool objectRemoved = false; 876// bool objectRemoved = false;
805 877
806 lock (m_PrimObjects) 878 lock (m_PrimObjects)
879 {
880 // Remove the script from it's prim
881 if (m_PrimObjects.ContainsKey(localID))
807 { 882 {
808 // Remove the script from it's prim 883 // Remove inventory item record
809 if (m_PrimObjects.ContainsKey(localID)) 884 if (m_PrimObjects[localID].Contains(itemID))
810 { 885 m_PrimObjects[localID].Remove(itemID);
811 // Remove inventory item record
812 if (m_PrimObjects[localID].Contains(itemID))
813 m_PrimObjects[localID].Remove(itemID);
814 886
815 // If there are no more scripts, remove prim 887 // If there are no more scripts, remove prim
816 if (m_PrimObjects[localID].Count == 0) 888 if (m_PrimObjects[localID].Count == 0)
817 { 889 {
818 m_PrimObjects.Remove(localID); 890 m_PrimObjects.Remove(localID);
819// objectRemoved = true; 891// objectRemoved = true;
820 }
821 } 892 }
822 } 893 }
894 }
823 895
824 instance.RemoveState(); 896 instance.RemoveState();
825 instance.DestroyScriptInstance(); 897 instance.DestroyScriptInstance();
826 898
827 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 899 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
828 if (m_DomainScripts[instance.AppDomain].Count == 0) 900 if (m_DomainScripts[instance.AppDomain].Count == 0)
829 { 901 {
830 m_DomainScripts.Remove(instance.AppDomain); 902 m_DomainScripts.Remove(instance.AppDomain);
831 UnloadAppDomain(instance.AppDomain); 903 UnloadAppDomain(instance.AppDomain);
832 } 904 }
833 905
834 instance = null; 906 instance = null;
835 907
836 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 908 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
837 if (handlerObjectRemoved != null) 909 if (handlerObjectRemoved != null)
838 handlerObjectRemoved(part.UUID); 910 handlerObjectRemoved(part.UUID);
839 911
840 CleanAssemblies(); 912 CleanAssemblies();
841 } 913
842 914
843 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 915 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
844 if (handlerScriptRemoved != null) 916 if (handlerScriptRemoved != null)
@@ -1091,12 +1163,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1091 private IScriptInstance GetInstance(UUID itemID) 1163 private IScriptInstance GetInstance(UUID itemID)
1092 { 1164 {
1093 IScriptInstance instance; 1165 IScriptInstance instance;
1094 lock (m_Scripts) 1166 lockScriptsForRead(true);
1167 if (!m_Scripts.ContainsKey(itemID))
1095 { 1168 {
1096 if (!m_Scripts.ContainsKey(itemID)) 1169 lockScriptsForRead(false);
1097 return null; 1170 return null;
1098 instance = m_Scripts[itemID];
1099 } 1171 }
1172 instance = m_Scripts[itemID];
1173 lockScriptsForRead(false);
1100 return instance; 1174 return instance;
1101 } 1175 }
1102 1176
@@ -1200,11 +1274,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1200 { 1274 {
1201 List<IScriptInstance> instances = new List<IScriptInstance>(); 1275 List<IScriptInstance> instances = new List<IScriptInstance>();
1202 1276
1203 lock (m_Scripts) 1277 lockScriptsForRead(true);
1204 { 1278 foreach (IScriptInstance instance in m_Scripts.Values)
1205 foreach (IScriptInstance instance in m_Scripts.Values)
1206 instances.Add(instance); 1279 instances.Add(instance);
1207 } 1280 lockScriptsForRead(false);
1208 1281
1209 foreach (IScriptInstance i in instances) 1282 foreach (IScriptInstance i in instances)
1210 { 1283 {