Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@Flash3001
Created February 17, 2017 13:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Flash3001/da5bd3ca800f674082dd8030ef70cf4e to your computer and use it in GitHub Desktop.
Save Flash3001/da5bd3ca800f674082dd8030ef70cf4e to your computer and use it in GitHub Desktop.
using System;
using System.Linq;
using System.Threading;
namespace TearDateTime
{
class Program
{
public const int ITERATIONS = 20000;
public const int MAX_THREADS = 30;
public const int MAX_RERUNS = 10;
public const int MAX_FULL_RERUN = 4;
static unsafe void Main(string[] args)
{
Console.WriteLine("-------------- Trying to Tear --------------");
Console.WriteLine($"Running: {sizeof(IntPtr) * 8}bits");
Console.WriteLine($"Max Threads: {MAX_THREADS}");
Console.WriteLine($"Max Reruns: {MAX_RERUNS}");
Console.WriteLine($"Max Iterations per Thread: {ITERATIONS}");
Console.WriteLine("--------------------------------------------");
for (int i = 0; i < MAX_FULL_RERUN; i++)
{
Console.WriteLine("----- Tears ------ | -------- Size ---------");
Tearer<long>.Run((n) => n, sizeof(long));
Tearer<DateTime>.Run((n) => new DateTime(n), sizeof(DateTime));
Tearer<Struct128>.Run((n) => new Struct128(n), sizeof(Struct128));
Tearer<Struct192>.Run((n) => new Struct192(n), sizeof(Struct192));
Tearer<Struct256>.Run((n) => new Struct256(n), sizeof(Struct256));
}
Console.WriteLine("------------------- End --------------------");
Console.ReadLine();
}
}
#region Tearer
static class Tearer<T>
where T : struct
{
static int _threads = 1; // 2x
static int _rerun = 0;
static T _value;
static T[] _values;
static int _tearsFound;
static object _tearsLock = new object();
static CountdownEvent _threadsEndend;
static Random _random = new Random();
static void Setup(Func<long, T> getNew)
{
var range = Enumerable.Range(0, _threads);
_values = range.Select(c => getNew((long)_random.Next() << 30 | (long)_random.Next())).ToArray();
_threadsEndend = new CountdownEvent(_threads * 2);
_value = _values[0]; // Remove to get false positives! You will get 'normal' races, not tears.
}
static void Assign(int i)
{
for (int c = 0; c < Program.ITERATIONS; c++)
{
_value = _values[i];
}
_threadsEndend.Signal();
}
static void FindTear()
{
for (int c = 0; c < Program.ITERATIONS; c++)
{
var localValue = _value;
if (!_values.Contains(localValue))
{
lock (_tearsLock)
{
_tearsFound++;
Console.CursorTop--;
Console.WriteLine($"Total tears {_tearsFound} in {typeof(T).Name}");
}
}
}
_threadsEndend.Signal();
}
public static unsafe void Run(Func<long, T> getNew, int size)
{
_rerun = 0;
_tearsFound = 0;
Console.WriteLine($"Running {typeof(T).Name}: {size * 8}bits");
while (_rerun < Program.MAX_RERUNS)
{
Setup(getNew);
for (int i = 0; i < _threads; i++)
{
var l = i;
new Thread(() => Assign(l)).Start();
new Thread(FindTear).Start();
}
_threadsEndend.Wait();
_threadsEndend.Dispose();
_threads++;
if (_threads == Program.MAX_THREADS)
{
_rerun++;
_threads = 1;
}
}
Console.CursorTop--;
Console.WriteLine($"\t{ _tearsFound.ToString().PadLeft(3, ' ')}\t\t{typeof(T).Name} ({size * 8}bits)");
}
}
#endregion
#region Structs
struct Struct128
{
long a, b;
public Struct128(long num)
{
a = b = num;
}
public override bool Equals(object obj)
{
var o = (Struct128)obj;
return o.a == this.a && o.b == this.b;
}
}
struct Struct192
{
long a, b, c;
public Struct192(long num)
{
a = b = c = num;
}
public override bool Equals(object obj)
{
var o = (Struct192)obj;
return o.a == this.a && o.b == this.b && o.c == this.c;
}
}
struct Struct256
{
long a, b, c, d;
public Struct256(long num)
{
a = b = c = d = num;
}
public override bool Equals(object obj)
{
var o = (Struct256)obj;
return o.a == this.a && o.b == this.b && o.c == this.c && o.d == this.d;
}
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment