mirror of
https://github.com/opensim/opensim.git
synced 2026-08-11 03:45:35 +08:00
Experimental change to use an immutable array for iterating ScenePresences, avoiding locking and copying the list each time it is accessed
This commit is contained in:
@@ -66,7 +66,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
#region Fields
|
||||
|
||||
protected internal Dictionary<UUID, ScenePresence> ScenePresences = new Dictionary<UUID, ScenePresence>();
|
||||
protected Dictionary<UUID, ScenePresence> m_scenePresences = new Dictionary<UUID, ScenePresence>();
|
||||
protected ScenePresence[] m_scenePresenceArray = new ScenePresence[0];
|
||||
|
||||
// SceneObjects is not currently populated or used.
|
||||
//public Dictionary<UUID, SceneObjectGroup> SceneObjects;
|
||||
protected internal EntityManager Entities = new EntityManager();
|
||||
@@ -126,10 +128,12 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
protected internal void Close()
|
||||
{
|
||||
lock (ScenePresences)
|
||||
lock (m_scenePresences)
|
||||
{
|
||||
ScenePresences.Clear();
|
||||
m_scenePresences.Clear();
|
||||
m_scenePresenceArray = new ScenePresence[0];
|
||||
}
|
||||
|
||||
lock (m_dictionary_lock)
|
||||
{
|
||||
SceneObjectGroupsByFullID.Clear();
|
||||
@@ -157,11 +161,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
protected internal void UpdatePresences()
|
||||
{
|
||||
List<ScenePresence> updateScenePresences = GetScenePresences();
|
||||
foreach (ScenePresence pres in updateScenePresences)
|
||||
{
|
||||
pres.Update();
|
||||
}
|
||||
ScenePresence[] updateScenePresences = GetScenePresences();
|
||||
for (int i = 0; i < updateScenePresences.Length; i++)
|
||||
updateScenePresences[i].Update();
|
||||
}
|
||||
|
||||
protected internal float UpdatePhysics(double elapsed)
|
||||
@@ -190,15 +192,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
protected internal void UpdateScenePresenceMovement()
|
||||
{
|
||||
List<ScenePresence> moveEntities = GetScenePresences();
|
||||
|
||||
foreach (EntityBase entity in moveEntities)
|
||||
{
|
||||
//cfk. This throws occaisional exceptions on a heavily used region
|
||||
//and I added this null check to try to preclude the exception.
|
||||
if (entity != null)
|
||||
entity.UpdateMovement();
|
||||
}
|
||||
ScenePresence[] moveEntities = GetScenePresences();
|
||||
for (int i = 0; i < moveEntities.Length; i++)
|
||||
moveEntities[i].UpdateMovement();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -645,9 +641,34 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
Entities[presence.UUID] = presence;
|
||||
|
||||
lock (ScenePresences)
|
||||
lock (m_scenePresences)
|
||||
{
|
||||
ScenePresences[presence.UUID] = presence;
|
||||
if (!m_scenePresences.ContainsKey(presence.UUID))
|
||||
{
|
||||
m_scenePresences.Add(presence.UUID, presence);
|
||||
|
||||
// Create a new array of ScenePresence references
|
||||
int oldLength = m_scenePresenceArray.Length;
|
||||
ScenePresence[] newArray = new ScenePresence[oldLength + 1];
|
||||
Array.Copy(m_scenePresenceArray, newArray, oldLength);
|
||||
newArray[oldLength] = presence;
|
||||
m_scenePresenceArray = newArray;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_scenePresences[presence.UUID] = presence;
|
||||
|
||||
// Do a linear search through the array of ScenePresence references
|
||||
// and update the modified entry
|
||||
for (int i = 0; i < m_scenePresenceArray.Length; i++)
|
||||
{
|
||||
if (m_scenePresenceArray[i].UUID == presence.UUID)
|
||||
{
|
||||
m_scenePresenceArray[i] = presence;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -663,16 +684,30 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
agentID);
|
||||
}
|
||||
|
||||
lock (ScenePresences)
|
||||
lock (m_scenePresences)
|
||||
{
|
||||
if (!ScenePresences.Remove(agentID))
|
||||
if (m_scenePresences.Remove(agentID))
|
||||
{
|
||||
// Copy all of the elements from the previous array
|
||||
// into the new array except the removed element
|
||||
int oldLength = m_scenePresenceArray.Length;
|
||||
ScenePresence[] newArray = new ScenePresence[oldLength - 1];
|
||||
int j = 0;
|
||||
for (int i = 0; i < m_scenePresenceArray.Length; i++)
|
||||
{
|
||||
ScenePresence presence = m_scenePresenceArray[i];
|
||||
if (presence.UUID != agentID)
|
||||
{
|
||||
newArray[j] = presence;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
m_scenePresenceArray = newArray;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat("[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// m_log.InfoFormat("[SCENE] Removed scene presence {0} from scene presences list", agentID);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -704,20 +739,21 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
public void RecalculateStats()
|
||||
{
|
||||
List<ScenePresence> SPList = GetScenePresences();
|
||||
ScenePresence[] presences = GetScenePresences();
|
||||
int rootcount = 0;
|
||||
int childcount = 0;
|
||||
|
||||
foreach (ScenePresence user in SPList)
|
||||
for (int i = 0; i < presences.Length; i++)
|
||||
{
|
||||
ScenePresence user = presences[i];
|
||||
if (user.IsChildAgent)
|
||||
childcount++;
|
||||
++childcount;
|
||||
else
|
||||
rootcount++;
|
||||
++rootcount;
|
||||
}
|
||||
|
||||
m_numRootAgents = rootcount;
|
||||
m_numChildAgents = childcount;
|
||||
|
||||
}
|
||||
|
||||
public int GetChildAgentCount()
|
||||
@@ -767,12 +803,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// locking is required to iterate over it.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected internal List<ScenePresence> GetScenePresences()
|
||||
protected internal ScenePresence[] GetScenePresences()
|
||||
{
|
||||
lock (ScenePresences)
|
||||
{
|
||||
return new List<ScenePresence>(ScenePresences.Values);
|
||||
}
|
||||
return m_scenePresenceArray;
|
||||
}
|
||||
|
||||
protected internal List<ScenePresence> GetAvatars()
|
||||
@@ -817,14 +850,13 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
// No locking of scene presences here since we're passing back a list...
|
||||
|
||||
List<ScenePresence> result = new List<ScenePresence>();
|
||||
List<ScenePresence> ScenePresencesList = GetScenePresences();
|
||||
ScenePresence[] scenePresences = GetScenePresences();
|
||||
|
||||
foreach (ScenePresence avatar in ScenePresencesList)
|
||||
for (int i = 0; i < scenePresences.Length; i++)
|
||||
{
|
||||
ScenePresence avatar = scenePresences[i];
|
||||
if (filter(avatar))
|
||||
{
|
||||
result.Add(avatar);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -839,9 +871,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
{
|
||||
ScenePresence sp;
|
||||
|
||||
lock (ScenePresences)
|
||||
lock (m_scenePresences)
|
||||
{
|
||||
ScenePresences.TryGetValue(agentID, out sp);
|
||||
m_scenePresences.TryGetValue(agentID, out sp);
|
||||
}
|
||||
|
||||
return sp;
|
||||
@@ -1000,48 +1032,24 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
protected internal bool TryGetAvatar(UUID avatarId, out ScenePresence avatar)
|
||||
{
|
||||
ScenePresence presence;
|
||||
|
||||
lock (ScenePresences)
|
||||
{
|
||||
if (ScenePresences.TryGetValue(avatarId, out presence))
|
||||
{
|
||||
avatar = presence;
|
||||
return true;
|
||||
|
||||
//if (!presence.IsChildAgent)
|
||||
//{
|
||||
// avatar = presence;
|
||||
// return true;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// m_log.WarnFormat(
|
||||
// "[INNER SCENE]: Requested avatar {0} could not be found in scene {1} since it is only registered as a child agent!",
|
||||
// avatarId, m_parentScene.RegionInfo.RegionName);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
avatar = null;
|
||||
return false;
|
||||
lock (m_scenePresences)
|
||||
return m_scenePresences.TryGetValue(avatarId, out avatar);
|
||||
}
|
||||
|
||||
protected internal bool TryGetAvatarByName(string avatarName, out ScenePresence avatar)
|
||||
{
|
||||
lock (ScenePresences)
|
||||
{
|
||||
foreach (ScenePresence presence in ScenePresences.Values)
|
||||
{
|
||||
if (!presence.IsChildAgent)
|
||||
{
|
||||
string name = presence.ControllingClient.Name;
|
||||
ScenePresence[] presences = GetScenePresences();
|
||||
|
||||
if (String.Compare(avatarName, name, true) == 0)
|
||||
{
|
||||
avatar = presence;
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < presences.Length; i++)
|
||||
{
|
||||
ScenePresence presence = presences[i];
|
||||
|
||||
if (!presence.IsChildAgent)
|
||||
{
|
||||
if (String.Compare(avatarName, presence.ControllingClient.Name, true) == 0)
|
||||
{
|
||||
avatar = presence;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user