Browse Source

Merge pull request #646 from shangfengh/new

refactor:  add the AtomicInt and AtomicBool
dev
Changli Tang GitHub 2 years ago
parent
commit
ac08fc3e06
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 91 additions and 104 deletions
  1. +5
    -5
      logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs
  2. +3
    -12
      logic/GameClass/GameObj/Bullet/Bullet.cs
  3. +2
    -2
      logic/GameClass/GameObj/Character/Character.Skill.cs
  4. +3
    -3
      logic/GameClass/GameObj/Character/Character.cs
  5. +2
    -11
      logic/GameClass/GameObj/GameObj.cs
  6. +0
    -2
      logic/GameClass/GameObj/Immovable.cs
  7. +4
    -32
      logic/GameClass/GameObj/Moveable.cs
  8. +2
    -2
      logic/GameClass/GameObj/Prop/Gadget.cs
  9. +2
    -2
      logic/GameClass/GameObj/Prop/Item.cs
  10. +4
    -4
      logic/GameEngine/MoveEngine.cs
  11. +2
    -2
      logic/Gaming/ActionManager.cs
  12. +4
    -8
      logic/Gaming/AttackManager.cs
  13. +0
    -10
      logic/Gaming/CharacterManager.cs
  14. +1
    -1
      logic/Gaming/Game.cs
  15. +1
    -1
      logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs
  16. +1
    -1
      logic/Preparation/Interface/IGameObj.cs
  17. +3
    -4
      logic/Preparation/Interface/IMoveable.cs
  18. +51
    -0
      logic/Preparation/Utility/LockedValue.cs
  19. +1
    -2
      logic/Preparation/Utility/XY.cs

+ 5
- 5
logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs View File

