Skip to content

Commit

Permalink
fix: check against race condition while converting data
Browse files Browse the repository at this point in the history
Add a check, if the converting is still ongoing, to simply skip it in the current thread to avoid race conditions
  • Loading branch information
RenCloud authored Feb 11, 2023
1 parent 2430415 commit 6e3e50d
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 29 deletions.
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Rev 12, Update 1

- fix: add check to avoid a race condition when converting the data

## Rev 12, former Rev 11 Update 1

Change version to 12, because of offset changes. This leads to a rev change and not just an update like it was before.
Expand Down
22 changes: 13 additions & 9 deletions scs-client/C#/SCSSdkClient/SCSSdkConvert.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
//
// Ets2SdkClient
// Ets2SdkDataAlt.cs
// 22:51

using System;
using System;
using System.Text;
using SCSSdkClient.Object;

Expand All @@ -14,8 +9,8 @@ namespace SCSSdkClient {
/// </summary>
public class SCSSdkConvert {
private const int StringSize = 64;
private const int Substances = 25;
private const int WheelSize = 16;
private const int Substances = 25;

private readonly int[] _offsetAreas =
{0, 40, 500, 700, 1500, 1640, 2000, 2200, 2300, 4000, 4200, 4300, 4400, 6000};
Expand All @@ -25,6 +20,8 @@ public class SCSSdkConvert {

private int _offsetArea;

private bool currentlyActive = false;

/// <summary>
/// Convert the Shared Memory Byte data structure in a C# object
/// </summary>
Expand All @@ -35,6 +32,12 @@ public class SCSSdkConvert {
/// C# object with game data of the shared memory
/// </returns>
public SCSTelemetry Convert(byte[] structureDataBytes) {
if (currentlyActive) {
return null;
}

currentlyActive = true;

_offsetArea = 0;
SetOffset();

Expand Down Expand Up @@ -388,6 +391,8 @@ public SCSTelemetry Convert(byte[] structureDataBytes) {

#endregion 14TH ZONE

currentlyActive = false;

return retData;
}

Expand All @@ -399,6 +404,7 @@ private bool GetBool() {

private bool[] GetBoolArray(int length) {
var res = new bool[length];

for (var i = 0; i < length; i++) {
res[i] = GetBool();
}
Expand Down Expand Up @@ -594,7 +600,6 @@ private SCSTelemetry.Trailer GetTrailer() {

private SCSTelemetry.Trailer[] GetTrailers() {
var trailer = new SCSTelemetry.Trailer[10];

//TODO : only 1 for old game versions
for (var i = 0; i < 10; i++) {
trailer[i] = GetTrailer();
Expand Down Expand Up @@ -640,7 +645,6 @@ private void NextOffsetArea() {
}

private void SetOffset() {
// Debug Fix?
if (_offsetArea >= _offsetAreas.Length) {
return;
}
Expand Down
50 changes: 31 additions & 19 deletions scs-client/C#/SCSSdkClient/SCSSdkTelemetry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
using SCSSdkClient.Object;

namespace SCSSdkClient {

/// <summary>
/// Data Event
///
///
/// The parameter **newTimeStamp** is deprecated and will be removed in a future release.
///
///
/// </summary>
///
///
///
///
/// <param name="data">All data of the telemetry</param>
/// <param name="newTimestamp">Flag if the data changed</param>
public delegate void TelemetryData(SCSTelemetry data, bool newTimestamp);
Expand All @@ -19,27 +20,27 @@ namespace SCSSdkClient {
/// Handle the SCSSdkTelemetry.
/// Currently IDisposable. Was implemented because of an error
/// </summary>
public class SCSSdkTelemetry : IDisposable {
public class SCSSdkTelemetry: IDisposable {
private const string DefaultSharedMemoryMap = "Local\\SCSTelemetry";
private const int DefaultUpdateInterval = 100;
private const int DefaultPausedUpdateInterval = 1000;

private int updateInterval;

// todo: enhancement: some way to set this value
// todo: enhancement: some way to set this value
private readonly int pausedUpdateInterval = DefaultPausedUpdateInterval;

private Timer _updateTimer;

private ulong lastTime = 0xFFFFFFFFFFFFFFFF;


#if LOGGING
public void Dispose() {
_updateTimer?.Dispose();
Log.SaveShutdown();
}
#else

public void Dispose() => _updateTimer?.Dispose();

#endif
Expand Down Expand Up @@ -69,20 +70,28 @@ public void Dispose() {
public string Map { get; private set; }
public int UpdateInterval => paused ? pausedUpdateInterval : updateInterval;


public Exception Error { get; private set; }

public event TelemetryData Data;

public event EventHandler JobStarted;

public event EventHandler JobCancelled;

public event EventHandler JobDelivered;

public event EventHandler Fined;

public event EventHandler Tollgate;

public event EventHandler Ferry;

public event EventHandler Train;

public event EventHandler RefuelStart;

public event EventHandler RefuelEnd;

public event EventHandler RefuelPayed;

public void pause() => _updateTimer.Change(Timeout.Infinite, Timeout.Infinite);
Expand Down Expand Up @@ -127,9 +136,13 @@ private void Setup(string map, int interval) {
private void _updateTimer_Elapsed(object sender) {
var scsTelemetry = SharedMemory.Update<SCSTelemetry>();

if (scsTelemetry == null) {
return;
}

// check if sdk is NOT running
if (!scsTelemetry.SdkActive && !paused) {
// if so don't check so often the data
// if so don't check so often the data
var tsInterval = new TimeSpan(0, 0, 0, 0, DefaultPausedUpdateInterval);
_updateTimer.Change(tsInterval.Add(tsInterval), tsInterval);
paused = true;
Expand Down Expand Up @@ -182,43 +195,41 @@ private void _updateTimer_Elapsed(object sender) {

if (delivered != scsTelemetry.SpecialEventsValues.JobDelivered) {
delivered = scsTelemetry.SpecialEventsValues.JobDelivered;

if (!updated) {
Data?.Invoke(scsTelemetry, true);
updated = true;
}

JobDelivered?.Invoke(this, new EventArgs());
JobDelivered?.Invoke(this, new EventArgs());
}

if (fined != scsTelemetry.SpecialEventsValues.Fined) {
fined = scsTelemetry.SpecialEventsValues.Fined;
Fined?.Invoke(this, new EventArgs());

Fined?.Invoke(this, new EventArgs());
}

if (tollgate != scsTelemetry.SpecialEventsValues.Tollgate) {
tollgate = scsTelemetry.SpecialEventsValues.Tollgate;


Tollgate?.Invoke(this, new EventArgs());

}

if (ferry != scsTelemetry.SpecialEventsValues.Ferry) {
ferry = scsTelemetry.SpecialEventsValues.Ferry;

if (!updated) {
Data?.Invoke(scsTelemetry, true);
updated = true;
}

Ferry?.Invoke(this, new EventArgs());
Ferry?.Invoke(this, new EventArgs());
}

if (train != scsTelemetry.SpecialEventsValues.Train) {
train = scsTelemetry.SpecialEventsValues.Train;

if (!updated) {
Data?.Invoke(scsTelemetry, true);
updated = true;
Expand Down Expand Up @@ -252,6 +263,7 @@ private void _updateTimer_Elapsed(object sender) {
Data?.Invoke(scsTelemetry, false);
}
}

#if LOGGING
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
try {
Expand All @@ -269,4 +281,4 @@ private static void CurrentDomain_UnhandledException(object sender, UnhandledExc
}
#endif
}
}
}
4 changes: 3 additions & 1 deletion scs-client/C#/SCSSdkClient/SharedMemory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
using SCSSdkClient.Object;

namespace SCSSdkClient {

/// <summary>
/// Manage the shared memory
/// </summary>
public class SharedMemory {

/// <summary>
/// size of the shared memory in bytes
/// </summary>
Expand Down Expand Up @@ -119,4 +121,4 @@ public void Update() {
/// <returns>Managed object from given bytes</returns>
protected SCSTelemetry ToObject<T>(byte[] structureDataBytes) => _sdkconvert.Convert(structureDataBytes);
}
}
}

0 comments on commit 6e3e50d

Please sign in to comment.