-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathArenaID.cs
92 lines (77 loc) · 2.62 KB
/
ArenaID.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;
namespace Arenas {
[StructLayout(LayoutKind.Sequential)]
public readonly struct ArenaID : IEquatable<ArenaID> {
public readonly int Value;
public ArenaID(int value) {
Value = value;
}
#region Equality
public override bool Equals(object obj) {
return obj is ArenaID iD &&
Value == iD.Value;
}
public bool Equals(ArenaID other) {
return other.Value == Value;
}
public override int GetHashCode() {
return 710438321 + Value.GetHashCode();
}
public static bool operator ==(ArenaID left, ArenaID right) {
return left.Equals(right);
}
public static bool operator !=(ArenaID left, ArenaID right) {
return !(left == right);
}
#endregion
public override string ToString() {
return Value.ToString("x", CultureInfo.InvariantCulture);
}
public static ArenaID NewID() {
return new ArenaID((int)LFSR.Shift());
}
private static readonly ArenaID empty = new ArenaID(0);
public static ArenaID Empty { get { return empty; } }
/// <summary>
/// A maximum length 32-bit linear feedback shift register which produces ID numbers
/// </summary>
private static class LFSR {
/// <summary>
/// 32-bit term that produces a maximum-length LFSR
/// </summary>
private const uint feedbackTerm = 0x80000EA6;
private static uint value;
private static object lfsrLock = new object();
static LFSR() {
value = 0x0BADCAFE;
}
public static uint Shift() {
uint ret;
lock (lfsrLock) {
if (value == feedbackTerm) {
ret = value = 0;
}
else {
if (value == 0) {
ret = value = feedbackTerm;
}
if ((value & 1) == 1) {
ret = value = (value >> 1) ^ feedbackTerm;
}
else {
ret = value = value >> 1;
}
}
}
if (ret == 0) {
return Shift();
}
return ret;
}
}
}
}