@@ -8,7 +8,7 @@ namespace GameClass.GameObj
public CommonAttackOfGhost(Character player, XY pos, int radius = GameData.bulletRadius) : public CommonAttackOfGhost(Character player, XY pos, int radius = GameData.bulletRadius) :
base(player, radius, pos) base(player, radius, pos)
{ {
ap = GameData.basicApOfGhost;
AP.Set(GameData.basicApOfGhost);
} }
public override double BulletBombRange => 0; public override double BulletBombRange => 0;
public override double AttackDistance => GameData.basicAttackShortRange; public override double AttackDistance => GameData.basicAttackShortRange;
@@ -45,7 +45,7 @@ namespace GameClass.GameObj
public Strike(Character player, XY pos, int radius = GameData.bulletRadius) : public Strike(Character player, XY pos, int radius = GameData.bulletRadius) :
base(player, radius, pos) base(player, radius, pos)
{ {
ap = GameData.basicApOfGhost * 16 / 15;
AP.Set(GameData.basicApOfGhost * 16 / 15);
} }
public override double BulletBombRange => 0; public override double BulletBombRange => 0;
public override double AttackDistance => GameData.basicAttackShortRange * 20 / 22; public override double AttackDistance => GameData.basicAttackShortRange * 20 / 22;
@@ -83,7 +83,7 @@ namespace GameClass.GameObj
public FlyingKnife(Character player, XY pos, int radius = GameData.bulletRadius) : public FlyingKnife(Character player, XY pos, int radius = GameData.bulletRadius) :
base(player, radius, pos) base(player, radius, pos)
{ {
ap = GameData.basicApOfGhost * 4 / 5;
AP.Set(GameData.basicApOfGhost * 4 / 5);
} }
public override double BulletBombRange => 0; public override double BulletBombRange => 0;
public override double AttackDistance => GameData.basicRemoteAttackRange * 13; public override double AttackDistance => GameData.basicRemoteAttackRange * 13;
@@ -123,7 +123,7 @@ namespace GameClass.GameObj
{ {
public BombBomb(Character player, XY pos, int radius = GameData.bulletRadius) : base(player, radius, pos) public BombBomb(Character player, XY pos, int radius = GameData.bulletRadius) : base(player, radius, pos)
{ {
ap = (int)(GameData.basicApOfGhost * 6.0 / 5);
AP.Set((int)(GameData.basicApOfGhost * 6.0 / 5));
} }
public override double BulletBombRange => GameData.basicBulletBombRange; public override double BulletBombRange => GameData.basicBulletBombRange;
public override double AttackDistance => GameData.basicAttackShortRange; public override double AttackDistance => GameData.basicAttackShortRange;
@@ -163,7 +163,7 @@ namespace GameClass.GameObj
{ {
public JumpyDumpty(Character player, XY pos, int radius = GameData.bulletRadius) : base(player, radius, pos) public JumpyDumpty(Character player, XY pos, int radius = GameData.bulletRadius) : base(player, radius, pos)
{ {
ap = (int)(GameData.basicApOfGhost * 0.6);
AP.Set((int)(GameData.basicApOfGhost * 0.6));
} }
public override double BulletBombRange => GameData.basicBulletBombRange / 2; public override double BulletBombRange => GameData.basicBulletBombRange / 2;
public override double AttackDistance => GameData.basicAttackShortRange * 18 / 22; public override double AttackDistance => GameData.basicAttackShortRange * 18 / 22;


+ 3
- 12
logic/GameClass/GameObj/Bullet/Bullet.cs View File

@@ -11,16 +11,7 @@ namespace GameClass.GameObj
/// </summary> /// </summary>
public abstract double BulletBombRange { get; } public abstract double BulletBombRange { get; }
public abstract double AttackDistance { get; } public abstract double AttackDistance { get; }
protected int ap;
public int AP
{
get => Interlocked.CompareExchange(ref ap, 0, 0);
}
public void AddAP(int addAp)
{
Interlocked.Add(ref ap, addAp);
}

public AtomicInt AP { get; }
public abstract int Speed { get; } public abstract int Speed { get; }
public abstract bool IsRemoteAttack { get; } public abstract bool IsRemoteAttack { get; }
public abstract int CastTime { get; } public abstract int CastTime { get; }
@@ -52,8 +43,8 @@ namespace GameClass.GameObj
public Bullet(Character player, int radius, XY Position) : public Bullet(Character player, int radius, XY Position) :
base(Position, radius, GameObjType.Bullet) base(Position, radius, GameObjType.Bullet)
{ {
this.ReSetCanMove(true);
this.MoveSpeed = this.Speed;
this.CanMove.Set(true);
this.MoveSpeed.Set(this.Speed);
this.hasSpear = player.TryUseSpear(); this.hasSpear = player.TryUseSpear();
this.Parent = player; this.Parent = player;
} }


+ 2
- 2
logic/GameClass/GameObj/Character/Character.Skill.cs View File

@@ -31,12 +31,12 @@ namespace GameClass.GameObj
protected Character(XY initPos, int initRadius, CharacterType characterType) : protected Character(XY initPos, int initRadius, CharacterType characterType) :
base(initPos, initRadius, GameObjType.Character) base(initPos, initRadius, GameObjType.Character)
{ {
this.ReSetCanMove(true);
this.CanMove.Set(true);
this.score = 0; this.score = 0;
this.buffManager = new BuffManager(); this.buffManager = new BuffManager();
this.occupation = OccupationFactory.FindIOccupation(characterType); this.occupation = OccupationFactory.FindIOccupation(characterType);
this.MaxHp = this.hp = Occupation.MaxHp; this.MaxHp = this.hp = Occupation.MaxHp;
this.MoveSpeed = this.orgMoveSpeed = Occupation.MoveSpeed;
this.MoveSpeed.Set(this.orgMoveSpeed = Occupation.MoveSpeed);
this.BulletOfPlayer = this.OriBulletOfPlayer = Occupation.InitBullet; this.BulletOfPlayer = this.OriBulletOfPlayer = Occupation.InitBullet;
this.concealment = Occupation.Concealment; this.concealment = Occupation.Concealment;
this.alertnessRadius = Occupation.AlertnessRadius; this.alertnessRadius = Occupation.AlertnessRadius;


+ 3
- 3
logic/GameClass/GameObj/Character/Character.cs View File

@@ -107,7 +107,7 @@ namespace GameClass.GameObj
); );
Bullet? bullet = BulletFactory.GetBullet(this, res, this.bulletOfPlayer); Bullet? bullet = BulletFactory.GetBullet(this, res, this.bulletOfPlayer);
if (bullet == null) return null; if (bullet == null) return null;
if (TryAddAp()) bullet.AddAP(GameData.ApPropAdd);
if (TryAddAp()) bullet.AP.Add(GameData.ApPropAdd);
FacingDirection = new(angle, bullet.AttackDistance); FacingDirection = new(angle, bullet.AttackDistance);
return bullet; return bullet;
} }
@@ -647,7 +647,7 @@ namespace GameClass.GameObj
{ {
if (SetPlayerState(RunningStateType.RunningForcibly, playerStateType) == -1) return false; if (SetPlayerState(RunningStateType.RunningForcibly, playerStateType) == -1) return false;
TryToRemove(); TryToRemove();
ReSetCanMove(false);
CanMove.Set(false);
position = GameData.PosWhoDie; position = GameData.PosWhoDie;
} }
return true; return true;
@@ -802,7 +802,7 @@ namespace GameClass.GameObj
} }


