Lock the object queue when dequeueing
parent
f8e2d25739
commit
c900134f91
|
@ -67,105 +67,108 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public void SendPrimUpdates()
|
public void SendPrimUpdates()
|
||||||
{
|
{
|
||||||
if (m_pendingObjects == null)
|
lock(m_pendingObjects)
|
||||||
{
|
{
|
||||||
if (!m_presence.IsChildAgent || (m_presence.Scene.m_seeIntoRegionFromNeighbor))
|
if (m_pendingObjects == null)
|
||||||
{
|
{
|
||||||
m_pendingObjects = new Queue<SceneObjectGroup>();
|
if (!m_presence.IsChildAgent || (m_presence.Scene.m_seeIntoRegionFromNeighbor))
|
||||||
|
|
||||||
foreach (EntityBase e in m_presence.Scene.Entities)
|
|
||||||
{
|
{
|
||||||
if (e != null && e is SceneObjectGroup)
|
m_pendingObjects = new Queue<SceneObjectGroup>();
|
||||||
m_pendingObjects.Enqueue((SceneObjectGroup)e);
|
|
||||||
|
foreach (EntityBase e in m_presence.Scene.Entities)
|
||||||
|
{
|
||||||
|
if (e != null && e is SceneObjectGroup)
|
||||||
|
m_pendingObjects.Enqueue((SceneObjectGroup)e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
while (m_pendingObjects != null && m_pendingObjects.Count > 0)
|
while (m_pendingObjects != null && m_pendingObjects.Count > 0)
|
||||||
{
|
|
||||||
SceneObjectGroup g = m_pendingObjects.Dequeue();
|
|
||||||
// Yes, this can really happen
|
|
||||||
if (g == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// This is where we should check for draw distance
|
|
||||||
// do culling and stuff. Problem with that is that until
|
|
||||||
// we recheck in movement, that won't work right.
|
|
||||||
// So it's not implemented now.
|
|
||||||
//
|
|
||||||
|
|
||||||
// Don't even queue if we have sent this one
|
|
||||||
//
|
|
||||||
if (!m_updateTimes.ContainsKey(g.UUID))
|
|
||||||
g.ScheduleFullUpdateToAvatar(m_presence);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (m_partsUpdateQueue.Count > 0)
|
|
||||||
{
|
|
||||||
SceneObjectPart part = m_partsUpdateQueue.Dequeue();
|
|
||||||
|
|
||||||
if (part.ParentGroup == null || part.ParentGroup.IsDeleted)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (m_updateTimes.ContainsKey(part.UUID))
|
|
||||||
{
|
{
|
||||||
ScenePartUpdate update = m_updateTimes[part.UUID];
|
SceneObjectGroup g = m_pendingObjects.Dequeue();
|
||||||
|
// Yes, this can really happen
|
||||||
|
if (g == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
// We deal with the possibility that two updates occur at
|
// This is where we should check for draw distance
|
||||||
// the same unix time at the update point itself.
|
// do culling and stuff. Problem with that is that until
|
||||||
|
// we recheck in movement, that won't work right.
|
||||||
|
// So it's not implemented now.
|
||||||
|
//
|
||||||
|
|
||||||
if ((update.LastFullUpdateTime < part.TimeStampFull) ||
|
// Don't even queue if we have sent this one
|
||||||
part.IsAttachment)
|
//
|
||||||
|
if (!m_updateTimes.ContainsKey(g.UUID))
|
||||||
|
g.ScheduleFullUpdateToAvatar(m_presence);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (m_partsUpdateQueue.Count > 0)
|
||||||
|
{
|
||||||
|
SceneObjectPart part = m_partsUpdateQueue.Dequeue();
|
||||||
|
|
||||||
|
if (part.ParentGroup == null || part.ParentGroup.IsDeleted)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (m_updateTimes.ContainsKey(part.UUID))
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat(
|
ScenePartUpdate update = m_updateTimes[part.UUID];
|
||||||
// "[SCENE PRESENCE]: Fully updating prim {0}, {1} - part timestamp {2}",
|
|
||||||
// part.Name, part.UUID, part.TimeStampFull);
|
// We deal with the possibility that two updates occur at
|
||||||
|
// the same unix time at the update point itself.
|
||||||
|
|
||||||
|
if ((update.LastFullUpdateTime < part.TimeStampFull) ||
|
||||||
|
part.IsAttachment)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[SCENE PRESENCE]: Fully updating prim {0}, {1} - part timestamp {2}",
|
||||||
|
// part.Name, part.UUID, part.TimeStampFull);
|
||||||
|
|
||||||
|
part.SendFullUpdate(m_presence.ControllingClient,
|
||||||
|
m_presence.GenerateClientFlags(part.UUID));
|
||||||
|
|
||||||
|
// We'll update to the part's timestamp rather than
|
||||||
|
// the current time to avoid the race condition
|
||||||
|
// whereby the next tick occurs while we are doing
|
||||||
|
// this update. If this happened, then subsequent
|
||||||
|
// updates which occurred on the same tick or the
|
||||||
|
// next tick of the last update would be ignored.
|
||||||
|
|
||||||
|
update.LastFullUpdateTime = part.TimeStampFull;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (update.LastTerseUpdateTime <= part.TimeStampTerse)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[SCENE PRESENCE]: Tersely updating prim {0}, {1} - part timestamp {2}",
|
||||||
|
// part.Name, part.UUID, part.TimeStampTerse);
|
||||||
|
|
||||||
|
part.SendTerseUpdateToClient(m_presence.ControllingClient);
|
||||||
|
|
||||||
|
update.LastTerseUpdateTime = part.TimeStampTerse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//never been sent to client before so do full update
|
||||||
|
ScenePartUpdate update = new ScenePartUpdate();
|
||||||
|
update.FullID = part.UUID;
|
||||||
|
update.LastFullUpdateTime = part.TimeStampFull;
|
||||||
|
m_updateTimes.Add(part.UUID, update);
|
||||||
|
|
||||||
|
// Attachment handling
|
||||||
|
//
|
||||||
|
if (part.ParentGroup.RootPart.Shape.PCode == 9 && part.ParentGroup.RootPart.Shape.State != 0)
|
||||||
|
{
|
||||||
|
if (part != part.ParentGroup.RootPart)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
part.ParentGroup.SendFullUpdateToClient(m_presence.ControllingClient);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
part.SendFullUpdate(m_presence.ControllingClient,
|
part.SendFullUpdate(m_presence.ControllingClient,
|
||||||
m_presence.GenerateClientFlags(part.UUID));
|
m_presence.GenerateClientFlags(part.UUID));
|
||||||
|
|
||||||
// We'll update to the part's timestamp rather than
|
|
||||||
// the current time to avoid the race condition
|
|
||||||
// whereby the next tick occurs while we are doing
|
|
||||||
// this update. If this happened, then subsequent
|
|
||||||
// updates which occurred on the same tick or the
|
|
||||||
// next tick of the last update would be ignored.
|
|
||||||
|
|
||||||
update.LastFullUpdateTime = part.TimeStampFull;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (update.LastTerseUpdateTime <= part.TimeStampTerse)
|
|
||||||
{
|
|
||||||
// m_log.DebugFormat(
|
|
||||||
// "[SCENE PRESENCE]: Tersely updating prim {0}, {1} - part timestamp {2}",
|
|
||||||
// part.Name, part.UUID, part.TimeStampTerse);
|
|
||||||
|
|
||||||
part.SendTerseUpdateToClient(m_presence.ControllingClient);
|
|
||||||
|
|
||||||
update.LastTerseUpdateTime = part.TimeStampTerse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//never been sent to client before so do full update
|
|
||||||
ScenePartUpdate update = new ScenePartUpdate();
|
|
||||||
update.FullID = part.UUID;
|
|
||||||
update.LastFullUpdateTime = part.TimeStampFull;
|
|
||||||
m_updateTimes.Add(part.UUID, update);
|
|
||||||
|
|
||||||
// Attachment handling
|
|
||||||
//
|
|
||||||
if (part.ParentGroup.RootPart.Shape.PCode == 9 && part.ParentGroup.RootPart.Shape.State != 0)
|
|
||||||
{
|
|
||||||
if (part != part.ParentGroup.RootPart)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
part.ParentGroup.SendFullUpdateToClient(m_presence.ControllingClient);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
part.SendFullUpdate(m_presence.ControllingClient,
|
|
||||||
m_presence.GenerateClientFlags(part.UUID));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue