diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index b876fc6e41..2a69ee1218 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -423,6 +423,17 @@ namespace OpenSim.Region.Framework.Scenes private int landMS; private int spareMS; + // A temporary configuration flag to enable using FireAndForget to process + // collisions from the physics engine. There is a problem with collisions + // stopping sometimes and MB's suspicion is some race condition passing + // collisions from the physics engine callback to the script engine. + // This causes the collision events to be passed with a FireAndForget + // call which should eliminate that linkage. Testers can turn this on + // and see if collisions stop. If they don't, the problem is somewhere else. + // This feature defaults to 'off' so, by default, the simulator operation + // is not changed. + public bool ShouldUseFireAndForgetForCollisions = false; + /// /// Tick at which the last frame was processed. /// @@ -1075,8 +1086,14 @@ namespace OpenSim.Region.Framework.Scenes m_update_presences = startupConfig.GetInt("UpdateAgentsEveryNFrames", m_update_presences); m_update_terrain = startupConfig.GetInt("UpdateTerrainEveryNFrames", m_update_terrain); m_update_temp_cleaning = startupConfig.GetInt("UpdateTempCleaningEveryNSeconds", m_update_temp_cleaning); + + if (startupConfig.Contains("ShouldUseFireAndForgetForCollisions")) + { + ShouldUseFireAndForgetForCollisions = startupConfig.GetBoolean("ShouldUseFireAndForgetForCollisions", false); + } } + // FIXME: Ultimately this should be in a module. SendPeriodicAppearanceUpdates = false; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 781c20c943..f52c9c8fe3 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -126,6 +126,8 @@ namespace OpenSim.Region.Framework.Scenes private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private bool shouldUseFireAndForgetForCollisions = true; + /// /// Dynamic attributes can be created and deleted as required. /// @@ -2392,7 +2394,7 @@ namespace OpenSim.Region.Framework.Scenes CollidingMessage = CreateColliderArgs(this, colliders); if (CollidingMessage.Colliders.Count > 0) - notify(LocalId, CollidingMessage); + DoNotify(notify, LocalId, CollidingMessage); if (PassCollisions) sendToRoot = true; @@ -2406,7 +2408,7 @@ namespace OpenSim.Region.Framework.Scenes { CollidingMessage = CreateColliderArgs(ParentGroup.RootPart, colliders); if (CollidingMessage.Colliders.Count > 0) - notify(ParentGroup.RootPart.LocalId, CollidingMessage); + DoNotify(notify, ParentGroup.RootPart.LocalId, CollidingMessage); } } } @@ -2421,7 +2423,33 @@ namespace OpenSim.Region.Framework.Scenes colliding.Add(CreateDetObjectForGround()); LandCollidingMessage.Colliders = colliding; - notify(LocalId, LandCollidingMessage); + DoNotify(notify, LocalId, LandCollidingMessage); + } + } + + private void DoNotify(ScriptCollidingNotification notify, uint id, ColliderArgs collargs) + { + if (m_parentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.ShouldUseFireAndForgetForCollisions) + { + // For those learning C#, FireAndForget takes a function, an object to pass + // to that function and an ID string. The "oo => {}" construct is a lambda expression + // for a function with one arguement ('oo'). The 'new Object[] {}" construct creates an Object + // that is an object array and initializes it with three items (the parameters + // being passed). The parameters passed are the function to call ('notify') and + // its two arguements. Finally, once in the function (called later by the FireAndForget + // thread scheduler), the passed object is cast to an object array and then each + // of its items (aoo[0] to aoo[2]) are individually cast to what they are and + // then used in a call of the passed ScriptCollidingNotification function. + Util.FireAndForget(oo => + { + Object[] aoo = (Object[])oo; + ((ScriptCollidingNotification)aoo[0])((uint)aoo[1], (ColliderArgs)aoo[2]); + + }, new Object[] { notify, id, collargs }, "SOP.Collision"); + } + else + { + notify(id, collargs); } }