public void AddMoveSpeed(int buffTime, double add = 1.0) => buffManager.AddMoveSpeed(add, buffTime, newVal => public void AddMoveSpeed(int buffTime, double add = 1.0) => buffManager.AddMoveSpeed(add, buffTime, newVal =>
{ MoveSpeed = newVal < GameData.characterMaxSpeed ? newVal : GameData.characterMaxSpeed; },
{ MoveSpeed.Set(newVal < GameData.characterMaxSpeed ? newVal : GameData.characterMaxSpeed); },
OrgMoveSpeed); OrgMoveSpeed);
public bool HasFasterSpeed => buffManager.HasFasterSpeed; public bool HasFasterSpeed => buffManager.HasFasterSpeed;




+ 2
- 11
logic/GameClass/GameObj/GameObj.cs View File

@@ -26,23 +26,14 @@ namespace GameClass.GameObj
protected XY position; protected XY position;
public abstract XY Position { get; } public abstract XY Position { get; }


public abstract bool CanMove { get; }

public abstract bool IsRigid { get; } public abstract bool IsRigid { get; }


public abstract ShapeType Shape { get; } public abstract ShapeType Shape { get; }


protected int isRemoved = 0;
public bool IsRemoved
{
get
{
return (Interlocked.CompareExchange(ref isRemoved, 0, 0) == 1);
}
}
public AtomicBool IsRemoved { get; } = new AtomicBool(false);
public virtual bool TryToRemove() public virtual bool TryToRemove()
{ {
return Interlocked.Exchange(ref isRemoved, 1) == 0;
return IsRemoved.TrySet(true);
} }


public int Radius { get; } public int Radius { get; }


+ 0
- 2
logic/GameClass/GameObj/Immovable.cs View File

@@ -7,8 +7,6 @@ namespace GameClass.GameObj


public override XY Position => position; public override XY Position => position;


public override bool CanMove => false;

public Immovable(XY initPos, int initRadius, GameObjType initType) : base(initPos, initRadius, initType) public Immovable(XY initPos, int initRadius, GameObjType initType) : base(initPos, initRadius, initType)
{ {
} }


+ 4
- 32
logic/GameClass/GameObj/Moveable.cs View File

@@ -67,12 +67,7 @@ namespace GameClass.GameObj
} }
} }


private int isMoving = 0;
public bool IsMoving
{
get => (Interlocked.CompareExchange(ref isMoving, 0, 0) == 1);
set => Interlocked.Exchange(ref isMoving, value ? 1 : 0);
}
public AtomicBool IsMoving { get; } = new(false);


