From 70604b56f80100e43e22bbd61f29120725774fea Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Sat, 4 Nov 2023 23:34:36 +0800 Subject: [PATCH 1/3] feat: :sparkles: Add the progress TimeBasedProgressAtVariableSpeed --- .../GameClass/GameObj/Character/Character.cs | 2 +- logic/GameClass/GameObj/Map/Doorway.cs | 58 +--- logic/Gaming/ActionManager.cs | 7 +- logic/Preparation/Interface/IDoorway.cs | 5 +- .../Utility/SafeValue/InTheRange.cs | 109 ++++--- .../Utility/SafeValue/TimeBased.cs | 270 +++++++++++++----- logic/Server/CopyInfo.cs | 3 +- 7 files changed, 254 insertions(+), 200 deletions(-) diff --git a/logic/GameClass/GameObj/Character/Character.cs b/logic/GameClass/GameObj/Character/Character.cs index 2b6a9e18..6c07855b 100644 --- a/logic/GameClass/GameObj/Character/Character.cs +++ b/logic/GameClass/GameObj/Character/Character.cs @@ -327,7 +327,7 @@ public long SetPlayerState(RunningStateType runningState, PlayerStateType value case PlayerStateType.OpeningTheDoorway: if (value == PlayerStateType.Rescued) return -1; Doorway doorway = (Doorway)lastObj!; - doorway.StopOpenning(); + doorway.ProgressOfDoorway.TryStop(); return ChangePlayerState(runningState, value, gameObj); case PlayerStateType.OpeningTheDoor: if (value == PlayerStateType.Rescued) return -1; diff --git a/logic/GameClass/GameObj/Map/Doorway.cs b/logic/GameClass/GameObj/Map/Doorway.cs index 82ac6bea..a0835627 100644 --- a/logic/GameClass/GameObj/Map/Doorway.cs +++ b/logic/GameClass/GameObj/Map/Doorway.cs @@ -17,70 +17,18 @@ public Doorway(XY initPos) : public override ShapeType Shape => ShapeType.Square; public override bool IgnoreCollideExecutor(IGameObj targetObj) { - if (!IsOpen()) return false; + if (!ProgressOfDoorway.IsFinished()) return false; if (targetObj.Type != GameObjType.Character) return true; // 非玩家不碰撞 return false; } public AtomicBool PowerSupply { get; } = new(false); - - private long openStartTime = 0; - public long OpenStartTime - { - get - { - lock (gameObjLock) - return openStartTime; - } - } + public TimeBasedProgressAtVariableSpeed ProgressOfDoorway { get; } = new(GameData.degreeOfOpenedDoorway, 1); public bool TryToOpen() { if (!PowerSupply) return false; - lock (gameObjLock) - { - if (openStartTime > 0) return false; - openStartTime = Environment.TickCount64; - return true; - } + return ProgressOfDoorway.Start(); } - - public bool StopOpenning() - { - lock (gameObjLock) - { - if (Environment.TickCount64 - openStartTime + openDegree >= GameData.degreeOfOpenedDoorway) - { - openDegree = GameData.degreeOfOpenedDoorway; - return true; - } - else - { - openDegree = (int)(Environment.TickCount64 - openStartTime) + openDegree; - openStartTime = 0; - return false; - } - } - } - - public void FinishOpenning() - { - lock (gameObjLock) - { - openDegree = GameData.degreeOfOpenedDoorway; - } - } - - private int openDegree = 0; - public int OpenDegree - { - get - { - lock (gameObjLock) - return openDegree; - } - } - - public bool IsOpen() => (OpenDegree == GameData.degreeOfOpenedDoorway); } } diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs index bfb78d27..645f7ea9 100644 --- a/logic/Gaming/ActionManager.cs +++ b/logic/Gaming/ActionManager.cs @@ -2,6 +2,7 @@ using System.Threading; using GameClass.GameObj; using GameEngine; +using Preparation.Interface; using Preparation.Utility; using Timothy.FrameRateTask; @@ -148,11 +149,11 @@ public bool OpenDoorway(Student player) player.ThreadNum.Release(); return; } - Thread.Sleep(GameData.degreeOfOpenedDoorway - doorwayToOpen.OpenDegree); + Thread.Sleep(GameData.degreeOfOpenedDoorway - (int)doorwayToOpen.ProgressOfDoorway.GetProgressNow()); if (player.ResetPlayerState(stateNum)) { - doorwayToOpen.FinishOpenning(); + doorwayToOpen.ProgressOfDoorway.Finish(); player.ThreadNum.Release(); } } @@ -168,7 +169,7 @@ public bool Escape(Student player) return false; Doorway? doorwayForEscape = (Doorway?)gameMap.OneForInteract(player.Position, GameObjType.Doorway); - if (doorwayForEscape != null && doorwayForEscape.IsOpen()) + if (doorwayForEscape != null && doorwayForEscape.ProgressOfDoorway.IsProgressing()) { if (!player.TryToRemoveFromGame(PlayerStateType.Escaped)) return false; player.AddScore(GameData.StudentScoreEscape); diff --git a/logic/Preparation/Interface/IDoorway.cs b/logic/Preparation/Interface/IDoorway.cs index b48be758..942f1032 100644 --- a/logic/Preparation/Interface/IDoorway.cs +++ b/logic/Preparation/Interface/IDoorway.cs @@ -4,9 +4,6 @@ namespace Preparation.Interface { public interface IDoorway : IGameObj { - public long OpenStartTime { get; } - public int OpenDegree { get; } - public bool StopOpenning(); - public bool TryToOpen(); + public TimeBasedProgressAtVariableSpeed ProgressOfDoorway { get; } } } \ No newline at end of file diff --git a/logic/Preparation/Utility/SafeValue/InTheRange.cs b/logic/Preparation/Utility/SafeValue/InTheRange.cs index 3c8a9cae..f08f2e04 100644 --- a/logic/Preparation/Utility/SafeValue/InTheRange.cs +++ b/logic/Preparation/Utility/SafeValue/InTheRange.cs @@ -24,8 +24,8 @@ public InTheVariableRange() /// public class IntInTheVariableRange : InTheVariableRange { - private int v; - private int maxV; + protected int v; + protected int maxV; #region 构造与读取 public IntInTheVariableRange(int value, int maxValue) : base() { @@ -157,6 +157,13 @@ public bool TrySetMaxV(int maxValue) return true; } } + public void SetVToMaxV() + { + lock (vLock) + { + v = maxV; + } + } public bool Set0IfNotMaxor0() { lock (vLock) @@ -397,6 +404,32 @@ public int AddV(StartTime startTime, double speed = 1.0) return v - previousV; } } + + /// + /// 试图加到满,如果加上时间差*速度可以达到MaxV,则加上并使startTime变为long.MaxValue + /// 如果无法加到maxValue则清零 + /// + /// 返回是否清零 + public bool Set0IfNotAddToMaxV(StartTime startTime, double speed = 1.0) + { + lock (vLock) + { + if (v == maxV) return false; + int addV = (int)(startTime.StopIfPassing(maxV - v) * speed); + if (addV < 0) + { + v = 0; + return true; + } + if (maxV - v < addV) + { + v = maxV; + return false; + } + v = 0; + return false; + } + } #endregion } @@ -405,8 +438,8 @@ public int AddV(StartTime startTime, double speed = 1.0) /// public class LongInTheVariableRange : InTheVariableRange { - private long v; - private long maxV; + protected long v; + protected long maxV; #region 构造与读取 public LongInTheVariableRange(long value, long maxValue) : base() { @@ -455,23 +488,6 @@ public bool IsMaxV() } #endregion - #region 内嵌读取(在锁的情况下读取内容同时读取其他更基本的外部数据) - public (long, long) GetValue(StartTime startTime) - { - lock (vLock) - { - return (v, startTime.Get()); - } - } - public (long, long, long) GetValueAndMaxV(StartTime startTime) - { - lock (vLock) - { - return (v, maxV, startTime.Get()); - } - } - #endregion - #region 普通设置MaxV与Value的值的方法 /// /// 若maxValue<=0则maxValue设为0并返回False @@ -645,6 +661,13 @@ public bool TrySetMaxV(long maxValue) return true; } } + public void SetVToMaxV() + { + lock (vLock) + { + v = maxV; + } + } public bool Set0IfNotMax() { @@ -709,22 +732,6 @@ public long TryAddToMaxV(long addV) } } - /// - /// 增加量为时间差*速度,并将startTime变为long.MaxValue - /// - /// 返回实际改变量 - public long AddV(StartTime startTime, double speed = 1.0) - { - lock (vLock) - { - long previousV = v; - long addV = (Environment.TickCount64 - startTime.Stop()); - if (addV < 0) v += (long)(addV * speed); - else return 0; - if (v > maxV) v = maxV; - return v - previousV; - } - } #endregion } @@ -733,8 +740,8 @@ public long AddV(StartTime startTime, double speed = 1.0) /// public class DoubleInTheVariableRange : InTheVariableRange { - private double v; - private double maxV; + protected double v; + protected double maxV; #region 构造与读取 public DoubleInTheVariableRange(double value, double maxValue) : base() { @@ -783,23 +790,6 @@ public bool IsMaxV() } #endregion - #region 内嵌读取(在锁的情况下读取内容同时读取其他更基本的外部数据) - public (double, long) GetValue(StartTime startTime) - { - lock (vLock) - { - return (v, startTime.Get()); - } - } - public (double, double, long) GetValueAndMaxValue(StartTime startTime) - { - lock (vLock) - { - return (v, maxV, startTime.Get()); - } - } - #endregion - #region 普通设置MaxV与Value的值的方法 /// /// 若maxValue<=0则maxValue设为0并返回False @@ -949,6 +939,13 @@ public bool TrySetMaxV(double maxValue) return true; } } + public void SetVToMaxV() + { + lock (vLock) + { + v = maxV; + } + } public bool Set0IfNotMax() { diff --git a/logic/Preparation/Utility/SafeValue/TimeBased.cs b/logic/Preparation/Utility/SafeValue/TimeBased.cs index 6ed57435..402595a1 100644 --- a/logic/Preparation/Utility/SafeValue/TimeBased.cs +++ b/logic/Preparation/Utility/SafeValue/TimeBased.cs @@ -35,6 +35,197 @@ public long StopIfPassing(long passedTime) } } + public class LongInTheVariableRangeWithStartTime : LongInTheVariableRange + { + public StartTime startTime = new(); + public LongInTheVariableRangeWithStartTime(long value, long maxValue) : base(value, maxValue) { } + /// + /// 默认使Value=maxValue + /// + public LongInTheVariableRangeWithStartTime(long maxValue) : base(maxValue) { } + public LongInTheVariableRangeWithStartTime() : base() { } + + #region 读取 + public (long, long) GetValueWithStartTime() + { + lock (vLock) + { + return (v, startTime.Get()); + } + } + public (long, long, long) GetValueAndMaxVWithStartTime() + { + lock (vLock) + { + return (v, maxV, startTime.Get()); + } + } + #endregion + + /// + /// 试图加到满,如果加上时间差*速度可以达到MaxV,则加上并使startTime变为long.MaxValue + /// 如果无法加到maxValue则不加 + /// + /// 返回试图加到的值与最大值 + public (long, long, long) AddStartTimeToMaxV(double speed = 1.0) + { + lock (vLock) + { + long addV = (long)(startTime.StopIfPassing(maxV - v) * speed); + if (addV < 0) return (v, maxV, startTime.Get()); + if (maxV - v < addV) return (v = maxV, maxV, startTime.Get()); + return (v + addV, maxV, startTime.Get()); + } + } + + /// + /// 增加量为时间差*速度,并将startTime变为long.MaxValue + /// + /// 返回实际改变量 + public long AddStartTime(double speed = 1.0) + { + lock (vLock) + { + long previousV = v; + long addV = (Environment.TickCount64 - startTime.Stop()); + if (addV < 0) v += (long)(addV * speed); + else return 0; + if (v > maxV) v = maxV; + return v - previousV; + } + } + + /// + /// 试图加到满,如果加上时间差*速度可以达到MaxV,则加上 + /// 如果无法加到maxValue则清零 + /// 无论如何startTime变为long.MaxValue + /// + /// 返回是否清零 + public bool Set0IfNotAddStartTimeToMaxV(double speed = 1.0) + { + lock (vLock) + { + if (v == maxV) return false; + long addV = (long)(startTime.Stop() * speed); + if (addV < 0) + { + v = 0; + return true; + } + if (maxV - v < addV) + { + v = maxV; + return false; + } + v = 0; + return false; + } + } + + public void SetAndStop(long value = 0) + { + lock (vLock) + { + this.v = value; + startTime.Stop(); + } + } + } + + public class TimeBasedProgressAtVariableSpeed + { + private LongInTheVariableRangeWithStartTime progress; + public AtomicDouble speed; + + #region 构造 + public TimeBasedProgressAtVariableSpeed(long needProgress, double speed = 1.0) + { + progress = new LongInTheVariableRangeWithStartTime(0, needProgress); + if (needProgress <= 0) Debugger.Output("Bug:TimeBasedProgressAtVariableSpeed.needProgress (" + needProgress.ToString() + ") is less than 0."); + this.speed = new(speed); + } + public TimeBasedProgressAtVariableSpeed() + { + progress = new LongInTheVariableRangeWithStartTime(0, 0); + this.speed = new(1.0); + } + #endregion + + #region 读取 + public override string ToString() + { + long progressStored, lastStartTime; + (progressStored, lastStartTime) = progress.GetValueWithStartTime(); + return "ProgressStored: " + progressStored.ToString() + + " ; LastStartTime: " + lastStartTime.ToString() + "ms" + + " ; Speed: " + speed.ToString(); + } + public long GetProgressNow() => progress.AddStartTimeToMaxV((double)speed).Item1; + public (long, long, long) GetProgressNowAndNeedTimeAndLastStartTime() => progress.AddStartTimeToMaxV((double)speed); + public long GetProgressStored() => progress.GetValue(); + public (long, long) GetProgressStoredAndNeedTime() => progress.GetValueAndMaxV(); + public (long, long, long) GetProgressStoredAndNeedTimeAndLastStartTime() => progress.GetValueAndMaxVWithStartTime(); + + public bool IsFinished() + { + long progressNow, needTime; + (progressNow, needTime, _) = progress.AddStartTimeToMaxV((double)speed); + return progressNow == needTime; + } + public bool IsProgressing() + { + long progressNow, needTime, startT; + (progressNow, needTime, startT) = progress.AddStartTimeToMaxV((double)speed); + return (startT != long.MaxValue && progressNow != needTime); + } + #endregion + + public bool Start(long needTime) + { + if (needTime <= 2) + { + Debugger.Output("Warning:Start TimeBasedProgressAtVariableSpeed with the needProgress (" + needTime.ToString() + ") which is less than 0."); + return false; + } + if (progress.startTime.Start() != long.MaxValue) return false; + progress.SetMaxV(needTime); + return true; + } + public bool Start() + { + return progress.startTime.Start() == long.MaxValue; + } + /// + /// 使进度条强制终止清零 + /// + public void Set0() + { + progress.SetAndStop(); + } + /// + /// 如果进度条加上时间差不能为满,使进度条强制终止清零 + /// + public void TryStop() + { + progress.Set0IfNotAddStartTimeToMaxV(speed); + } + /// + /// 使进度条暂停 + /// + public bool Pause() + { + return progress.AddStartTime((double)speed) != 0; + } + /// + /// 使进度条进度为满 + /// + public void Finish() + { + progress.SetVToMaxV(); + progress.startTime.Stop(); + } + } + /// /// 根据时间推算Start后完成多少进度的进度条(long)。 /// 只允许Start(清零状态的进度条才可以Start)时修改needTime(请确保大于0); @@ -158,85 +349,6 @@ public bool InterruptToSet0() //增加其他新的写操作可能导致不安全 } - public class TimeBasedProgressAtVariableSpeed - { - public LongInTheVariableRange progress; - public StartTime startTime = new(); - public AtomicDouble speed; - - #region 构造 - public TimeBasedProgressAtVariableSpeed(long needProgress, double speed) - { - if (needProgress <= 0) Debugger.Output("Bug:TimeBasedProgressAtVariableSpeed.needProgress (" + needProgress.ToString() + ") is less than 0."); - this.progress = new(0, needProgress); - this.speed = new(speed); - } - public TimeBasedProgressAtVariableSpeed() - { - this.progress = new(0, 0); - this.speed = new(1.0); - } - #endregion - - #region 读取 - public override string ToString() - { - return "ProgressStored: " + progress.ToString() - + " ; LastStartTime: " + startTime.ToString() + "ms" - + " ; Speed: " + speed.ToString(); - } - public long GetProgressNow() => progress.TryAddToMaxV(startTime, (double)speed).Item1; - public (long, long, long) GetProgressNowAndNeedTimeAndLastStartTime() => progress.TryAddToMaxV(startTime, (double)speed); - public long GetProgressStored() => progress.GetValue(); - public (long, long) GetProgressStoredAndNeedTime() => progress.GetValueAndMaxV(); - public (long, long, long) GetProgressStoredAndNeedTimeAndLastStartTime() => progress.GetValueAndMaxV(startTime); - - public bool IsFinished() - { - long progressNow, needTime; - (progressNow, needTime, _) = progress.TryAddToMaxV(startTime); - return progressNow == needTime; - } - public bool IsProgressing() - { - long progressNow, needTime, startT; - (progressNow, needTime, startT) = progress.TryAddToMaxV(startTime); - return (startT != long.MaxValue && progressNow != needTime); - } - #endregion - - public bool Start(long needTime) - { - if (needTime <= 2) - { - Debugger.Output("Warning:Start TimeBasedProgressAtVariableSpeed with the needProgress (" + needTime.ToString() + ") which is less than 0."); - return false; - } - if (startTime.Start() != long.MaxValue) return false; - progress.SetMaxV(needTime); - return true; - } - public bool Start() - { - return startTime.Start() == long.MaxValue; - } - /// - /// 使进度条强制终止清零 - /// - public void Set0() - { - startTime.Stop(); - progress.SetPositiveV(0); - } - /// - /// 使进度条暂停 - /// - public bool Pause() - { - return progress.AddV(startTime, (double)speed) != 0; - } - } - /// /// 冷却时间为可变的CDms的bool,不支持查看当前进度,初始为True /// diff --git a/logic/Server/CopyInfo.cs b/logic/Server/CopyInfo.cs index 57863dc7..a18d58a2 100644 --- a/logic/Server/CopyInfo.cs +++ b/logic/Server/CopyInfo.cs @@ -232,8 +232,7 @@ private static MessageOfObj Gate(Doorway doorway, long time) Y = doorway.Position.y } }; - int progress = ((doorway.OpenStartTime > 0) ? ((int)(time - doorway.OpenStartTime)) : 0) + doorway.OpenDegree; - msg.GateMessage.Progress = (progress > GameData.degreeOfOpenedDoorway) ? GameData.degreeOfOpenedDoorway : progress; + msg.GateMessage.Progress = (int)doorway.ProgressOfDoorway.GetProgressNow(); return msg; } private static MessageOfObj HiddenGate(EmergencyExit Exit) From 801d1aea30db9d3df03f20f8d95249d9a4f37fdc Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Sun, 5 Nov 2023 00:41:51 +0800 Subject: [PATCH 2/3] feat(SafeValue): :sparkles: Add the AtomicIntOnlyAddScore --- logic/GameClass/GameObj/Map/Map.cs | 2 +- logic/Preparation/Utility/SafeValue/Atomic.cs | 173 ++++++++++++++++-- 2 files changed, 158 insertions(+), 17 deletions(-) diff --git a/logic/GameClass/GameObj/Map/Map.cs b/logic/GameClass/GameObj/Map/Map.cs index 75dea6b8..dd7e6bbb 100644 --- a/logic/GameClass/GameObj/Map/Map.cs +++ b/logic/GameClass/GameObj/Map/Map.cs @@ -24,7 +24,7 @@ public void AddNumOfRepairedGenerators() GameObjLockDict[GameObjType.EmergencyExit].EnterReadLock(); try { - Random r = new Random(Environment.TickCount); + Random r = new(Environment.TickCount); EmergencyExit emergencyExit = (EmergencyExit)(GameObjDict[GameObjType.EmergencyExit][r.Next(0, GameObjDict[GameObjType.EmergencyExit].Count)]); emergencyExit.CanOpen.SetReturnOri(true); Preparation.Utility.Debugger.Output(emergencyExit, emergencyExit.Position.ToString()); diff --git a/logic/Preparation/Utility/SafeValue/Atomic.cs b/logic/Preparation/Utility/SafeValue/Atomic.cs index da6ebaa7..0eee2f5f 100644 --- a/logic/Preparation/Utility/SafeValue/Atomic.cs +++ b/logic/Preparation/Utility/SafeValue/Atomic.cs @@ -1,4 +1,5 @@ -using System; +using Google.Protobuf.WellKnownTypes; +using System; using System.Threading; namespace Preparation.Utility @@ -10,7 +11,7 @@ public abstract class Atomic public class AtomicInt : Atomic { - private int v; + protected int v; public AtomicInt(int x) { v = x; @@ -19,33 +20,173 @@ public AtomicInt(int x) public int Get() => Interlocked.CompareExchange(ref v, -1, -1); public static implicit operator int(AtomicInt aint) => Interlocked.CompareExchange(ref aint.v, -1, -1); /// 返回操作前的值 - public int SetReturnOri(int value) => Interlocked.Exchange(ref v, value); - public int Add(int x) => Interlocked.Add(ref v, x); - public int Sub(int x) => Interlocked.Add(ref v, -x); - public int Inc() => Interlocked.Increment(ref v); + public virtual int SetReturnOri(int value) => Interlocked.Exchange(ref v, value); + public virtual int Add(int x) => Interlocked.Add(ref v, x); + /// + /// 注意:确保参数为非负数 + /// + public virtual int AddPositive(int x) => Interlocked.Add(ref v, x); + public virtual int Sub(int x) => Interlocked.Add(ref v, -x); + /// + /// 注意:确保参数为非负数 + /// + public virtual int SubPositive(int x) => Interlocked.Add(ref v, -x); + public virtual int Inc() => Interlocked.Increment(ref v); public int Dec() => Interlocked.Decrement(ref v); /// 返回操作前的值 - public int CompareExReturnOri(int newV, int compareTo) => Interlocked.CompareExchange(ref v, newV, compareTo); + public virtual int CompareExReturnOri(int newV, int compareTo) => Interlocked.CompareExchange(ref v, newV, compareTo); + } + + /// + /// 参数要求倍率speed(默认1)以及AtomicInt类的Score, + /// 在发生正向的变化时,自动给Score加上正向变化的差乘以speed。 + /// 注意:AtomicIntOnlyAddScore本身为AtomicInt,提供的Score可能构成环而死锁。 + /// + public class AtomicIntOnlyAddScore : AtomicInt + { + public AtomicInt Score { get; set; }; + public AtomicDouble speed; + public AtomicIntOnlyAddScore(int x, AtomicInt Score, double speed = 1.0) : base(x) + { + this.Score = Score; + this.speed = new(speed); + } + /// 返回操作前的值 + public override int SetReturnOri(int value) + { + int previousV = Interlocked.Exchange(ref v, value); + if (value - previousV > 0) + Score.AddPositive((int)(speed * (value - previousV))); + return previousV; + } + public override int Add(int x) + { + if (x > 0) Score.AddPositive((int)(speed * x)); + return Interlocked.Add(ref v, x); + } + /// + /// 注意:确保参数为非负数 + /// + public override int AddPositive(int x) + { + Score.AddPositive((int)(speed * x)); + return Interlocked.Add(ref v, x); + } + public override int Sub(int x) + { + if (x < 0) Score.AddPositive((int)(speed * -x)); + return Interlocked.Add(ref v, -x); + } + /// + /// 注意:确保参数为非负数 + /// + public override int SubPositive(int x) + { + return Interlocked.Add(ref v, -x); + } + public override int Inc() + { + Score.AddPositive((int)(speed)); + return Interlocked.Increment(ref v); + } + /// 返回操作前的值 + public override int CompareExReturnOri(int newV, int compareTo) + { + int previousV = Interlocked.CompareExchange(ref v, newV, compareTo); + if (newV - previousV > 0) + Score.AddPositive((int)(speed * (newV - previousV))); + return previousV; + } } public class AtomicLong : Atomic { - private long v; + protected long v; public AtomicLong(long x) { v = x; } - public override string ToString() => Interlocked.Read(ref v).ToString(); - public long Get() => Interlocked.Read(ref v); - public static implicit operator long(AtomicLong along) => Interlocked.Read(ref along.v); + public override string ToString() => Interlocked.CompareExchange(ref v, -1, -1).ToString(); + public long Get() => Interlocked.CompareExchange(ref v, -1, -1); + public static implicit operator long(AtomicLong along) => Interlocked.CompareExchange(ref along.v, -1, -1); /// 返回操作前的值 - public long SetReturnOri(long value) => Interlocked.Exchange(ref v, value); - public long Add(long x) => Interlocked.Add(ref v, x); - public long Sub(long x) => Interlocked.Add(ref v, -x); - public long Inc() => Interlocked.Increment(ref v); + public virtual long SetReturnOri(long value) => Interlocked.Exchange(ref v, value); + public virtual long Add(long x) => Interlocked.Add(ref v, x); + /// + /// 注意:确保参数为非负数 + /// + public virtual long AddPositive(long x) => Interlocked.Add(ref v, x); + public virtual long Sub(long x) => Interlocked.Add(ref v, -x); + /// + /// 注意:确保参数为非负数 + /// + public virtual long SubPositive(long x) => Interlocked.Add(ref v, -x); + public virtual long Inc() => Interlocked.Increment(ref v); public long Dec() => Interlocked.Decrement(ref v); /// 返回操作前的值 - public long CompareExReturnOri(long newV, long compareTo) => Interlocked.CompareExchange(ref v, newV, compareTo); + public virtual long CompareExReturnOri(long newV, long compareTo) => Interlocked.CompareExchange(ref v, newV, compareTo); + } + + /// + /// 参数要求倍率speed(默认1)以及AtomicLong类的Score, + /// 在发生正向的变化时,自动给Score加上正向变化的差乘以speed。 + /// 注意:AtomicLongOnlyAddScore本身为AtomicLong,提供的Score可能构成环而死锁。 + /// + public class AtomicLongOnlyAddScore : AtomicLong + { + public AtomicInt Score { get; set; }; + public AtomicDouble speed; + public AtomicLongOnlyAddScore(long x, AtomicLong Score, double speed = 1.0) : base(x) + { + this.Score = Score; + this.speed = new(speed); + } + /// 返回操作前的值 + public override long SetReturnOri(long value) + { + long previousV = Interlocked.Exchange(ref v, value); + if (value - previousV > 0) + Score.AddPositive((long)(speed * (value - previousV))); + return previousV; + } + public override long Add(long x) + { + if (x > 0) Score.AddPositive((long)(speed * x)); + return Interlocked.Add(ref v, x); + } + /// + /// 注意:确保参数为非负数 + /// + public override long AddPositive(long x) + { + Score.AddPositive((long)(speed * x)); + return Interlocked.Add(ref v, x); + } + public override long Sub(long x) + { + if (x < 0) Score.AddPositive((long)(speed * -x)); + return Interlocked.Add(ref v, -x); + } + /// + /// 注意:确保参数为非负数 + /// + public override long SubPositive(long x) + { + return Interlocked.Add(ref v, -x); + } + public override long Inc() + { + Score.AddPositive((long)(speed)); + return Interlocked.Increment(ref v); + } + /// 返回操作前的值 + public override long CompareExReturnOri(long newV, long compareTo) + { + long previousV = Interlocked.CompareExchange(ref v, newV, compareTo); + if (newV - previousV > 0) + Score.AddPositive((long)(speed * (newV - previousV))); + return previousV; + } } public class AtomicDouble : Atomic From f8d0f838c1983ce4b4bd888f95abd4471ba776a5 Mon Sep 17 00:00:00 2001 From: shangfengh <3495281661@qq.com> Date: Sun, 5 Nov 2023 01:27:02 +0800 Subject: [PATCH 3/3] feat(SafeValue): :sparkles: Add AtomicIntChangeAffectScore --- logic/Preparation/Utility/SafeValue/Atomic.cs | 82 +++++++++++++++++-- 1 file changed, 74 insertions(+), 8 deletions(-) diff --git a/logic/Preparation/Utility/SafeValue/Atomic.cs b/logic/Preparation/Utility/SafeValue/Atomic.cs index 0eee2f5f..dc9c570e 100644 --- a/logic/Preparation/Utility/SafeValue/Atomic.cs +++ b/logic/Preparation/Utility/SafeValue/Atomic.cs @@ -32,19 +32,19 @@ public AtomicInt(int x) /// public virtual int SubPositive(int x) => Interlocked.Add(ref v, -x); public virtual int Inc() => Interlocked.Increment(ref v); - public int Dec() => Interlocked.Decrement(ref v); + public virtual int Dec() => Interlocked.Decrement(ref v); /// 返回操作前的值 public virtual int CompareExReturnOri(int newV, int compareTo) => Interlocked.CompareExchange(ref v, newV, compareTo); } /// /// 参数要求倍率speed(默认1)以及AtomicInt类的Score, - /// 在发生正向的变化时,自动给Score加上正向变化的差乘以speed。 + /// 在发生正向的变化时,自动给Score加上正向变化的差乘以speed取整。 /// 注意:AtomicIntOnlyAddScore本身为AtomicInt,提供的Score可能构成环而死锁。 /// public class AtomicIntOnlyAddScore : AtomicInt { - public AtomicInt Score { get; set; }; + public AtomicInt Score { get; set; } public AtomicDouble speed; public AtomicIntOnlyAddScore(int x, AtomicInt Score, double speed = 1.0) : base(x) { @@ -99,6 +99,72 @@ public override int CompareExReturnOri(int newV, int compareTo) } } + /// + /// 参数要求倍率speed(默认1)以及AtomicInt类的Score, + /// 在发生变化时,自动给Score加上变化的差乘以speed取整。 + /// 注意:AtomicIntChangeAffectScore本身为AtomicInt,提供的Score可能构成环而死锁。 + /// + public class AtomicIntChangeAffectScore : AtomicInt + { + public AtomicInt Score { get; set; } + public AtomicDouble speed; + public AtomicIntChangeAffectScore(int x, AtomicInt Score, double speed = 1.0) : base(x) + { + this.Score = Score; + this.speed = new(speed); + } + /// 返回操作前的值 + public override int SetReturnOri(int value) + { + int previousV = Interlocked.Exchange(ref v, value); + Score.Add((int)(speed * (value - previousV))); + return previousV; + } + public override int Add(int x) + { + Score.Add((int)(speed * x)); + return Interlocked.Add(ref v, x); + } + /// + /// 注意:确保参数为非负数 + /// + public override int AddPositive(int x) + { + Score.AddPositive((int)(speed * x)); + return Interlocked.Add(ref v, x); + } + public override int Sub(int x) + { + Score.Sub((int)(speed * x)); + return Interlocked.Add(ref v, -x); + } + /// + /// 注意:确保参数为非负数 + /// + public override int SubPositive(int x) + { + Score.SubPositive((int)(speed * x)); + return Interlocked.Add(ref v, -x); + } + public override int Inc() + { + Score.AddPositive((int)(speed)); + return Interlocked.Increment(ref v); + } + public override int Dec() + { + Score.SubPositive((int)(speed)); + return Interlocked.Decrement(ref v); + } + /// 返回操作前的值 + public override int CompareExReturnOri(int newV, int compareTo) + { + int previousV = Interlocked.CompareExchange(ref v, newV, compareTo); + Score.Add((int)(speed * (newV - previousV))); + return previousV; + } + } + public class AtomicLong : Atomic { protected long v; @@ -122,23 +188,23 @@ public AtomicLong(long x) /// public virtual long SubPositive(long x) => Interlocked.Add(ref v, -x); public virtual long Inc() => Interlocked.Increment(ref v); - public long Dec() => Interlocked.Decrement(ref v); + public virtual long Dec() => Interlocked.Decrement(ref v); /// 返回操作前的值 public virtual long CompareExReturnOri(long newV, long compareTo) => Interlocked.CompareExchange(ref v, newV, compareTo); } /// /// 参数要求倍率speed(默认1)以及AtomicLong类的Score, - /// 在发生正向的变化时,自动给Score加上正向变化的差乘以speed。 + /// 在发生正向的变化时,自动给Score加上正向变化的差乘以speed取整。 /// 注意:AtomicLongOnlyAddScore本身为AtomicLong,提供的Score可能构成环而死锁。 /// public class AtomicLongOnlyAddScore : AtomicLong { - public AtomicInt Score { get; set; }; + public AtomicLong Score { get; set; } public AtomicDouble speed; - public AtomicLongOnlyAddScore(long x, AtomicLong Score, double speed = 1.0) : base(x) + public AtomicLongOnlyAddScore(long x, AtomicLong score, double speed = 1.0) : base(x) { - this.Score = Score; + this.Score = score; this.speed = new(speed); } /// 返回操作前的值