aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes
diff options
context:
space:
mode:
authorMelanie2010-05-21 03:41:32 +0100
committerMelanie2010-05-21 03:41:32 +0100
commitd28da5e5ce4e36c7a0b052fb5d2f04105d95176b (patch)
tree89024fd93013c62417d399e7afa90340cf2fd20b /OpenSim/Region/Framework/Scenes
parentMerge branch 'careminster' into careminster-presence-refactor (diff)
downloadopensim-SC-d28da5e5ce4e36c7a0b052fb5d2f04105d95176b.zip
opensim-SC-d28da5e5ce4e36c7a0b052fb5d2f04105d95176b.tar.gz
opensim-SC-d28da5e5ce4e36c7a0b052fb5d2f04105d95176b.tar.bz2
opensim-SC-d28da5e5ce4e36c7a0b052fb5d2f04105d95176b.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.
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs131
1 files changed, 49 insertions, 82 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index c16ba12..3c2203c 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -68,11 +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>();
72 protected ScenePresence[] m_scenePresenceArray = new ScenePresence[0];
73 protected List<ScenePresence> m_scenePresenceList = new List<ScenePresence>();
74
75 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim(); 71 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
76 74
77 // SceneObjects is not currently populated or used. 75 // SceneObjects is not currently populated or used.
78 //public Dictionary<UUID, SceneObjectGroup> SceneObjects; 76 //public Dictionary<UUID, SceneObjectGroup> SceneObjects;
@@ -138,9 +136,10 @@ namespace OpenSim.Region.Framework.Scenes
138 m_scenePresencesLock.EnterWriteLock(); 136 m_scenePresencesLock.EnterWriteLock();
139 try 137 try
140 { 138 {
141 m_scenePresences.Clear(); 139 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
142 m_scenePresenceArray = new ScenePresence[0]; 140 List<ScenePresence> newlist = new List<ScenePresence>();
143 m_scenePresenceList = new List<ScenePresence>(); 141 m_scenePresenceMap = newmap;
142 m_scenePresenceArray = newlist;
144 } 143 }
145 finally 144 finally
146 { 145 {
@@ -554,34 +553,27 @@ namespace OpenSim.Region.Framework.Scenes
554 m_scenePresencesLock.EnterWriteLock(); 553 m_scenePresencesLock.EnterWriteLock();
555 try 554 try
556 { 555 {
557 if (!m_scenePresences.ContainsKey(presence.UUID)) 556 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
557 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
558
559 if (!newmap.ContainsKey(presence.UUID))
558 { 560 {
559 m_scenePresences.Add(presence.UUID, presence); 561 newmap.Add(presence.UUID, presence);
560 562 newlist.Add(presence);
561 // Create a new array of ScenePresence references
562 int oldLength = m_scenePresenceArray.Length;
563 ScenePresence[] newArray = new ScenePresence[oldLength + 1];
564 Array.Copy(m_scenePresenceArray, newArray, oldLength);
565 newArray[oldLength] = presence;
566 m_scenePresenceArray = newArray;
567 m_scenePresenceList = new List<ScenePresence>(m_scenePresenceArray);
568 } 563 }
569 else 564 else
570 { 565 {
571 m_scenePresences[presence.UUID] = presence; 566 // Remember the old presene reference from the dictionary
572 567 ScenePresence oldref = newmap[presence.UUID];
573 // Do a linear search through the array of ScenePresence references 568 // Replace the presence reference in the dictionary with the new value
574 // and update the modified entry 569 newmap[presence.UUID] = presence;
575 for (int i = 0; i < m_scenePresenceArray.Length; i++) 570 // Find the index in the list where the old ref was stored and update the reference
576 { 571 newlist[newlist.IndexOf(oldref)] = presence;
577 if (m_scenePresenceArray[i].UUID == presence.UUID)
578 {
579 m_scenePresenceArray[i] = presence;
580 break;
581 }
582 }
583 m_scenePresenceList = new List<ScenePresence>(m_scenePresenceArray);
584 } 572 }
573
574 // Swap out the dictionary and list with new references
575 m_scenePresenceMap = newmap;
576 m_scenePresenceArray = newlist;
585 } 577 }
586 finally 578 finally
587 { 579 {
@@ -604,24 +596,19 @@ namespace OpenSim.Region.Framework.Scenes
604 m_scenePresencesLock.EnterWriteLock(); 596 m_scenePresencesLock.EnterWriteLock();
605 try 597 try
606 { 598 {
607 if (m_scenePresences.Remove(agentID)) 599 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
600 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
601
602 // Remember the old presene reference from the dictionary
603 ScenePresence oldref = newmap[agentID];
604 // Remove the presence reference from the dictionary
605 if (newmap.Remove(agentID))
608 { 606 {
609 // Copy all of the elements from the previous array 607 // Find the index in the list where the old ref was stored and remove the reference
610 // into the new array except the removed element 608 newlist.RemoveAt(newlist.IndexOf(oldref));
611 int oldLength = m_scenePresenceArray.Length; 609 // Swap out the dictionary and list with new references
612 ScenePresence[] newArray = new ScenePresence[oldLength - 1]; 610 m_scenePresenceMap = newmap;
613 int j = 0; 611 m_scenePresenceArray = newlist;
614 for (int i = 0; i < m_scenePresenceArray.Length; i++)
615 {
616 ScenePresence presence = m_scenePresenceArray[i];
617 if (presence.UUID != agentID)
618 {
619 newArray[j] = presence;
620 ++j;
621 }
622 }
623 m_scenePresenceArray = newArray;
624 m_scenePresenceList = new List<ScenePresence>(m_scenePresenceArray);
625 } 612 }
626 else 613 else
627 { 614 {
@@ -744,7 +731,7 @@ namespace OpenSim.Region.Framework.Scenes
744 } 731 }
745 732
746 /// <summary> 733 /// <summary>
747 /// Request a copy of m_scenePresences in this World 734 /// Get a reference to the scene presence list. Changes to the list will be done in a copy
748 /// There is no guarantee that presences will remain in the scene after the list is returned. 735 /// There is no guarantee that presences will remain in the scene after the list is returned.
749 /// This list should remain private to SceneGraph. Callers wishing to iterate should instead 736 /// This list should remain private to SceneGraph. Callers wishing to iterate should instead
750 /// pass a delegate to ForEachScenePresence. 737 /// pass a delegate to ForEachScenePresence.
@@ -752,15 +739,7 @@ namespace OpenSim.Region.Framework.Scenes
752 /// <returns></returns> 739 /// <returns></returns>
753 private List<ScenePresence> GetScenePresences() 740 private List<ScenePresence> GetScenePresences()
754 { 741 {
755 m_scenePresencesLock.EnterReadLock(); 742 return m_scenePresenceArray;
756 try
757 {
758 return m_scenePresenceList;
759 }
760 finally
761 {
762 m_scenePresencesLock.ExitReadLock();
763 }
764 } 743 }
765 744
766 /// <summary> 745 /// <summary>
@@ -770,17 +749,10 @@ namespace OpenSim.Region.Framework.Scenes
770 /// <returns>null if the presence was not found</returns> 749 /// <returns>null if the presence was not found</returns>
771 protected internal ScenePresence GetScenePresence(UUID agentID) 750 protected internal ScenePresence GetScenePresence(UUID agentID)
772 { 751 {
773 ScenePresence sp; 752 Dictionary<UUID, ScenePresence> presences = m_scenePresenceMap;
774 m_scenePresencesLock.EnterReadLock(); 753 ScenePresence presence;
775 try 754 presences.TryGetValue(agentID, out presence);
776 { 755 return presence;
777 m_scenePresences.TryGetValue(agentID, out sp);
778 }
779 finally
780 {
781 m_scenePresencesLock.ExitReadLock();
782 }
783 return sp;
784 } 756 }
785 757
786 /// <summary> 758 /// <summary>
@@ -791,7 +763,8 @@ namespace OpenSim.Region.Framework.Scenes
791 /// <returns>null if the presence was not found</returns> 763 /// <returns>null if the presence was not found</returns>
792 protected internal ScenePresence GetScenePresence(string firstName, string lastName) 764 protected internal ScenePresence GetScenePresence(string firstName, string lastName)
793 { 765 {
794 foreach (ScenePresence presence in GetScenePresences()) 766 List<ScenePresence> presences = GetScenePresences();
767 foreach (ScenePresence presence in presences)
795 { 768 {
796 if (presence.Firstname == firstName && presence.Lastname == lastName) 769 if (presence.Firstname == firstName && presence.Lastname == lastName)
797 return presence; 770 return presence;
@@ -806,7 +779,8 @@ namespace OpenSim.Region.Framework.Scenes
806 /// <returns>null if the presence was not found</returns> 779 /// <returns>null if the presence was not found</returns>
807 protected internal ScenePresence GetScenePresence(uint localID) 780 protected internal ScenePresence GetScenePresence(uint localID)
808 { 781 {
809 foreach (ScenePresence presence in GetScenePresences()) 782 List<ScenePresence> presences = GetScenePresences();
783 foreach (ScenePresence presence in presences)
810 if (presence.LocalId == localID) 784 if (presence.LocalId == localID)
811 return presence; 785 return presence;
812 return null; 786 return null;
@@ -814,15 +788,8 @@ namespace OpenSim.Region.Framework.Scenes
814 788
815 protected internal bool TryGetScenePresence(UUID agentID, out ScenePresence avatar) 789 protected internal bool TryGetScenePresence(UUID agentID, out ScenePresence avatar)
816 { 790 {
817 m_scenePresencesLock.EnterReadLock(); 791 Dictionary<UUID, ScenePresence> presences = m_scenePresenceMap;
818 try 792 presences.TryGetValue(agentID, out avatar);
819 {
820 m_scenePresences.TryGetValue(agentID, out avatar);
821 }
822 finally
823 {
824 m_scenePresencesLock.ExitReadLock();
825 }
826 return (avatar != null); 793 return (avatar != null);
827 } 794 }
828 795
@@ -1099,9 +1066,9 @@ namespace OpenSim.Region.Framework.Scenes
1099 }); 1066 });
1100 Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction); 1067 Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction);
1101 */ 1068 */
1102 // For now, perform actiona serially 1069 // For now, perform actions serially
1103 1070 List<ScenePresence> presences = GetScenePresences();
1104 foreach (ScenePresence sp in GetScenePresences()) 1071 foreach (ScenePresence sp in presences)
1105 { 1072 {
1106 try 1073 try
1107 { 1074 {