// 移动,改变坐标 // 移动,改变坐标
public long MovingSetPos(XY moveVec, long stateNo) public long MovingSetPos(XY moveVec, long stateNo)
@@ -99,37 +94,14 @@ namespace GameClass.GameObj
} }
} }


private int canMove;
public override bool CanMove
{
get => (Interlocked.CompareExchange(ref canMove, 0, 0) == 1);
}
public AtomicBool CanMove { get; }


public void ReSetCanMove(bool value)
{
Interlocked.Exchange(ref canMove, (value ? 1 : 0));
}
public bool IsAvailableForMove => !IsMoving && CanMove && !IsRemoved; // 是否能接收移动指令


public bool IsAvailableForMove // 是否能接收移动指令
{
get
{
lock (actionLock)
{
return !IsMoving && CanMove && !IsRemoved;
}
}
}

protected int moveSpeed;
/// <summary> /// <summary>
/// 移动速度 /// 移动速度
/// </summary> /// </summary>
public int MoveSpeed
{
get => Interlocked.CompareExchange(ref moveSpeed, 0, 0);
set => Interlocked.Exchange(ref moveSpeed, value);
}
public AtomicInt MoveSpeed { get; }
/// <summary> /// <summary>
/// 原初移动速度 /// 原初移动速度
/// </summary> /// </summary>


+ 2
- 2
logic/GameClass/GameObj/Prop/Gadget.cs View File

@@ -24,8 +24,8 @@ namespace GameClass.GameObj
public Gadget(XY initPos, int radius = GameData.propRadius) : public Gadget(XY initPos, int radius = GameData.propRadius) :
base(initPos, radius, GameObjType.Gadget) base(initPos, radius, GameObjType.Gadget)
{ {
this.ReSetCanMove(false);
this.MoveSpeed = GameData.propMoveSpeed;
this.CanMove.Set(false);
this.MoveSpeed.Set(GameData.propMoveSpeed);
} }
} }
public abstract class Tool : Gadget public abstract class Tool : Gadget


+ 2
- 2
logic/GameClass/GameObj/Prop/Item.cs View File

@@ -17,8 +17,8 @@ namespace GameClass.GameObj
public Item(XY initPos, int radius = GameData.propRadius) : public Item(XY initPos, int radius = GameData.propRadius) :
base(initPos, radius, GameObjType.Item) base(initPos, radius, GameObjType.Item)
{ {
this.ReSetCanMove(false);
this.MoveSpeed = 0;
this.CanMove.Set(false);
this.MoveSpeed.Set(0);
} }
} }




+ 4
- 4
logic/GameEngine/MoveEngine.cs View File

@@ -102,7 +102,7 @@ namespace GameEngine
lock (obj.ActionLock) lock (obj.ActionLock)
{ {
if (!obj.IsAvailableForMove) { EndMove(obj); return; } if (!obj.IsAvailableForMove) { EndMove(obj); return; }
obj.IsMoving = true;
obj.IsMoving.Set(true);
} }


new Thread new Thread
@@ -139,7 +139,7 @@ namespace GameEngine


if (isEnded) if (isEnded)
{ {
obj.IsMoving = false;
obj.IsMoving.Set(false);
EndMove(obj); EndMove(obj);
return; return;
} }
@@ -184,7 +184,7 @@ namespace GameEngine
} }
if (isEnded) if (isEnded)
{ {
obj.IsMoving = false;
obj.IsMoving.Set(false);
EndMove(obj); EndMove(obj);
return; return;
} }
@@ -224,7 +224,7 @@ namespace GameEngine
} }
} while (flag); } while (flag);
} }
obj.IsMoving = false; // 结束移动
obj.IsMoving.Set(false); // 结束移动
EndMove(obj); EndMove(obj);
} }
} }


+ 2
- 2
logic/Gaming/ActionManager.cs View File

@@ -450,12 +450,12 @@ namespace Gaming
player.ReSetPos(windowToPlayer + windowForClimb.Position); player.ReSetPos(windowToPlayer + windowForClimb.Position);
} }


