aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDan Lake2010-05-04 16:49:46 -0700
committerunknown2010-05-15 02:20:23 -0700
commit36bcab5f075089f18a5c80f3f988c1e6605c16e5 (patch)
treeb930bd812f1a62d7e5af168368c6854e634f19e4
parentMerge branch 'master' of ssh://opensimulator.org/var/git/opensim into slimupd... (diff)
downloadopensim-SC-36bcab5f075089f18a5c80f3f988c1e6605c16e5.zip
opensim-SC-36bcab5f075089f18a5c80f3f988c1e6605c16e5.tar.gz
opensim-SC-36bcab5f075089f18a5c80f3f988c1e6605c16e5.tar.bz2
opensim-SC-36bcab5f075089f18a5c80f3f988c1e6605c16e5.tar.xz
Refactor scene presence list for lockless iteration. Lock contention will now only be for simultaneous add/removes of scene presences from the scene.
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs114
1 files changed, 53 insertions, 61 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index ce11267..ef13c98 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -68,8 +68,9 @@ namespace OpenSim.Region.Framework.Scenes
68 68
69 #region Fields 69 #region Fields
70 70
71 protected Dictionary<UUID, ScenePresence> m_scenePresences = new Dictionary<UUID, ScenePresence>(); 71 protected object m_presenceLock = new object();
72 protected ScenePresence[] m_scenePresenceArray = new ScenePresence[0]; 72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
73 74
74 // SceneObjects is not currently populated or used. 75 // SceneObjects is not currently populated or used.
75 //public Dictionary<UUID, SceneObjectGroup> SceneObjects; 76 //public Dictionary<UUID, SceneObjectGroup> SceneObjects;
@@ -132,10 +133,12 @@ namespace OpenSim.Region.Framework.Scenes
132 133
133 protected internal void Close() 134 protected internal void Close()
134 { 135 {
135 lock (m_scenePresences) 136 lock (m_presenceLock)
136 { 137 {
137 m_scenePresences.Clear(); 138 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
138 m_scenePresenceArray = new ScenePresence[0]; 139 List<ScenePresence> newlist = new List<ScenePresence>();
140 m_scenePresenceMap = newmap;
141 m_scenePresenceArray = newlist;
139 } 142 }
140 143
141 lock (m_dictionary_lock) 144 lock (m_dictionary_lock)
@@ -518,34 +521,29 @@ namespace OpenSim.Region.Framework.Scenes
518 521
519 Entities[presence.UUID] = presence; 522 Entities[presence.UUID] = presence;
520 523
521 lock (m_scenePresences) 524 lock (m_presenceLock)
522 { 525 {
523 if (!m_scenePresences.ContainsKey(presence.UUID)) 526 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
527 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
528
529 if (!newmap.ContainsKey(presence.UUID))
524 { 530 {
525 m_scenePresences.Add(presence.UUID, presence); 531 newmap.Add(presence.UUID, presence);
526 532 newlist.Add(presence);
527 // Create a new array of ScenePresence references
528 int oldLength = m_scenePresenceArray.Length;
529 ScenePresence[] newArray = new ScenePresence[oldLength + 1];
530 Array.Copy(m_scenePresenceArray, newArray, oldLength);
531 newArray[oldLength] = presence;
532 m_scenePresenceArray = newArray;
533 } 533 }
534 else 534 else
535 { 535 {
536 m_scenePresences[presence.UUID] = presence; 536 // Remember the old presene reference from the dictionary
537 537 ScenePresence oldref = newmap[presence.UUID];
538 // Do a linear search through the array of ScenePresence references 538 // Replace the presence reference in the dictionary with the new value
539 // and update the modified entry 539 newmap[presence.UUID] = presence;
540 for (int i = 0; i < m_scenePresenceArray.Length; i++) 540 // Find the index in the list where the old ref was stored and update the reference
541 { 541 newlist[newlist.IndexOf(oldref)] = presence;
542 if (m_scenePresenceArray[i].UUID == presence.UUID)
543 {
544 m_scenePresenceArray[i] = presence;
545 break;
546 }
547 }
548 } 542 }
543
544 // Swap out the dictionary and list with new references
545 m_scenePresenceMap = newmap;
546 m_scenePresenceArray = newlist;
549 } 547 }
550 } 548 }
551 549
@@ -561,25 +559,21 @@ namespace OpenSim.Region.Framework.Scenes
561 agentID); 559 agentID);
562 } 560 }
563 561
564 lock (m_scenePresences) 562 lock (m_presenceLock)
565 { 563 {
566 if (m_scenePresences.Remove(agentID)) 564 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
565 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
566
567 // Remember the old presene reference from the dictionary
568 ScenePresence oldref = newmap[agentID];
569 // Remove the presence reference from the dictionary
570 if (newmap.Remove(agentID))
567 { 571 {
568 // Copy all of the elements from the previous array 572 // Find the index in the list where the old ref was stored and remove the reference
569 // into the new array except the removed element 573 newlist.RemoveAt(newlist.IndexOf(oldref));
570 int oldLength = m_scenePresenceArray.Length; 574 // Swap out the dictionary and list with new references
571 ScenePresence[] newArray = new ScenePresence[oldLength - 1]; 575 m_scenePresenceMap = newmap;
572 int j = 0; 576 m_scenePresenceArray = newlist;
573 for (int i = 0; i < m_scenePresenceArray.Length; i++)
574 {
575 ScenePresence presence = m_scenePresenceArray[i];
576 if (presence.UUID != agentID)
577 {
578 newArray[j] = presence;
579 ++j;
580 }
581 }
582 m_scenePresenceArray = newArray;
583 } 577 }
584 else 578 else
585 { 579 {
@@ -698,7 +692,7 @@ namespace OpenSim.Region.Framework.Scenes
698 } 692 }
699 693
700 /// <summary> 694 /// <summary>
701 /// Request a copy of m_scenePresences in this World 695 /// Get a reference to the scene presence list. Changes to the list will be done in a copy
702 /// There is no guarantee that presences will remain in the scene after the list is returned. 696 /// There is no guarantee that presences will remain in the scene after the list is returned.
703 /// This list should remain private to SceneGraph. Callers wishing to iterate should instead 697 /// This list should remain private to SceneGraph. Callers wishing to iterate should instead
704 /// pass a delegate to ForEachScenePresence. 698 /// pass a delegate to ForEachScenePresence.
@@ -706,8 +700,7 @@ namespace OpenSim.Region.Framework.Scenes
706 /// <returns></returns> 700 /// <returns></returns>
707 private List<ScenePresence> GetScenePresences() 701 private List<ScenePresence> GetScenePresences()
708 { 702 {
709 lock (m_scenePresences) 703 return m_scenePresenceArray;
710 return new List<ScenePresence>(m_scenePresenceArray);
711 } 704 }
712 705
713 /// <summary> 706 /// <summary>
@@ -717,12 +710,10 @@ namespace OpenSim.Region.Framework.Scenes
717 /// <returns>null if the presence was not found</returns> 710 /// <returns>null if the presence was not found</returns>
718 protected internal ScenePresence GetScenePresence(UUID agentID) 711 protected internal ScenePresence GetScenePresence(UUID agentID)
719 { 712 {
720 ScenePresence sp; 713 Dictionary<UUID, ScenePresence> presences = m_scenePresenceMap;
721 lock (m_scenePresences) 714 ScenePresence presence;
722 { 715 presences.TryGetValue(agentID, out presence);
723 m_scenePresences.TryGetValue(agentID, out sp); 716 return presence;
724 }
725 return sp;
726 } 717 }
727 718
728 /// <summary> 719 /// <summary>
@@ -733,7 +724,8 @@ namespace OpenSim.Region.Framework.Scenes
733 /// <returns>null if the presence was not found</returns> 724 /// <returns>null if the presence was not found</returns>
734 protected internal ScenePresence GetScenePresence(string firstName, string lastName) 725 protected internal ScenePresence GetScenePresence(string firstName, string lastName)
735 { 726 {
736 foreach (ScenePresence presence in GetScenePresences()) 727 List<ScenePresence> presences = GetScenePresences();
728 foreach (ScenePresence presence in presences)
737 { 729 {
738 if (presence.Firstname == firstName && presence.Lastname == lastName) 730 if (presence.Firstname == firstName && presence.Lastname == lastName)
739 return presence; 731 return presence;
@@ -748,7 +740,8 @@ namespace OpenSim.Region.Framework.Scenes
748 /// <returns>null if the presence was not found</returns> 740 /// <returns>null if the presence was not found</returns>
749 protected internal ScenePresence GetScenePresence(uint localID) 741 protected internal ScenePresence GetScenePresence(uint localID)
750 { 742 {
751 foreach (ScenePresence presence in GetScenePresences()) 743 List<ScenePresence> presences = GetScenePresences();
744 foreach (ScenePresence presence in presences)
752 if (presence.LocalId == localID) 745 if (presence.LocalId == localID)
753 return presence; 746 return presence;
754 return null; 747 return null;
@@ -756,10 +749,8 @@ namespace OpenSim.Region.Framework.Scenes
756 749
757 protected internal bool TryGetScenePresence(UUID agentID, out ScenePresence avatar) 750 protected internal bool TryGetScenePresence(UUID agentID, out ScenePresence avatar)
758 { 751 {
759 lock (m_scenePresences) 752 Dictionary<UUID, ScenePresence> presences = m_scenePresenceMap;
760 { 753 presences.TryGetValue(agentID, out avatar);
761 m_scenePresences.TryGetValue(agentID, out avatar);
762 }
763 return (avatar != null); 754 return (avatar != null);
764 } 755 }
765 756
@@ -1036,8 +1027,9 @@ namespace OpenSim.Region.Framework.Scenes
1036 }); 1027 });
1037 Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction); 1028 Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction);
1038 */ 1029 */
1039 // For now, perform actiona serially 1030 // For now, perform actions serially
1040 foreach (ScenePresence sp in GetScenePresences()) 1031 List<ScenePresence> presences = GetScenePresences();
1032 foreach (ScenePresence sp in presences)
1041 { 1033 {
1042 try 1034 try
1043 { 1035 {