* Switched all operations on the list of clients that could be either sync or async to use Scene.ForEachClient() instead of referencing ClientManager directly
* Added a new [Startup] config option called use_async_when_possible to signal how to run operations that could be either sync or async * Changed Scene.ForEachClient to respect use_async_when_possible * Fixing a potential deadlock in Parallel.ForEach by locking on a temporary object instead of the enumerator (which may be shared across multiple invocations on ForEach). Thank you diva0.6.8-post-fixes
parent
119cf80e13
commit
4847e62e9f
|
@ -118,6 +118,7 @@ namespace OpenSim.Framework
|
||||||
int counter = threadCount;
|
int counter = threadCount;
|
||||||
AutoResetEvent threadFinishEvent = new AutoResetEvent(false);
|
AutoResetEvent threadFinishEvent = new AutoResetEvent(false);
|
||||||
IEnumerator<T> enumerator = enumerable.GetEnumerator();
|
IEnumerator<T> enumerator = enumerable.GetEnumerator();
|
||||||
|
object syncRoot = new object();
|
||||||
Exception exception = null;
|
Exception exception = null;
|
||||||
|
|
||||||
for (int i = 0; i < threadCount; i++)
|
for (int i = 0; i < threadCount; i++)
|
||||||
|
@ -131,7 +132,7 @@ namespace OpenSim.Framework
|
||||||
{
|
{
|
||||||
T entry;
|
T entry;
|
||||||
|
|
||||||
lock (enumerator)
|
lock (syncRoot)
|
||||||
{
|
{
|
||||||
if (!enumerator.MoveNext())
|
if (!enumerator.MoveNext())
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -262,7 +262,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
for (int i = 0; i < packetCount; i++)
|
for (int i = 0; i < packetCount; i++)
|
||||||
{
|
{
|
||||||
byte[] data = datas[i];
|
byte[] data = datas[i];
|
||||||
m_scene.ClientManager.ForEach(
|
m_scene.ForEachClient(
|
||||||
delegate(IClientAPI client)
|
delegate(IClientAPI client)
|
||||||
{
|
{
|
||||||
if (client is LLClientView)
|
if (client is LLClientView)
|
||||||
|
@ -274,7 +274,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
byte[] data = packet.ToBytes();
|
byte[] data = packet.ToBytes();
|
||||||
m_scene.ClientManager.ForEach(
|
m_scene.ForEachClient(
|
||||||
delegate(IClientAPI client)
|
delegate(IClientAPI client)
|
||||||
{
|
{
|
||||||
if (client is LLClientView)
|
if (client is LLClientView)
|
||||||
|
|
|
@ -114,7 +114,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
|
||||||
{
|
{
|
||||||
string reasonStr = Utils.BytesToString(reason);
|
string reasonStr = Utils.BytesToString(reason);
|
||||||
|
|
||||||
m_scene.ClientManager.ForEach(
|
m_scene.ForEachClient(
|
||||||
delegate(IClientAPI controller)
|
delegate(IClientAPI controller)
|
||||||
{
|
{
|
||||||
if (controller.AgentId != godID)
|
if (controller.AgentId != godID)
|
||||||
|
|
|
@ -408,7 +408,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
ViewerEffectPacket.EffectBlock[] effectBlockArray = effectBlock.ToArray();
|
ViewerEffectPacket.EffectBlock[] effectBlockArray = effectBlock.ToArray();
|
||||||
|
|
||||||
ClientManager.ForEach(
|
ForEachClient(
|
||||||
delegate(IClientAPI client)
|
delegate(IClientAPI client)
|
||||||
{
|
{
|
||||||
if (client.AgentId != remoteClient.AgentId)
|
if (client.AgentId != remoteClient.AgentId)
|
||||||
|
|
|
@ -106,11 +106,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
public bool m_physicalPrim;
|
public bool m_physicalPrim;
|
||||||
public float m_maxNonphys = 256;
|
public float m_maxNonphys = 256;
|
||||||
public float m_maxPhys = 10;
|
public float m_maxPhys = 10;
|
||||||
public bool m_clampPrimSize = false;
|
public bool m_clampPrimSize;
|
||||||
public bool m_trustBinaries = false;
|
public bool m_trustBinaries;
|
||||||
public bool m_allowScriptCrossings = false;
|
public bool m_allowScriptCrossings;
|
||||||
public bool m_useFlySlow = false;
|
public bool m_useFlySlow;
|
||||||
public bool m_usePreJump = false;
|
public bool m_usePreJump;
|
||||||
public bool m_seeIntoRegionFromNeighbor;
|
public bool m_seeIntoRegionFromNeighbor;
|
||||||
// TODO: need to figure out how allow client agents but deny
|
// TODO: need to figure out how allow client agents but deny
|
||||||
// root agents when ACL denies access to root agent
|
// root agents when ACL denies access to root agent
|
||||||
|
@ -118,11 +118,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
public int MaxUndoCount = 5;
|
public int MaxUndoCount = 5;
|
||||||
private int m_RestartTimerCounter;
|
private int m_RestartTimerCounter;
|
||||||
private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
|
private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
|
||||||
private int m_incrementsof15seconds = 0;
|
private int m_incrementsof15seconds;
|
||||||
private volatile bool m_backingup = false;
|
private volatile bool m_backingup;
|
||||||
|
private bool m_useAsyncWhenPossible = true;
|
||||||
|
|
||||||
private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
|
private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
|
||||||
|
|
||||||
private Dictionary<UUID, SceneObjectGroup> m_groupsWithTargets = new Dictionary<UUID, SceneObjectGroup>();
|
private Dictionary<UUID, SceneObjectGroup> m_groupsWithTargets = new Dictionary<UUID, SceneObjectGroup>();
|
||||||
|
|
||||||
protected string m_simulatorVersion = "OpenSimulator Server";
|
protected string m_simulatorVersion = "OpenSimulator Server";
|
||||||
|
@ -142,8 +142,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public IXfer XferManager;
|
public IXfer XferManager;
|
||||||
|
|
||||||
protected IAssetService m_AssetService = null;
|
protected IAssetService m_AssetService;
|
||||||
protected IAuthorizationService m_AuthorizationService = null;
|
protected IAuthorizationService m_AuthorizationService;
|
||||||
|
|
||||||
private Object m_heartbeatLock = new Object();
|
private Object m_heartbeatLock = new Object();
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IInventoryService m_InventoryService = null;
|
protected IInventoryService m_InventoryService;
|
||||||
|
|
||||||
public IInventoryService InventoryService
|
public IInventoryService InventoryService
|
||||||
{
|
{
|
||||||
|
@ -204,7 +204,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IGridService m_GridService = null;
|
protected IGridService m_GridService;
|
||||||
|
|
||||||
public IGridService GridService
|
public IGridService GridService
|
||||||
{
|
{
|
||||||
|
@ -252,7 +252,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// Central Update Loop
|
// Central Update Loop
|
||||||
|
|
||||||
protected int m_fps = 10;
|
protected int m_fps = 10;
|
||||||
protected int m_frame = 0;
|
protected int m_frame;
|
||||||
protected float m_timespan = 0.089f;
|
protected float m_timespan = 0.089f;
|
||||||
protected DateTime m_lastupdate = DateTime.UtcNow;
|
protected DateTime m_lastupdate = DateTime.UtcNow;
|
||||||
|
|
||||||
|
@ -265,17 +265,17 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
private int m_update_terrain = 50;
|
private int m_update_terrain = 50;
|
||||||
private int m_update_land = 1;
|
private int m_update_land = 1;
|
||||||
|
|
||||||
private int frameMS = 0;
|
private int frameMS;
|
||||||
private int physicsMS2 = 0;
|
private int physicsMS2;
|
||||||
private int physicsMS = 0;
|
private int physicsMS;
|
||||||
private int otherMS = 0;
|
private int otherMS;
|
||||||
|
|
||||||
private bool m_physics_enabled = true;
|
private bool m_physics_enabled = true;
|
||||||
private bool m_scripts_enabled = true;
|
private bool m_scripts_enabled = true;
|
||||||
private string m_defaultScriptEngine;
|
private string m_defaultScriptEngine;
|
||||||
private int m_LastLogin = 0;
|
private int m_LastLogin;
|
||||||
private Thread HeartbeatThread = null;
|
private Thread HeartbeatThread;
|
||||||
private volatile bool shuttingdown = false;
|
private volatile bool shuttingdown;
|
||||||
|
|
||||||
private int m_lastUpdate = Environment.TickCount;
|
private int m_lastUpdate = Environment.TickCount;
|
||||||
private bool m_firstHeartbeat = true;
|
private bool m_firstHeartbeat = true;
|
||||||
|
@ -479,6 +479,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
//
|
//
|
||||||
IConfig startupConfig = m_config.Configs["Startup"];
|
IConfig startupConfig = m_config.Configs["Startup"];
|
||||||
|
|
||||||
|
// Should we try to run loops synchronously or asynchronously?
|
||||||
|
m_useAsyncWhenPossible = startupConfig.GetBoolean("use_async_when_possible", true);
|
||||||
|
|
||||||
//Animation states
|
//Animation states
|
||||||
m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
|
m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
|
||||||
// TODO: Change default to true once the feature is supported
|
// TODO: Change default to true once the feature is supported
|
||||||
|
@ -4253,7 +4256,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public void ForEachClient(Action<IClientAPI> action)
|
public void ForEachClient(Action<IClientAPI> action)
|
||||||
{
|
{
|
||||||
ClientManager.ForEachSync(action);
|
if (m_useAsyncWhenPossible)
|
||||||
|
ClientManager.ForEach(action);
|
||||||
|
else
|
||||||
|
ClientManager.ForEachSync(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ForEachSOG(Action<SceneObjectGroup> action)
|
public void ForEachSOG(Action<SceneObjectGroup> action)
|
||||||
|
|
|
@ -183,10 +183,12 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
|
||||||
public virtual void HideFromAll()
|
public virtual void HideFromAll()
|
||||||
{
|
{
|
||||||
foreach (SceneObjectPart part in m_Entity.Children.Values)
|
foreach (SceneObjectPart part in m_Entity.Children.Values)
|
||||||
m_Entity.Scene.ClientManager.ForEach(
|
{
|
||||||
|
m_Entity.Scene.ForEachClient(
|
||||||
delegate(IClientAPI controller)
|
delegate(IClientAPI controller)
|
||||||
{ controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); }
|
{ controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); }
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendFullUpdate(IClientAPI client)
|
public void SendFullUpdate(IClientAPI client)
|
||||||
|
@ -202,7 +204,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
|
||||||
|
|
||||||
public void SendFullUpdateToAll()
|
public void SendFullUpdateToAll()
|
||||||
{
|
{
|
||||||
m_Entity.Scene.ClientManager.ForEach(
|
m_Entity.Scene.ForEachClient(
|
||||||
delegate(IClientAPI controller)
|
delegate(IClientAPI controller)
|
||||||
{ m_Entity.SendFullUpdateToClient(controller); }
|
{ m_Entity.SendFullUpdateToClient(controller); }
|
||||||
);
|
);
|
||||||
|
|
|
@ -44,6 +44,13 @@
|
||||||
; performance on .NET/Windows
|
; performance on .NET/Windows
|
||||||
;async_call_method = SmartThreadPool
|
;async_call_method = SmartThreadPool
|
||||||
|
|
||||||
|
; There are several operations on large collections (such as
|
||||||
|
; the current avatar list) that can be run synchronously or
|
||||||
|
; in parallel. Running in parallel should increase performance
|
||||||
|
; on a multi-core system, but will make debugging more
|
||||||
|
; difficult if something deadlocks or times out
|
||||||
|
use_async_when_possible = true
|
||||||
|
|
||||||
; Max threads to allocate on the FireAndForget thread pool
|
; Max threads to allocate on the FireAndForget thread pool
|
||||||
; when running with the SmartThreadPool option above
|
; when running with the SmartThreadPool option above
|
||||||
MaxPoolThreads = 15
|
MaxPoolThreads = 15
|
||||||
|
|
Loading…
Reference in New Issue