player.MoveSpeed = player.SpeedOfClimbingThroughWindows;
player.MoveSpeed.Set(player.SpeedOfClimbingThroughWindows);
moveEngine.MoveObj(player, (int)(GameData.numOfPosGridPerCell * 3 * 1000 / player.MoveSpeed / 2), (-1 * windowToPlayer).Angle(), stateNum); moveEngine.MoveObj(player, (int)(GameData.numOfPosGridPerCell * 3 * 1000 / player.MoveSpeed / 2), (-1 * windowToPlayer).Angle(), stateNum);


Thread.Sleep((int)(GameData.numOfPosGridPerCell * 3 * 1000 / player.MoveSpeed / 2)); Thread.Sleep((int)(GameData.numOfPosGridPerCell * 3 * 1000 / player.MoveSpeed / 2));


player.MoveSpeed = player.ReCalculateBuff(BuffType.AddSpeed, player.OrgMoveSpeed, GameData.MaxSpeed, GameData.MinSpeed);
player.MoveSpeed.Set(player.ReCalculateBuff(BuffType.AddSpeed, player.OrgMoveSpeed, GameData.MaxSpeed, GameData.MinSpeed));


lock (player.ActionLock) lock (player.ActionLock)
{ {


+ 4
- 8
logic/Gaming/AttackManager.cs View File

@@ -33,7 +33,7 @@ namespace Gaming
Debugger.Output(obj, " end move at " + obj.Position.ToString() + " At time: " + Environment.TickCount64); Debugger.Output(obj, " end move at " + obj.Position.ToString() + " At time: " + Environment.TickCount64);
if (obj.CanMove && ((Bullet)obj).TypeOfBullet != BulletType.JumpyDumpty) if (obj.CanMove && ((Bullet)obj).TypeOfBullet != BulletType.JumpyDumpty)
BulletBomb((Bullet)obj, null); BulletBomb((Bullet)obj, null);
obj.ReSetCanMove(false);
obj.CanMove.Set(false);
} }
); );
this.characterManager = characterManager; this.characterManager = characterManager;
@@ -89,7 +89,7 @@ namespace Gaming
{ {
if (gameMap.Remove(bullet)) if (gameMap.Remove(bullet))
{ {
bullet.ReSetCanMove(false);
bullet.CanMove.Set(false);
if (bullet.BulletBombRange > 0) if (bullet.BulletBombRange > 0)
{ {
BombedBullet bombedBullet = new(bullet); BombedBullet bombedBullet = new(bullet);
@@ -255,16 +255,12 @@ namespace Gaming
} }
if (bullet != null) if (bullet != null)
{ {
#if DEBUG
Console.WriteLine($"playerID:{player.ID} successfully attacked!");
#endif
Debugger.Output($"playerID:{player.ID} successfully attacked!");
return true; return true;
} }
else else
{ {
#if DEBUG
Console.WriteLine($"playerID:{player.ID} has no bullets so that he can't attack!");
#endif
Debugger.Output($"playerID:{player.ID} has no bullets so that he can't attack!");
return false; return false;
} }
} }


+ 0
- 10
logic/Gaming/CharacterManager.cs View File

@@ -306,9 +306,7 @@ namespace Gaming
/// <returns>人物在受到攻击后死了吗</returns> /// <returns>人物在受到攻击后死了吗</returns>
public void BeAttacked(Student student, Bullet bullet) public void BeAttacked(Student student, Bullet bullet)
{ {
#if DEBUG
Debugger.Output(student, "is being shot!"); Debugger.Output(student, "is being shot!");
#endif
if (!bullet.Parent!.IsGhost()) return; if (!bullet.Parent!.IsGhost()) return;


if (student.CharacterType == CharacterType.StraightAStudent) if (student.CharacterType == CharacterType.StraightAStudent)
@@ -319,17 +317,13 @@ namespace Gaming


if (student.NoHp()) return; // 原来已经死了 if (student.NoHp()) return; // 原来已经死了


#if DEBUG
Debugger.Output(bullet, " 's AP is " + bullet.AP.ToString()); Debugger.Output(bullet, " 's AP is " + bullet.AP.ToString());
#endif
if (student.TryUseShield()) if (student.TryUseShield())
{ {
if (bullet.HasSpear) if (bullet.HasSpear)
{ {
long subHp = student.SubHp(bullet.AP); long subHp = student.SubHp(bullet.AP);
#if DEBUG
Debugger.Output(this, "is being shot! Now his hp is" + student.HP.ToString()); Debugger.Output(this, "is being shot! Now his hp is" + student.HP.ToString());
#endif
bullet.Parent.AddScore(GameData.TrickerScoreAttackStudent(subHp) + GameData.ScorePropUseSpear); bullet.Parent.AddScore(GameData.TrickerScoreAttackStudent(subHp) + GameData.ScorePropUseSpear);
bullet.Parent.AddHP((long)bullet.Parent.Vampire * subHp); bullet.Parent.AddHP((long)bullet.Parent.Vampire * subHp);
} }
@@ -341,16 +335,12 @@ namespace Gaming
if (bullet.HasSpear) if (bullet.HasSpear)
{ {
subHp = student.SubHp(bullet.AP + GameData.ApSpearAdd); subHp = student.SubHp(bullet.AP + GameData.ApSpearAdd);
#if DEBUG
Debugger.Output(this, "is being shot with Spear! Now his hp is" + student.HP.ToString()); Debugger.Output(this, "is being shot with Spear! Now his hp is" + student.HP.ToString());
#endif
} }
else else
{ {
subHp = student.SubHp(bullet.AP); subHp = student.SubHp(bullet.AP);
#if DEBUG
Debugger.Output(this, "is being shot! Now his hp is" + student.HP.ToString()); Debugger.Output(this, "is being shot! Now his hp is" + student.HP.ToString());
#endif
} }
bullet.Parent.AddScore(GameData.TrickerScoreAttackStudent(subHp)); bullet.Parent.AddScore(GameData.TrickerScoreAttackStudent(subHp));
if (student.CharacterType == CharacterType.Teacher) if (student.CharacterType == CharacterType.Teacher)


+ 1
- 1
logic/Gaming/Game.cs View File

@@ -326,7 +326,7 @@ namespace Gaming
{ {
foreach (Character player in gameMap.GameObjDict[GameObjType.Character]) foreach (Character player in gameMap.GameObjDict[GameObjType.Character])
{ {
player.ReSetCanMove(false);
player.CanMove.Set(false);
} }
} }
gameMap.GameObjDict[keyValuePair.Key].Clear(); gameMap.GameObjDict[keyValuePair.Key].Clear();


+ 1
- 1
logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs View File

@@ -196,7 +196,7 @@ namespace Gaming
} }
if (homingMissile != null) if (homingMissile != null)
{ {
homingMissile.ReSetCanMove(true);
homingMissile.CanMove.Set(true);
attackManager.moveEngine.MoveObj(homingMissile, GameData.checkIntervalWhenSparksNSplash - 1, (whoAttacked.Position - homingMissile.Position).Angle(), ++homingMissile.StateNum); attackManager.moveEngine.MoveObj(homingMissile, GameData.checkIntervalWhenSparksNSplash - 1, (whoAttacked.Position - homingMissile.Position).Angle(), ++homingMissile.StateNum);
} }
}, },


+ 1
- 1
logic/Preparation/Interface/IGameObj.cs View File

@@ -8,8 +8,8 @@ namespace Preparation.Interface
public long ID { get; } public long ID { get; }
public XY Position { get; } // if Square, Pos equals the center public XY Position { get; } // if Square, Pos equals the center
public bool IsRigid { get; } public bool IsRigid { get; }
public AtomicBool IsRemoved { get; }
public ShapeType Shape { get; } public ShapeType Shape { get; }
public bool CanMove { get; }
public int Radius { get; } // if Square, Radius equals half length of one side public int Radius { get; } // if Square, Radius equals half length of one side
public bool IgnoreCollideExecutor(IGameObj targetObj); // 忽略碰撞,在具体类中实现 public bool IgnoreCollideExecutor(IGameObj targetObj); // 忽略碰撞,在具体类中实现
} }


