In SceneViewer, introduce an IsEnabled flag and perform Close() under an m_pendingObjects lock in order to avoid the race condition seen by danbanner in http://opensimulator.org/mantis/view.php?id=5669
parent
1a8f5b97b9
commit
4bf3adffb8
|
@ -30,12 +30,21 @@ using OpenSim.Region.Framework.Scenes;
|
||||||
|
|
||||||
namespace OpenSim.Region.Framework.Interfaces
|
namespace OpenSim.Region.Framework.Interfaces
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Sends scheduled updates to it's associated ScenePresence.
|
||||||
|
/// </summary>
|
||||||
public interface ISceneViewer
|
public interface ISceneViewer
|
||||||
{
|
{
|
||||||
void Reset();
|
void Reset();
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add the part to the queue of parts for which we need to send an update to the client
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="part"></param>
|
||||||
void QueuePartForUpdate(SceneObjectPart part);
|
void QueuePartForUpdate(SceneObjectPart part);
|
||||||
|
|
||||||
void SendPrimUpdates();
|
void SendPrimUpdates();
|
||||||
int GetPendingObjectsCount();
|
int GetPendingObjectsCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -38,27 +38,42 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
public class SceneViewer : ISceneViewer
|
public class SceneViewer : ISceneViewer
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Is this scene viewer enabled?
|
||||||
|
/// </summary>
|
||||||
|
private bool IsEnabled { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The scene presence serviced by this viewer.
|
||||||
|
/// </summary>
|
||||||
protected ScenePresence m_presence;
|
protected ScenePresence m_presence;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The queue of parts for which we need to send out updates.
|
||||||
|
/// </summary>
|
||||||
protected UpdateQueue m_partsUpdateQueue = new UpdateQueue();
|
protected UpdateQueue m_partsUpdateQueue = new UpdateQueue();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The queue of objects for which we need to send out updates.
|
||||||
|
/// </summary>
|
||||||
protected Queue<SceneObjectGroup> m_pendingObjects;
|
protected Queue<SceneObjectGroup> m_pendingObjects;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The last update assocated with a given part update.
|
||||||
|
/// </summary>
|
||||||
protected Dictionary<UUID, ScenePartUpdate> m_updateTimes = new Dictionary<UUID, ScenePartUpdate>();
|
protected Dictionary<UUID, ScenePartUpdate> m_updateTimes = new Dictionary<UUID, ScenePartUpdate>();
|
||||||
|
|
||||||
public SceneViewer()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SceneViewer(ScenePresence presence)
|
public SceneViewer(ScenePresence presence)
|
||||||
{
|
{
|
||||||
m_presence = presence;
|
m_presence = presence;
|
||||||
|
IsEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Add the part to the queue of parts for which we need to send an update to the client
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="part"></param>
|
|
||||||
public void QueuePartForUpdate(SceneObjectPart part)
|
public void QueuePartForUpdate(SceneObjectPart part)
|
||||||
{
|
{
|
||||||
|
if (!IsEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
lock (m_partsUpdateQueue)
|
lock (m_partsUpdateQueue)
|
||||||
{
|
{
|
||||||
m_partsUpdateQueue.Enqueue(part);
|
m_partsUpdateQueue.Enqueue(part);
|
||||||
|
@ -87,6 +102,11 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
lock (m_pendingObjects)
|
lock (m_pendingObjects)
|
||||||
{
|
{
|
||||||
|
// We must do this under lock so that we don't suffer a race condition if another thread closes the
|
||||||
|
// viewer
|
||||||
|
if (!IsEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
while (m_pendingObjects != null && m_pendingObjects.Count > 0)
|
while (m_pendingObjects != null && m_pendingObjects.Count > 0)
|
||||||
{
|
{
|
||||||
SceneObjectGroup g = m_pendingObjects.Dequeue();
|
SceneObjectGroup g = m_pendingObjects.Dequeue();
|
||||||
|
@ -119,7 +139,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
// We deal with the possibility that two updates occur at
|
// We deal with the possibility that two updates occur at
|
||||||
// the same unix time at the update point itself.
|
// the same unix time at the update point itself.
|
||||||
|
|
||||||
if ((update.LastFullUpdateTime < part.TimeStampFull) || part.ParentGroup.IsAttachment)
|
if ((update.LastFullUpdateTime < part.TimeStampFull) || part.ParentGroup.IsAttachment)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
|
@ -135,9 +154,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// this update. If this happened, then subsequent
|
// this update. If this happened, then subsequent
|
||||||
// updates which occurred on the same tick or the
|
// updates which occurred on the same tick or the
|
||||||
// next tick of the last update would be ignored.
|
// next tick of the last update would be ignored.
|
||||||
|
|
||||||
update.LastFullUpdateTime = part.TimeStampFull;
|
update.LastFullUpdateTime = part.TimeStampFull;
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (update.LastTerseUpdateTime <= part.TimeStampTerse)
|
else if (update.LastTerseUpdateTime <= part.TimeStampTerse)
|
||||||
{
|
{
|
||||||
|
@ -193,15 +210,21 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
lock (m_updateTimes)
|
lock (m_pendingObjects)
|
||||||
{
|
{
|
||||||
m_updateTimes.Clear();
|
IsEnabled = false;
|
||||||
|
|
||||||
|
lock (m_updateTimes)
|
||||||
|
{
|
||||||
|
m_updateTimes.Clear();
|
||||||
|
}
|
||||||
|
lock (m_partsUpdateQueue)
|
||||||
|
{
|
||||||
|
m_partsUpdateQueue.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
Reset();
|
||||||
}
|
}
|
||||||
lock (m_partsUpdateQueue)
|
|
||||||
{
|
|
||||||
m_partsUpdateQueue.Clear();
|
|
||||||
}
|
|
||||||
Reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetPendingObjectsCount()
|
public int GetPendingObjectsCount()
|
||||||
|
|
Loading…
Reference in New Issue