* Refactored the central update loop - now easier to work with. Switching from per-framecounts to per-second time periods and moving to OpenSim.ini shortly.

afrisby
Adam Frisby 2007-09-24 15:46:03 +00:00
parent 0eac34b7ab
commit 48e0e05446
1 changed files with 170 additions and 102 deletions

View File

@ -60,15 +60,9 @@ namespace OpenSim.Region.Environment.Scenes
protected Dictionary<LLUUID, ScenePresence> m_scenePresences; protected Dictionary<LLUUID, ScenePresence> m_scenePresences;
protected Dictionary<LLUUID, SceneObjectGroup> m_sceneObjects; protected Dictionary<LLUUID, SceneObjectGroup> m_sceneObjects;
/// publicized so it can be accessed from SceneObjectGroup.
protected float timeStep = 0.1f;
private Random Rand = new Random(); private Random Rand = new Random();
private uint _primCount = 702000; private uint _primCount = 702000;
private readonly Mutex _primAllocateMutex = new Mutex(false); private readonly Mutex _primAllocateMutex = new Mutex(false);
private int storageCount;
private int terrainCheckCount;
private int landPrimCheckCount;
private int m_timePhase = 24; private int m_timePhase = 24;
private int m_timeUpdateCount; private int m_timeUpdateCount;
@ -98,6 +92,23 @@ namespace OpenSim.Region.Environment.Scenes
private IHttpRequests m_httpRequestModule = null; private IHttpRequests m_httpRequestModule = null;
private ISimChat m_simChatModule = null; private ISimChat m_simChatModule = null;
// Central Update Loop
protected int m_fps = 10;
protected int m_frame = 0;
protected float m_timespan = 0.1f;
protected DateTime m_lastupdate = DateTime.Now;
private int m_update_physics = 1;
private int m_update_entitymovement = 1;
private int m_update_entities = 1;
private int m_update_events = 1;
private int m_update_backup = 200;
private int m_update_terrain = 50;
private int m_update_land = 1;
private int m_update_avatars = 1;
#region Properties #region Properties
public AgentCircuitManager AuthenticateHandler public AgentCircuitManager AuthenticateHandler
@ -222,7 +233,7 @@ namespace OpenSim.Region.Environment.Scenes
public void StartTimer() public void StartTimer()
{ {
m_heartbeatTimer.Enabled = true; m_heartbeatTimer.Enabled = true;
m_heartbeatTimer.Interval = 100; m_heartbeatTimer.Interval = (int)(m_timespan * 1000);
m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
} }
@ -243,50 +254,108 @@ namespace OpenSim.Region.Environment.Scenes
/// </summary> /// </summary>
public override void Update() public override void Update()
{ {
TimeSpan SinceLastFrame = DateTime.Now - m_lastupdate;
// Aquire a lock so only one update call happens at once
updateLock.WaitOne(); updateLock.WaitOne();
try try
{ {
// Increment the frame counter
m_frame++;
// Loop it
if (m_frame == Int32.MaxValue)
m_frame = 0;
if (m_frame % m_update_physics == 0)
UpdatePreparePhysics();
if (m_frame % m_update_entitymovement == 0)
UpdateEntityMovement();
if (m_frame % m_update_physics == 0)
UpdatePhysics(
Math.Min(SinceLastFrame.TotalSeconds, 0.001)
);
if (m_frame % m_update_entities == 0)
UpdateEntities();
if (m_frame % m_update_events == 0)
UpdateEvents();
if (m_frame % m_update_backup == 0)
UpdateStorageBackup();
if (m_frame % m_update_terrain == 0)
UpdateTerrain();
if (m_frame % m_update_land == 0)
UpdateLand();
if (m_frame % m_update_avatars == 0)
UpdateAvatars();
}
catch (NotImplementedException)
{
throw;
}
catch (Exception e)
{
MainLog.Instance.Error("Scene", "Failed with exception " + e.ToString());
}
finally
{
updateLock.ReleaseMutex();
m_lastupdate = DateTime.Now;
}
}
private void UpdatePreparePhysics()
{
// If we are using a threaded physics engine
// grab the latest scene from the engine before
// trying to process it.
// PhysX does this (runs in the background).
if (phyScene.IsThreaded) if (phyScene.IsThreaded)
{ {
phyScene.GetResults(); phyScene.GetResults();
/// no engines implement this, and what does it have to do with threading? possible DEAD CODE }
} }
List<EntityBase> moveEntities = new List<EntityBase>(Entities.Values); private void UpdateAvatars()
foreach (EntityBase entity in moveEntities)
{ {
entity.UpdateMovement(); m_timeUpdateCount++;
if (m_timeUpdateCount > 600)
{
List<ScenePresence> avatars = GetAvatars();
foreach (ScenePresence avatar in avatars)
{
avatar.ControllingClient.SendViewerTime(m_timePhase);
} }
lock (m_syncRoot) m_timeUpdateCount = 0;
m_timePhase++;
if (m_timePhase > 94)
{ {
phyScene.Simulate(timeStep); m_timePhase = 0;
}
}
} }
List<EntityBase> updateEntities = new List<EntityBase>(Entities.Values); private void UpdateLand()
foreach (EntityBase entity in updateEntities)
{ {
entity.Update(); if (m_LandManager.landPrimCountTainted)
{
//Perform land update of prim count
performParcelPrimCountUpdate();
}
} }
// General purpose event manager private void UpdateTerrain()
m_eventManager.TriggerOnFrame();
//backup scene data
storageCount++;
if (storageCount > 1200) //set to how often you want to backup
{ {
Backup();
storageCount = 0;
}
terrainCheckCount++;
if (terrainCheckCount >= 50)
{
terrainCheckCount = 0;
if (Terrain.Tainted()) if (Terrain.Tainted())
{ {
CreateTerrainTexture(); CreateTerrainTexture();
@ -323,43 +392,42 @@ namespace OpenSim.Region.Environment.Scenes
} }
} }
landPrimCheckCount++; private void UpdateStorageBackup()
if (landPrimCheckCount > 50) //check every 5 seconds for tainted prims
{ {
if (m_LandManager.landPrimCountTainted) Backup();
}
private void UpdateEvents()
{ {
//Perform land update of prim count m_eventManager.TriggerOnFrame();
performParcelPrimCountUpdate(); }
landPrimCheckCount = 0;
private void UpdateEntities()
{
List<EntityBase> updateEntities = new List<EntityBase>(Entities.Values);
foreach (EntityBase entity in updateEntities)
{
entity.Update();
} }
} }
m_timeUpdateCount++; private void UpdatePhysics(double elapsed)
if (m_timeUpdateCount > 600)
{ {
List<ScenePresence> avatars = GetAvatars(); lock (m_syncRoot)
foreach (ScenePresence avatar in avatars)
{ {
avatar.ControllingClient.SendViewerTime(m_timePhase); phyScene.Simulate((float)elapsed);
}
} }
m_timeUpdateCount = 0; private void UpdateEntityMovement()
m_timePhase++;
if (m_timePhase > 94)
{ {
m_timePhase = 0; List<EntityBase> moveEntities = new List<EntityBase>(Entities.Values);
}
} foreach (EntityBase entity in moveEntities)
}
catch (NotImplementedException)
{ {
throw; entity.UpdateMovement();
} }
catch (Exception e)
{
MainLog.Instance.Error("Scene", "Failed with exception " + e.ToString());
}
updateLock.ReleaseMutex();
} }
/// <summary> /// <summary>