You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Atomic.cs 12 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. using System;
  2. using System.Threading;
  3. namespace Preparation.Utility
  4. {
  5. //其对应属性不应当有set访问器,避免不安全的=赋值
  6. public abstract class Atomic
  7. {
  8. }
  9. public class AtomicInt : Atomic
  10. {
  11. protected int v;
  12. public AtomicInt(int x)
  13. {
  14. v = x;
  15. }
  16. public override string ToString() => Interlocked.CompareExchange(ref v, -1, -1).ToString();
  17. public int Get() => Interlocked.CompareExchange(ref v, -1, -1);
  18. public static implicit operator int(AtomicInt aint) => Interlocked.CompareExchange(ref aint.v, -1, -1);
  19. /// <returns>返回操作前的值</returns>
  20. public virtual int SetReturnOri(int value) => Interlocked.Exchange(ref v, value);
  21. public virtual int Add(int x) => Interlocked.Add(ref v, x);
  22. /// <summary>
  23. /// 注意:确保参数为非负数
  24. /// </summary>
  25. public virtual int AddPositive(int x) => Interlocked.Add(ref v, x);
  26. public virtual int Sub(int x) => Interlocked.Add(ref v, -x);
  27. /// <summary>
  28. /// 注意:确保参数为非负数
  29. /// </summary>
  30. public virtual int SubPositive(int x) => Interlocked.Add(ref v, -x);
  31. public virtual int Inc() => Interlocked.Increment(ref v);
  32. public virtual int Dec() => Interlocked.Decrement(ref v);
  33. /// <returns>返回操作前的值</returns>
  34. public virtual int CompareExReturnOri(int newV, int compareTo) => Interlocked.CompareExchange(ref v, newV, compareTo);
  35. }
  36. /// <summary>
  37. /// 参数要求倍率speed(默认1)以及AtomicInt类的Score,
  38. /// 在发生正向的变化时,自动给Score加上正向变化的差乘以speed取整。
  39. /// 注意:AtomicIntOnlyAddScore本身为AtomicInt,提供的Score可能构成环而死锁。
  40. /// </summary>
  41. public class AtomicIntOnlyAddScore : AtomicInt
  42. {
  43. public AtomicInt Score { get; set; }
  44. public AtomicDouble speed;
  45. public AtomicIntOnlyAddScore(int x, AtomicInt Score, double speed = 1.0) : base(x)
  46. {
  47. this.Score = Score;
  48. this.speed = new(speed);
  49. }
  50. /// <returns>返回操作前的值</returns>
  51. public override int SetReturnOri(int value)
  52. {
  53. int previousV = Interlocked.Exchange(ref v, value);
  54. if (value - previousV > 0)
  55. Score.AddPositive((int)(speed * (value - previousV)));
  56. return previousV;
  57. }
  58. public override int Add(int x)
  59. {
  60. if (x > 0) Score.AddPositive((int)(speed * x));
  61. return Interlocked.Add(ref v, x);
  62. }
  63. /// <summary>
  64. /// 注意:确保参数为非负数
  65. /// </summary>
  66. public override int AddPositive(int x)
  67. {
  68. Score.AddPositive((int)(speed * x));
  69. return Interlocked.Add(ref v, x);
  70. }
  71. public override int Sub(int x)
  72. {
  73. if (x < 0) Score.AddPositive((int)(speed * -x));
  74. return Interlocked.Add(ref v, -x);
  75. }
  76. /// <summary>
  77. /// 注意:确保参数为非负数
  78. /// </summary>
  79. public override int SubPositive(int x)
  80. {
  81. return Interlocked.Add(ref v, -x);
  82. }
  83. public override int Inc()
  84. {
  85. Score.AddPositive((int)(speed));
  86. return Interlocked.Increment(ref v);
  87. }
  88. /// <returns>返回操作前的值</returns>
  89. public override int CompareExReturnOri(int newV, int compareTo)
  90. {
  91. int previousV = Interlocked.CompareExchange(ref v, newV, compareTo);
  92. if (newV - previousV > 0)
  93. Score.AddPositive((int)(speed * (newV - previousV)));
  94. return previousV;
  95. }
  96. }
  97. /// <summary>
  98. /// 参数要求倍率speed(默认1)以及AtomicInt类的Score,
  99. /// 在发生变化时,自动给Score加上变化的差乘以speed取整。
  100. /// 注意:AtomicIntChangeAffectScore本身为AtomicInt,提供的Score可能构成环而死锁。
  101. /// </summary>
  102. public class AtomicIntChangeAffectScore : AtomicInt
  103. {
  104. public AtomicInt Score { get; set; }
  105. public AtomicDouble speed;
  106. public AtomicIntChangeAffectScore(int x, AtomicInt Score, double speed = 1.0) : base(x)
  107. {
  108. this.Score = Score;
  109. this.speed = new(speed);
  110. }
  111. /// <returns>返回操作前的值</returns>
  112. public override int SetReturnOri(int value)
  113. {
  114. int previousV = Interlocked.Exchange(ref v, value);
  115. Score.Add((int)(speed * (value - previousV)));
  116. return previousV;
  117. }
  118. public override int Add(int x)
  119. {
  120. Score.Add((int)(speed * x));
  121. return Interlocked.Add(ref v, x);
  122. }
  123. /// <summary>
  124. /// 注意:确保参数为非负数
  125. /// </summary>
  126. public override int AddPositive(int x)
  127. {
  128. Score.AddPositive((int)(speed * x));
  129. return Interlocked.Add(ref v, x);
  130. }
  131. public override int Sub(int x)
  132. {
  133. Score.Sub((int)(speed * x));
  134. return Interlocked.Add(ref v, -x);
  135. }
  136. /// <summary>
  137. /// 注意:确保参数为非负数
  138. /// </summary>
  139. public override int SubPositive(int x)
  140. {
  141. Score.SubPositive((int)(speed * x));
  142. return Interlocked.Add(ref v, -x);
  143. }
  144. public override int Inc()
  145. {
  146. Score.AddPositive((int)(speed));
  147. return Interlocked.Increment(ref v);
  148. }
  149. public override int Dec()
  150. {
  151. Score.SubPositive((int)(speed));
  152. return Interlocked.Decrement(ref v);
  153. }
  154. /// <returns>返回操作前的值</returns>
  155. public override int CompareExReturnOri(int newV, int compareTo)
  156. {
  157. int previousV = Interlocked.CompareExchange(ref v, newV, compareTo);
  158. Score.Add((int)(speed * (newV - previousV)));
  159. return previousV;
  160. }
  161. }
  162. public class AtomicLong : Atomic
  163. {
  164. protected long v;
  165. public AtomicLong(long x)
  166. {
  167. v = x;
  168. }
  169. public override string ToString() => Interlocked.CompareExchange(ref v, -1, -1).ToString();
  170. public long Get() => Interlocked.CompareExchange(ref v, -1, -1);
  171. public static implicit operator long(AtomicLong along) => Interlocked.CompareExchange(ref along.v, -1, -1);
  172. /// <returns>返回操作前的值</returns>
  173. public virtual long SetReturnOri(long value) => Interlocked.Exchange(ref v, value);
  174. public virtual long Add(long x) => Interlocked.Add(ref v, x);
  175. /// <summary>
  176. /// 注意:确保参数为非负数
  177. /// </summary>
  178. public virtual long AddPositive(long x) => Interlocked.Add(ref v, x);
  179. public virtual long Sub(long x) => Interlocked.Add(ref v, -x);
  180. /// <summary>
  181. /// 注意:确保参数为非负数
  182. /// </summary>
  183. public virtual long SubPositive(long x) => Interlocked.Add(ref v, -x);
  184. public virtual long Inc() => Interlocked.Increment(ref v);
  185. public virtual long Dec() => Interlocked.Decrement(ref v);
  186. /// <returns>返回操作前的值</returns>
  187. public virtual long CompareExReturnOri(long newV, long compareTo) => Interlocked.CompareExchange(ref v, newV, compareTo);
  188. }
  189. /// <summary>
  190. /// 参数要求倍率speed(默认1)以及AtomicLong类的Score,
  191. /// 在发生正向的变化时,自动给Score加上正向变化的差乘以speed取整。
  192. /// 注意:AtomicLongOnlyAddScore本身为AtomicLong,提供的Score可能构成环而死锁。
  193. /// </summary>
  194. public class AtomicLongOnlyAddScore : AtomicLong
  195. {
  196. public AtomicLong Score { get; set; }
  197. public AtomicDouble speed;
  198. public AtomicLongOnlyAddScore(long x, AtomicLong score, double speed = 1.0) : base(x)
  199. {
  200. this.Score = score;
  201. this.speed = new(speed);
  202. }
  203. /// <returns>返回操作前的值</returns>
  204. public override long SetReturnOri(long value)
  205. {
  206. long previousV = Interlocked.Exchange(ref v, value);
  207. if (value - previousV > 0)
  208. Score.AddPositive((long)(speed * (value - previousV)));
  209. return previousV;
  210. }
  211. public override long Add(long x)
  212. {
  213. if (x > 0) Score.AddPositive((long)(speed * x));
  214. return Interlocked.Add(ref v, x);
  215. }
  216. /// <summary>
  217. /// 注意:确保参数为非负数
  218. /// </summary>
  219. public override long AddPositive(long x)
  220. {
  221. Score.AddPositive((long)(speed * x));
  222. return Interlocked.Add(ref v, x);
  223. }
  224. public override long Sub(long x)
  225. {
  226. if (x < 0) Score.AddPositive((long)(speed * -x));
  227. return Interlocked.Add(ref v, -x);
  228. }
  229. /// <summary>
  230. /// 注意:确保参数为非负数
  231. /// </summary>
  232. public override long SubPositive(long x)
  233. {
  234. return Interlocked.Add(ref v, -x);
  235. }
  236. public override long Inc()
  237. {
  238. Score.AddPositive((long)(speed));
  239. return Interlocked.Increment(ref v);
  240. }
  241. /// <returns>返回操作前的值</returns>
  242. public override long CompareExReturnOri(long newV, long compareTo)
  243. {
  244. long previousV = Interlocked.CompareExchange(ref v, newV, compareTo);
  245. if (newV - previousV > 0)
  246. Score.AddPositive((long)(speed * (newV - previousV)));
  247. return previousV;
  248. }
  249. }
  250. public class AtomicDouble : Atomic
  251. {
  252. private double v;
  253. public AtomicDouble(double x)
  254. {
  255. v = x;
  256. }
  257. public override string ToString() => Interlocked.CompareExchange(ref v, -2.0, -2.0).ToString();
  258. public double Get() => Interlocked.CompareExchange(ref v, -2.0, -2.0);
  259. public static implicit operator double(AtomicDouble adouble) => Interlocked.CompareExchange(ref adouble.v, -2.0, -2.0);
  260. /// <returns>返回操作前的值</returns>
  261. public double SetReturnOri(double value) => Interlocked.Exchange(ref v, value);
  262. /// <returns>返回操作前的值</returns>
  263. public double CompareExReturnOri(double newV, double compareTo) => Interlocked.CompareExchange(ref v, newV, compareTo);
  264. }
  265. public class AtomicBool : Atomic
  266. {
  267. private int v;//v&1==0为false,v&1==1为true
  268. public AtomicBool(bool x)
  269. {
  270. v = x ? 1 : 0;
  271. }
  272. public override string ToString() => ((Interlocked.CompareExchange(ref v, -2, -2) & 1) == 0) ? "false" : "true";
  273. public bool Get() => ((Interlocked.CompareExchange(ref v, -2, -2) & 1) == 1);
  274. public static implicit operator bool(AtomicBool abool) => abool.Get();
  275. /// <returns>返回操作前的值</returns>
  276. public bool SetReturnOri(bool value) => ((Interlocked.Exchange(ref v, value ? 1 : 0) & 1) == 1);
  277. /// <returns>赋值前的值是否与将赋予的值不相同</returns>
  278. public bool TrySet(bool value)
  279. {
  280. return ((Interlocked.Exchange(ref v, value ? 1 : 0) & 1) != (value ? 1 : 0));
  281. }
  282. public bool And(bool x) => (Interlocked.And(ref v, x ? 1 : 0) & 1) == 1;
  283. public bool Or(bool x) => (Interlocked.Or(ref v, x ? 1 : 0) & 1) == 1;
  284. /// <returns>返回操作后的值</returns>
  285. public bool Reverse() => (Interlocked.Increment(ref v) & 1) == 1;
  286. public bool Xor(bool x) => (Interlocked.Add(ref v, x ? 1 : 0) & 1) == 1;
  287. }
  288. }