parallelization isn't worth it unless we can reasonably estimate our workload before initiating

implement double checked locking
change active solution to x64
map thread-safety
This commit is contained in:
Mark Sturgill 2013-10-17 20:25:11 -07:00
parent bcafcacdbb
commit fe1f40f927
6 changed files with 121 additions and 138 deletions

View file

@ -232,8 +232,7 @@ Global
{0B33CEEB-88E1-49A6-8D7D-AF6A5A357087}.Debug|Any CPU.ActiveCfg = Debug|x86
{0B33CEEB-88E1-49A6-8D7D-AF6A5A357087}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{0B33CEEB-88E1-49A6-8D7D-AF6A5A357087}.Debug|Mixed Platforms.Build.0 = Debug|x86
{0B33CEEB-88E1-49A6-8D7D-AF6A5A357087}.Debug|x64.ActiveCfg = Debug|x64
{0B33CEEB-88E1-49A6-8D7D-AF6A5A357087}.Debug|x64.Build.0 = Debug|x64
{0B33CEEB-88E1-49A6-8D7D-AF6A5A357087}.Debug|x64.ActiveCfg = Debug|x86
{0B33CEEB-88E1-49A6-8D7D-AF6A5A357087}.Debug|x86.ActiveCfg = Debug|x86
{0B33CEEB-88E1-49A6-8D7D-AF6A5A357087}.Debug|x86.Build.0 = Debug|x86
{0B33CEEB-88E1-49A6-8D7D-AF6A5A357087}.Release|Any CPU.ActiveCfg = Release|x86

View file