+ 3
- 4
logic/Preparation/Interface/IMoveable.cs View File

@@ -8,14 +8,13 @@ namespace Preparation.Interface
{ {
public XY FacingDirection { get; set; } public XY FacingDirection { get; set; }
object ActionLock { get; } object ActionLock { get; }
public int MoveSpeed { get; }
public bool IsMoving { get; set; }
public bool IsRemoved { get; }
public AtomicInt MoveSpeed { get; }
public AtomicBool CanMove { get; }
public AtomicBool IsMoving { get; }
public bool IsAvailableForMove { get; } public bool IsAvailableForMove { get; }
public long StateNum { get; } public long StateNum { get; }
public Semaphore ThreadNum { get; } public Semaphore ThreadNum { get; }
public long MovingSetPos(XY moveVec, long stateNum); public long MovingSetPos(XY moveVec, long stateNum);
public void ReSetCanMove(bool value);
public bool WillCollideWith(IGameObj? targetObj, XY nextPos) // 检查下一位置是否会和目标物碰撞 public bool WillCollideWith(IGameObj? targetObj, XY nextPos) // 检查下一位置是否会和目标物碰撞
{ {
if (targetObj == null) if (targetObj == null)


+ 51
- 0
logic/Preparation/Utility/LockedValue.cs View File

@@ -0,0 +1,51 @@
using System.Threading;

namespace Preparation.Utility
{
//理论上结构体最好不可变,这里采用了可变结构。
public struct AtomicInt
{
private int v;
public AtomicInt(int x)
{
v = x;
}
public override string ToString() => Interlocked.CompareExchange(ref v, -1, -1).ToString();
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 Set(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 int Dec() => Interlocked.Decrement(ref v);

public void CompareExchange(int b, int c) => Interlocked.CompareExchange(ref v, b, c);
/// <returns>返回操作前的值</returns>
public int CompareExReturnOri(int b, int c) => Interlocked.CompareExchange(ref v, b, c);
}
public struct AtomicBool
{
private int v;//v==0为false,v!=0(v==1或v==-1)为true
public AtomicBool(bool x)
{
v = x ? 1 : 0;
}
public override string ToString() => (Interlocked.CompareExchange(ref v, -1, -1) == 0) ? "false" : "true";
public bool Get() => (Interlocked.CompareExchange(ref v, -1, -1) != 0);
public static implicit operator bool(AtomicBool abool) => (Interlocked.CompareExchange(ref abool.v, -1, -1) != 0);

public bool Set(bool value) => (Interlocked.Exchange(ref v, value ? 1 : 0) != 0);

/// <returns>赋值前的值是否与将赋予的值不相同</returns>
public bool TrySet(bool value)
{
int ori = Interlocked.CompareExchange(ref v, value ? 1 : 0, value ? 1 : 0);
return value ? (ori == 0) : (ori != 0);
}

public bool Invert() => Interlocked.Add(ref v, -1) != 0;
public bool And(bool x) => Interlocked.And(ref v, x ? 1 : 0) != 0;
public bool Or(bool x) => Interlocked.Or(ref v, x ? 1 : 0) != 0;
}
}

+ 1
- 2
logic/Preparation/Utility/XY.cs View File

@@ -2,7 +2,6 @@


namespace Preparation.Utility namespace Preparation.Utility
{ {

public struct XY public struct XY
{ {
public int x; public int x;
@@ -89,7 +88,7 @@ namespace Preparation.Utility
return Math.Atan2(y, x); return Math.Atan2(y, x);
} }


public override bool Equals(object? obj) => obj is null || obj is XY ? false : this == (XY)obj;
public override bool Equals(object? obj) => obj is not null && obj is XY xy && this == xy;


public override int GetHashCode() public override int GetHashCode()
{ {


Loading…
Cancel
Save