diff --git a/Server/Random.cs b/Server/Random.cs index 6311482d4..58463ff1d 100644 --- a/Server/Random.cs +++ b/Server/Random.cs @@ -46,23 +46,28 @@ namespace Server { get { return _Random.GetType(); } } - public static double NextDouble() { - return _Random.NextDouble(); - } - public static int Next(int c) { return _Random.Next(c); } + public static bool NextBool() { + return _Random.NextBool(); + } + public static void NextBytes(byte[] b) { _Random.NextBytes(b); } + + public static double NextDouble() { + return _Random.NextDouble(); + } } public interface IRandomImpl { - double NextDouble(); int Next(int c); + bool NextBool(); void NextBytes(byte[] b); + double NextDouble(); } public interface IHardwareRNG { @@ -75,13 +80,6 @@ namespace Server { public SimpleRandom() { } - public double NextDouble() { - double r; - lock (m_Random) - r = m_Random.NextDouble(); - return r; - } - public int Next(int c) { int r; lock (m_Random) @@ -89,10 +87,21 @@ namespace Server { return r; } + public bool NextBool() { + return NextDouble() >= .5; + } + public void NextBytes(byte[] b) { lock (m_Random) m_Random.NextBytes(b); } + + public double NextDouble() { + double r; + lock (m_Random) + r = m_Random.NextDouble(); + return r; + } } public sealed class CSPRandom : IRandomImpl { @@ -145,18 +154,21 @@ namespace Server { } } - public double NextDouble() { - byte[] b = new byte[8]; - - _GetBytes(b); - - return (double)BitConverter.ToUInt64(b, 0) / ulong.MaxValue; - } - public int Next(int c) { return (int)(c * NextDouble()); } + public bool NextBool() { + return (NextByte() & 1) == 1; + } + + private byte NextByte() { + CheckSwap(1); + + lock(_sync) + return _Working[_Index++]; + } + public void NextBytes(byte[] b) { int c = b.Length; @@ -167,6 +179,19 @@ namespace Server { } _GetBytes(b); } + + public double NextDouble() { + byte[] b = new byte[8]; + + _GetBytes(b); + + /* double: 53 bits of significand precision + * ulong.MaxValue >> 11 = 9007199254740991 + * 2^53 = 9007199254740992 + */ + + return ((double)(BitConverter.ToUInt64(b, 0) >> 11) / 9007199254740992); + } } public sealed class RDRand32 : IRandomImpl, IHardwareRNG { @@ -227,16 +252,21 @@ namespace Server { } } - public double NextDouble() { - byte[] b = new byte[8]; - _GetBytes(b); - return (double)BitConverter.ToUInt64(b, 0) / ulong.MaxValue; - } - public int Next(int c) { return (int)(c * NextDouble()); } + public bool NextBool() { + return (NextByte() & 1) == 1; + } + + private byte NextByte() { + CheckSwap(1); + + lock(_sync) + return _Working[_Index++]; + } + public void NextBytes(byte[] b) { int c = b.Length; @@ -246,6 +276,18 @@ namespace Server { } _GetBytes(b); } + + public double NextDouble() { + byte[] b = new byte[8]; + _GetBytes(b); + + /* double: 53 bits of significand precision + * ulong.MaxValue >> 11 = 9007199254740991 + * 2^53 = 9007199254740992 + */ + + return ((double)(BitConverter.ToUInt64(b, 0) >> 11) / 9007199254740992); + } } public sealed class RDRand64 : IRandomImpl, IHardwareRNG { @@ -306,16 +348,21 @@ namespace Server { } } - public double NextDouble() { - byte[] b = new byte[8]; - _GetBytes(b); - return (double)BitConverter.ToUInt64(b, 0) / ulong.MaxValue; - } - public int Next(int c) { return (int)(c * NextDouble()); } + public bool NextBool() { + return (NextByte() & 1) == 1; + } + + private byte NextByte() { + CheckSwap(1); + + lock(_sync) + return _Working[_Index++]; + } + public void NextBytes(byte[] b) { int c = b.Length; @@ -325,6 +372,18 @@ namespace Server { } _GetBytes(b); } + + public double NextDouble() { + byte[] b = new byte[8]; + _GetBytes(b); + + /* double: 53 bits of significand precision + * ulong.MaxValue >> 11 = 9007199254740991 + * 2^53 = 9007199254740992 + */ + + return ((double)(BitConverter.ToUInt64(b, 0) >> 11) / 9007199254740992); + } } public enum RDRandError : int { diff --git a/Server/Timer.cs b/Server/Timer.cs index f17bcf21b..edfcf5493 100644 --- a/Server/Timer.cs +++ b/Server/Timer.cs @@ -19,11 +19,13 @@ ***************************************************************************/ using System; -using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Threading; +#if Framework_4_0 +using System.Threading.Tasks; +#endif using Server.Diagnostics; namespace Server @@ -136,7 +138,7 @@ namespace Server public class TimerThread { - private static Queue m_ChangeQueue = Queue.Synchronized( new Queue() ); + private static Dictionary m_Changed = new Dictionary(); private static long[] m_NextPriorities = new long[8]; private static long[] m_PriorityDelays = new long[8] @@ -215,30 +217,29 @@ namespace Server public void Free() { - //m_InstancePool.Enqueue( this ); + lock (m_InstancePool) { + if (m_InstancePool.Count <= 200) // Arbitrary + m_InstancePool.Enqueue( this ); + } } private static Queue m_InstancePool = new Queue(); public static TimerChangeEntry GetInstance( Timer t, int newIndex, bool isAdd ) { - TimerChangeEntry e; + TimerChangeEntry e = null; - if ( m_InstancePool.Count > 0 ) - { - e = m_InstancePool.Dequeue(); - - if ( e == null ) - e = new TimerChangeEntry( t, newIndex, isAdd ); - else - { - e.m_Timer = t; - e.m_NewIndex = newIndex; - e.m_IsAdd = isAdd; + lock (m_InstancePool) { + if ( m_InstancePool.Count > 0 ) { + e = m_InstancePool.Dequeue(); } } - else - { + + if (e != null) { + e.m_Timer = t; + e.m_NewIndex = newIndex; + e.m_IsAdd = isAdd; + } else { e = new TimerChangeEntry( t, newIndex, isAdd ); } @@ -252,7 +253,8 @@ namespace Server public static void Change( Timer t, int newIndex, bool isAdd ) { - m_ChangeQueue.Enqueue( TimerChangeEntry.GetInstance( t, newIndex, isAdd ) ); + lock (m_Changed) + m_Changed[t] = TimerChangeEntry.GetInstance(t, newIndex, isAdd); m_Signal.Set(); } @@ -271,34 +273,57 @@ namespace Server Change( t, -1, false ); } - private static void ProcessChangeQueue() + private static void ProcessChanged() { - while ( m_ChangeQueue.Count > 0 ) - { - TimerChangeEntry tce = (TimerChangeEntry)m_ChangeQueue.Dequeue(); - Timer timer = tce.m_Timer; - int newIndex = tce.m_NewIndex; + lock (m_Changed) { +#if Framework_4_0 + Parallel.ForEach(m_Changed.Values, tce => { + Timer timer = tce.m_Timer; + int newIndex = tce.m_NewIndex; - if ( timer.m_List != null ) - timer.m_List.Remove( timer ); + 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 (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; + + if (timer.m_List != null) + 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]; + timer.m_List.Add(timer); + } else { + timer.m_List = null; + } + + tce.Free(); } - - if ( newIndex >= 0 ) - { - timer.m_List = m_Timers[newIndex]; - timer.m_List.Add( timer ); - } - else - { - timer.m_List = null; - } - - tce.Free(); +#endif + m_Changed.Clear(); } } @@ -313,7 +338,7 @@ namespace Server while ( !Core.Closing ) { - ProcessChangeQueue(); + ProcessChanged(); loaded = false; diff --git a/Server/Utility.cs b/Server/Utility.cs index 977b2926f..9550a865d 100644 --- a/Server/Utility.cs +++ b/Server/Utility.cs @@ -789,7 +789,7 @@ namespace Server public static bool RandomBool() { - return (RandomImpl.Next(2) == 0); + return RandomImpl.NextBool(); } public static int RandomMinMax( int min, int max ) @@ -810,16 +810,11 @@ namespace Server public static int Random( int from, int count ) { - if ( count == 0 ) - { + if ( count == 0 ) { return from; - } - else if ( count > 0 ) - { + } else if ( count > 0 ) { return from + RandomImpl.Next(count); - } - else - { + } else { return from - RandomImpl.Next(-count); } }