Ensure access is threadsafe

This commit is contained in:
UnknownShadow200 2017-04-21 15:07:26 +10:00
parent dc5d5e138e
commit 2b73e0c553
3 changed files with 44 additions and 12 deletions

View File

@ -16,21 +16,21 @@
permissions and limitations under the Licenses.
*/
using System;
using System.Threading;
namespace MCGalaxy {
/// <summary> Represents a player or an NPC. </summary>
public abstract class Entity {
// Raw orientation/position - NOT threadsafe
protected Orientation _rot;
protected Position _pos;
// Raw orientation/position - access must be threadsafe
int _rot;
long _pos;
// Last sent orientation/position, for delta calculation
protected internal Orientation lastRot;
protected internal Position lastPos;
internal bool supportsExtPositions;
// TODO: struct assignment needs to be THREADSAFE
/// <summary> Model name of this entity. </summary>
@ -45,14 +45,14 @@ namespace MCGalaxy {
/// <summary> Gets or sets the orientation of this entity. </summary>
public Orientation Rot {
get { return _rot; }
set { _rot = value; OnSetRot(); }
get { return Orientation.Unpack(Thread.VolatileRead(ref _rot)); }
set { Thread.VolatileWrite(ref _rot, value.Pack()); OnSetRot(); }
}
/// <summary> Gets or sets the position of this entity. </summary>
public Position Pos {
get { return _pos; }
set { _pos = value; OnSetPos(); }
get { return Position.Unpack(Thread.VolatileRead(ref _pos)); }
set { Thread.VolatileWrite(ref _pos, value.Pack()); OnSetPos(); }
}
/// <summary> Sets only the yaw and pitch of the orientation of this entity. </summary>

View File

@ -18,7 +18,7 @@
using System;
namespace MCGalaxy {
/// <summary> Represents the position of an entity in the world. </summary>
public struct Position: IEquatable<Position> {
@ -62,6 +62,27 @@ namespace MCGalaxy {
public static bool operator == (Position a, Position b) { return a.Equals(b); }
public static bool operator != (Position a, Position b) { return !a.Equals(b); }
const long mask = 0x1FFFFF;
internal long Pack() {
return (X & mask) | ((Y & mask) << 21) | ((Z & mask) << 42);
}
internal static Position Unpack(long raw) {
Position pos;
pos.X = SignExtend(raw);
pos.Y = SignExtend(raw >> 21);
pos.Z = SignExtend(raw >> 42);
return pos;
}
static int SignExtend(long parts) {
int value = (int)(parts & mask);
value <<= (32 - 21);
value >>= (32 - 21);
return value;
}
}
@ -92,5 +113,17 @@ namespace MCGalaxy {
public static byte DegreesToPacked(int degrees) {
return (byte)(degrees * 256 / 360);
}
internal int Pack() {
return RotX | (RotY << 8) | (RotZ << 16) | HeadX;
}
internal static Orientation Unpack(int raw) {
Orientation rot;
rot.RotX = (byte)raw; rot.RotY = (byte)(raw >> 8);
rot.RotZ = (byte)(raw >> 16); rot.HeadX = (byte)(raw >> 24);
return rot;
}
}
}

View File

@ -23,10 +23,9 @@ using System.IO;
namespace MCGalaxy {
public sealed class GroupProperties {
const string filename = "properties/ranks.properties";
public static void InitAll() {
Group grp = null;
PropertiesFile.Read(filename, ref grp, ParseProperty, '=', false);
PropertiesFile.Read(Paths.RankPropsFile, ref grp, ParseProperty, '=', false);
if (grp != null) AddGroup(ref grp);
}
@ -115,7 +114,7 @@ namespace MCGalaxy {
/// <summary> Save givenList group </summary>
/// <param name="givenList">The list of groups to save</param>
public static void SaveGroups(List<Group> givenList) {
using (StreamWriter w = new StreamWriter(filename)) {
using (StreamWriter w = new StreamWriter(Paths.RankPropsFile)) {
w.WriteLine("#Version 3");
w.WriteLine("#RankName = string");
w.WriteLine("#\tThe name of the rank, use capitalization.");