proper nextdouble

direct randombool
thread safe parallelized timer changes
This commit is contained in:
Mark Sturgill 2013-10-13 19:27:25 -07:00
parent 41019b691b
commit b3831721d9
3 changed files with 163 additions and 84 deletions

View file

@ -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 {

View file

@ -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<Timer,TimerChangeEntry> m_Changed = new Dictionary<Timer,TimerChangeEntry>();
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<TimerChangeEntry> m_InstancePool = new Queue<TimerChangeEntry>();
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;

View file

@ -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);
}
}