@ -1615,10 +1615,15 @@ namespace Server
{
get
{
lock (_rpl) {
if ( m_RemovePacket == null ) {
m_RemovePacket = new RemoveItem( this );
m_RemovePacket.SetStatic();
if (m_RemovePacket == null)
{
lock (_rpl)
{
if (m_RemovePacket == null)
{
m_RemovePacket = new RemoveItem(this);
m_RemovePacket.SetStatic();
}
}
}
@ -1632,10 +1637,15 @@ namespace Server
{
get
{
lock (_opll) {
if ( m_OPLPacket == null ) {
m_OPLPacket = new OPLInfo( PropertyList );
m_OPLPacket.SetStatic();
if (m_OPLPacket == null)
{
lock (_opll)
{
if (m_OPLPacket == null)
{
m_OPLPacket = new OPLInfo(PropertyList);
m_OPLPacket.SetStatic();
}
}
}
@ -1723,10 +1733,15 @@ namespace Server
// - Packet Flags
// - Direction
lock (_wpl) {
if ( m_WorldPacket == null ) {
m_WorldPacket = new WorldItem( this );
m_WorldPacket.SetStatic();
if (m_WorldPacket == null)
{
lock (_wpl)
{
if (m_WorldPacket == null)
{
m_WorldPacket = new WorldItem(this);
m_WorldPacket.SetStatic();
}
}
}
@ -1746,10 +1761,15 @@ namespace Server
// - Packet Flags
// - Direction
lock (_wplsa) {
if ( m_WorldPacketSA == null ) {
m_WorldPacketSA = new WorldItemSA( this );
m_WorldPacketSA.SetStatic();
if (m_WorldPacketSA == null)
{
lock (_wplsa)
{
if (m_WorldPacketSA == null)
{
m_WorldPacketSA = new WorldItemSA(this);
m_WorldPacketSA.SetStatic();
}
}
}
@ -1769,10 +1789,15 @@ namespace Server
// - Packet Flags
// - Direction
lock (_wplhs) {
if ( m_WorldPacketHS == null ) {
m_WorldPacketHS = new WorldItemHS( this );
m_WorldPacketHS.SetStatic();
if (m_WorldPacketHS == null)
{
lock (_wplhs)
{
if (m_WorldPacketHS == null)
{
m_WorldPacketHS = new WorldItemHS(this);
m_WorldPacketHS.SetStatic();
}
}
}
@ -3282,8 +3307,15 @@ namespace Server
{
#if Framework_4_0
_processing = true;
Parallel.ForEach( m_DeltaQueue, i => i.ProcessDelta() );
if (m_DeltaQueue.Count >= 64) {
Parallel.ForEach(m_DeltaQueue, i => i.ProcessDelta());
} else {
for (int i = 0; i < m_DeltaQueue.Count; i++) m_DeltaQueue[i].ProcessDelta();
}
m_DeltaQueue.Clear();
_processing = false;
#else
int count = m_DeltaQueue.Count;

View file

@ -1845,7 +1845,7 @@ namespace Server
int height;
bool found;
Point3D p;
Point3DList path = m_PathList;
Point3DList path = new Point3DList();
TileFlag flags;
if( org == dest )
@ -2087,7 +2087,6 @@ namespace Server
set { m_InvalidLandTiles = value; }
}
private static Point3DList m_PathList = new Point3DList();
public int CompareTo( Map other )
{
if ( other == null )

View file

@ -3317,41 +3317,31 @@ namespace Server
for( int j = 0; j < cache[i].Length; ++j )
Packet.Release( ref cache[i][j] );*/
object cacheSync = new object();
#if Framework_4_0
Parallel.ForEach(m_MoveClientList, m => {
#else
foreach(Mobile m in m_MoveClientList) {
#endif
NetState ns = m.NetState;
if (ns != null && Utility.InUpdateRange(m_Location, m.m_Location) && m.CanSee(this)) {
if (ns.StygianAbyss) {
Packet p;
int noto = Notoriety.Compute(m, this);
lock (cacheSync) {
p = cache[0][noto];
p = cache[0][noto];
if (p == null)
cache[0][noto] = p = Packet.Acquire(new MobileMoving(this, noto));
if (p == null)
cache[0][noto] = p = Packet.Acquire(new MobileMoving(this, noto));
}
ns.Send(p);
} else {
Packet p;
int noto = Notoriety.Compute(m, this);
lock (cacheSync) {
p = cache[1][noto];
p = cache[1][noto];
if (p == null)
cache[1][noto] = p = Packet.Acquire(new MobileMovingOld(this, noto));
if (p == null)
cache[1][noto] = p = Packet.Acquire(new MobileMovingOld(this, noto));
}
ns.Send(p);
}
}
}
#if Framework_4_0
);
#endif
for (int i = 0; i < cache.Length; ++i)
for (int j = 0; j < cache[i].Length; ++j)
@ -4692,8 +4682,7 @@ namespace Server
Item item = cont.Items[i];
if(item.HandlesOnSpeech)
lock (list)
list.Add( item );
list.Add( item );
if(item is Container)
AddSpeechItemsFrom(list, (Container)item);
@ -4841,31 +4830,24 @@ namespace Server
{
IPooledEnumerable<IEntity> eable = m_Map.GetObjectsInRange( m_Location, range );
#if Framework_4_0
Parallel.ForEach(eable, o => {
#else
foreach(IEntity o in eable) {
#endif
if( o is Mobile ) {
Mobile heard = (Mobile)o;
if( heard.CanSee( this ) && (m_NoSpeechLOS || !heard.Player || heard.InLOS( this )) )
{
if( heard.m_NetState != null )
lock (hears)
hears.Add( heard );
hears.Add( heard );
if( heard.HandlesOnSpeech( this ) )
lock (onSpeech)
onSpeech.Add( heard );
onSpeech.Add( heard );
for( int i = 0; i < heard.Items.Count; ++i )
{
Item item = heard.Items[i];
if( item.HandlesOnSpeech )
lock (onSpeech)
onSpeech.Add( item );
onSpeech.Add( item );
if( item is Container )
AddSpeechItemsFrom( onSpeech, (Container)item );
@ -4875,16 +4857,12 @@ namespace Server
else if( o is Item )
{
if( ((Item)o).HandlesOnSpeech )
lock (onSpeech)
onSpeech.Add(o);
onSpeech.Add(o);
if( o is Container )
AddSpeechItemsFrom( onSpeech, (Container)o );
}
}
#if Framework_4_0
);
#endif
eable.Free();
@ -6576,11 +6554,8 @@ namespace Server
if( m_Map != null && ns != null )
{
IPooledEnumerable<IEntity> eable = m_Map.GetObjectsInRange( m_Location, Core.GlobalMaxUpdateRange );
#if Framework_4_0
Parallel.ForEach(eable, o => {
#else
foreach ( IEntity o in eable ) {
#endif
if( o is Mobile ) {
Mobile m = (Mobile)o;
@ -6593,9 +6568,6 @@ namespace Server
ns.Send( item.RemovePacket );
}
}
#if Framework_4_0
);
#endif
eable.Free();
}
@ -6781,11 +6753,8 @@ namespace Server
if( m_Map != null && ns != null )
{
IPooledEnumerable<IEntity> eable = m_Map.GetObjectsInRange( m_Location, Core.GlobalMaxUpdateRange );
#if Framework_4_0
Parallel.ForEach(eable, o => {
#else
foreach ( IEntity o in eable ) {
#endif
if( o is Item ) {
Item item = (Item)o;
@ -6819,9 +6788,6 @@ namespace Server
}
}
}
#if Framework_4_0
);
#endif
eable.Free();
}
@ -8850,10 +8816,15 @@ namespace Server
{
get
{
lock (rpLock) {
if (m_RemovePacket == null) {
m_RemovePacket = new RemoveMobile(this);
m_RemovePacket.SetStatic();
if (m_RemovePacket == null)
{
lock (rpLock)
{
if (m_RemovePacket == null)
{
m_RemovePacket = new RemoveMobile(this);
m_RemovePacket.SetStatic();
}
}
}
@ -8868,10 +8839,15 @@ namespace Server
{
get
{
lock (oplLock) {
if( m_OPLPacket == null ) {
m_OPLPacket = new OPLInfo( PropertyList );
m_OPLPacket.SetStatic();
if (m_OPLPacket == null)
{
lock (oplLock)
{
if (m_OPLPacket == null)
{
m_OPLPacket = new OPLInfo(PropertyList);
m_OPLPacket.SetStatic();
}
}
}
@ -9109,11 +9085,8 @@ namespace Server
IPooledEnumerable<IEntity> eeable = map.GetObjectsInRange( newLocation, Core.GlobalMaxUpdateRange );
// We are attached to a client, so it's a bit more complex. We need to send new items and people to ourself, and ourself to other clients
#if Framework_4_0
Parallel.ForEach(eeable, o => {
#else
foreach ( IEntity o in eeable ) {
#endif
if( o is Item )
{
Item item = (Item)o;
@ -9129,11 +9102,8 @@ namespace Server
Mobile m = (Mobile)o;
if( !Utility.InUpdateRange( newLocation, m.m_Location ) )
#if Framework_4_0
return;
#else
continue;
#endif
bool inOldRange = Utility.InUpdateRange( oldLocation, m.m_Location );
if( m.m_NetState != null && ( ( isTeleport && ( !m.m_NetState.HighSeas || !m_NoMoveHS ) ) || !inOldRange ) && m.CanSee( this ) )
@ -9185,9 +9155,6 @@ namespace Server
}
}
}
#if Framework_4_0
);
#endif
eeable.Free();
}
@ -10360,11 +10327,17 @@ namespace Server
{
#if Framework_4_0
_processing = true;
Parallel.ForEach( m_DeltaQueue, m => m.ProcessDelta() );
m_DeltaQueue.Clear();
if (m_DeltaQueue.Count >= 64) {
Parallel.ForEach(m_DeltaQueue, m => m.ProcessDelta());
m_DeltaQueue.Clear();
} else {
while (m_DeltaQueueR.Count > 0) m_DeltaQueueR.Dequeue().ProcessDelta();
}
_processing = false;
Parallel.ForEach( m_DeltaQueueR, m => m.ProcessDelta() );
m_DeltaQueueR.Clear();
while (m_DeltaQueueR.Count > 0) m_DeltaQueueR.Dequeue().ProcessDelta();
#else
int count = m_DeltaQueue.Count;
int index = 0;

View file

@ -1052,12 +1052,13 @@ namespace Server.Network {
public static void FlushAll() {
#if Framework_4_0
Parallel.ForEach( m_Instances, ns => ns.Flush() );
#else
for ( int i = 0; i < m_Instances.Count; ++i ) {
m_Instances[i].Flush();
}
if (m_Instances.Count >= 128)
Parallel.ForEach(m_Instances, ns => ns.Flush());
else
#endif
for ( int i = 0; i < m_Instances.Count; ++i ) {
m_Instances[i].Flush();
}
}
private static int m_CoalesceSleep = -1;
@ -1073,18 +1074,18 @@ namespace Server.Network {
private long m_NextCheckActivity;
public bool CheckAlive() {
public void CheckAlive(long curTicks) {
if ( m_Socket == null )
return false;
return;
if (m_NextCheckActivity - Core.TickCount >= 0) {
return true;
if (m_NextCheckActivity - curTicks >= 0) {
return;
}
Console.WriteLine( "Client: {0}: Disconnecting due to inactivity...", this );
Dispose();
return false;
return;
}
public static void TraceException( Exception ex ) {
@ -1172,13 +1173,15 @@ namespace Server.Network {
public static void CheckAllAlive() {
try {
long curTicks = Core.TickCount;
#if Framework_4_0
Parallel.ForEach( m_Instances, ns => ns.CheckAlive() );
#else
for ( int i = 0; i < m_Instances.Count; ++i ) {
m_Instances[i].CheckAlive();
}
if (m_Instances.Count >= 512)
Parallel.ForEach(m_Instances, ns => ns.CheckAlive(curTicks));
else
#endif
for ( int i = 0; i < m_Instances.Count; ++i ) {
m_Instances[i].CheckAlive(curTicks);
}
} catch ( Exception ex ) {
TraceException( ex );
}

View file

@ -276,31 +276,8 @@ namespace Server
private static void ProcessChanged()
{
lock (m_Changed) {
#if Framework_4_0
Parallel.ForEach(m_Changed.Values, tce => {
Timer timer = tce.m_Timer;
int newIndex = tce.m_NewIndex;
long curTicks = Core.TickCount;
if (timer.m_List != null)
lock (timer.m_List)
timer.m_List.Remove(timer);
if (tce.m_IsAdd) {
timer.m_Next = Core.TickCount + timer.m_Delay;
timer.m_Index = 0;
}
if (newIndex >= 0) {
timer.m_List = m_Timers[newIndex];
lock (timer.m_List)
timer.m_List.Add(timer);
} else {
timer.m_List = null;
}
tce.Free();
});
#else
foreach (TimerChangeEntry tce in m_Changed.Values) {
Timer timer = tce.m_Timer;
int newIndex = tce.m_NewIndex;
@ -309,7 +286,7 @@ namespace Server
timer.m_List.Remove(timer);
if (tce.m_IsAdd) {
timer.m_Next = Core.TickCount + timer.m_Delay;
timer.m_Next = curTicks + timer.m_Delay;
timer.m_Index = 0;
}
@ -322,7 +299,7 @@ namespace Server
tce.Free();
}
#endif
m_Changed.Clear();
}
}