protected SolverUpdateable() { //Initialize the connection. //It will usually be overridden and end up floating on back to the resource pool. simulationIslandConnection = PhysicsResources.GetSimulationIslandConnection(); simulationIslandConnection.Owner = this; }
/// <summary> /// Returns a resource to the pool. /// </summary> /// <param name="connection">Connection to return.</param> public static void GiveBack(SimulationIslandConnection connection) { if (SimulationIslandConnections == null) { SimulationIslandConnections = new UnsafeResourcePool <SimulationIslandConnection>(); } connection.CleanUp(); SimulationIslandConnections.GiveBack(connection); }
///<summary> /// Removes a connection reference from the member. ///</summary> ///<param name="connection">Reference to remove.</param> ///<param name="index">Index of the connection in this member's list</param> internal void RemoveConnectionReference(SimulationIslandConnection connection, int index) { if (connections.Count > index) { connections.FastRemoveAt(index); if (connections.Count > index) { connections.Elements[index].SetListIndex(this, index); } } }
///<summary> /// Removes a simulation island connection from the manager. ///</summary> ///<param name="connection">Connection to remove from the manager.</param> ///<exception cref="ArgumentException">Thrown if the connection does not belong to this manager.</exception> public void Remove(SimulationIslandConnection connection) { if (connection.DeactivationManager == this) { connection.DeactivationManager = null; connection.SlatedForRemoval = true; //Don't immediately do simulation island management. //Defer the splits! splitAttempts.Enqueue(connection); } else { throw new ArgumentException("Cannot remove connection from activity manager; it is owned by a different or no activity manager."); } }
///<summary> /// Adds a simulation island connection to the deactivation manager. ///</summary> ///<param name="connection">Connection to add.</param> ///<exception cref="ArgumentException">Thrown if the connection already belongs to a manager.</exception> public void Add(SimulationIslandConnection connection) { //DO A MERGE IF NECESSARY if (connection.DeactivationManager == null) { addLocker.Enter(); connection.DeactivationManager = this; if (connection.entries.Count > 0) { var island = connection.entries.Elements[0].Member.SimulationIsland; for (int i = 1; i < connection.entries.Count; i++) { SimulationIsland opposingIsland; if (island != (opposingIsland = connection.entries.Elements[i].Member.SimulationIsland)) { //Need to do a merge between the two islands. //Note that this merge may eliminate the need for a merge with subsequent connection if they belong to the same island. island = Merge(island, opposingIsland); } } //If it was slated for removal, that means the flush stage will try to split it. //Since it was just added back, splitting is known to be pointless. //Just set the flag and the flush will ignore the split attempt. if (connection.SlatedForRemoval) { connection.SlatedForRemoval = false; } else { //If the connection was NOT slated for removal, that means the reference don't currently exist. //(If the connection was slated for removal, that would imply the connection existed previously, so it must have had references.) connection.AddReferencesToConnectedMembers(); } } addLocker.Exit(); } else { throw new ArgumentException("Cannot add connection to deactivation manager; it already belongs to one."); } }
void UpdateConnectedMembers() { //Since we're about to change this updateable's connections, make sure the //simulation islands hear about it. This is NOT thread safe. var deactivationManager = simulationIslandConnection.DeactivationManager; //Orphan the simulation island connection since it's about to get replaced. //There's three possible situations here: //1) We belong to the DeactivationManager. //2) We don't belong to a DeactivationManager and the connection is slated for removal (we were in the deactivation manager before). // This can happen when a solver updateable associated with a pair gets removed and cleaned up. //3) We don't belong to a DeactivationManager and the connection is not slated for removal (we weren't in a deactivation manager before). //In Case #1, all we have to do is orphan the connection and remove it from the manager. This performs any splits necessary. The replacement connection will force any necessary merges. //In Case #2, we were just removed but the connection is still considered to have an owner. //It won't get cleaned up by the removal, and doing it here would be premature: orphan the connection so the next deactivation manager splits flush cleans it up! //In Case #3, we have full control over the simulation island connection because there is no interaction with a deactivation manager. We can just get rid of it directly. simulationIslandConnection.Owner = null; if (deactivationManager != null) { deactivationManager.Remove(simulationIslandConnection); } else if (!simulationIslandConnection.SlatedForRemoval) //If it's already been removed, cleaning it ourselves would prevent proper simulation island splits in the deactivation manager split flush. { PhysicsResources.GiveBack(simulationIslandConnection); //Well, since we're going to orphan the connection, we'll need to take care of its trash. } //The SimulationIslandConnection is immutable. //So create a new one! //Assume we've already dealt with the old connection. simulationIslandConnection = PhysicsResources.GetSimulationIslandConnection(); for (int i = 0; i < involvedEntities.Count; i++) { simulationIslandConnection.Add(involvedEntities.Elements[i].activityInformation); } simulationIslandConnection.Owner = this; //Add the new reference back. if (deactivationManager != null) { deactivationManager.Add(simulationIslandConnection); } }
///<summary> /// Adds a connection reference to the member. ///</summary> ///<param name="connection">Reference to add.</param> ///<returns>Index of the connection in the member's list.</returns> internal int AddConnectionReference(SimulationIslandConnection connection) { connections.Add(connection); return(connections.Count - 1); }