diff options
author | Melanie | 2010-05-21 03:41:32 +0100 |
---|---|---|
committer | Melanie | 2010-05-21 03:41:32 +0100 |
commit | d28da5e5ce4e36c7a0b052fb5d2f04105d95176b (patch) | |
tree | 89024fd93013c62417d399e7afa90340cf2fd20b /OpenSim/Region/Framework/Scenes | |
parent | Merge branch 'careminster' into careminster-presence-refactor (diff) | |
download | opensim-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.cs | 131 |
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 | { |