Skip to content

Commit 6e19457

Browse files
committed
Added Fence and SemaphoreLight.
1 parent 82620dc commit 6e19457

File tree

3 files changed

+124
-2
lines changed

3 files changed

+124
-2
lines changed

Hexa.NET.Utilities/Fence.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
namespace Hexa.NET.Utilities
2+
{
3+
using System.Diagnostics;
4+
using System.Threading;
5+
6+
public struct Fence
7+
{
8+
private int _state;
9+
10+
public Fence()
11+
{
12+
_state = 0;
13+
}
14+
15+
public void Signal()
16+
{
17+
Interlocked.Exchange(ref _state, 1);
18+
}
19+
20+
public void Wait()
21+
{
22+
while (Interlocked.CompareExchange(ref _state, 0, 0) == 0)
23+
{
24+
Thread.Yield();
25+
}
26+
}
27+
28+
public bool Wait(int timeout)
29+
{
30+
if (timeout == 0)
31+
{
32+
return Interlocked.CompareExchange(ref _state, 0, 0) != 0;
33+
}
34+
35+
var end = Stopwatch.GetTimestamp() + timeout * (Stopwatch.Frequency / 1000);
36+
while (Interlocked.CompareExchange(ref _state, 0, 0) == 0)
37+
{
38+
var now = Stopwatch.GetTimestamp();
39+
if (now >= end)
40+
{
41+
return false;
42+
}
43+
44+
Thread.Yield();
45+
}
46+
return true;
47+
}
48+
49+
public void Reset()
50+
{
51+
Interlocked.Exchange(ref _state, 0);
52+
}
53+
}
54+
}

Hexa.NET.Utilities/Hexa.NET.Utilities.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<PropertyGroup>
2020
<PackageId>Hexa.NET.Utilities</PackageId>
2121
<AssemblyVersion>1.0.0</AssemblyVersion>
22-
<PackageVersion>2.1.4</PackageVersion>
22+
<PackageVersion>2.1.5</PackageVersion>
2323
<Authors>Juna</Authors>
2424
<AssemblyName>Hexa.NET.Utilities</AssemblyName>
2525
<PackageProjectUrl>https://github.com/HexaEngine/Hexa.NET.Utilities</PackageProjectUrl>
@@ -37,7 +37,7 @@
3737
</ItemGroup>
3838

3939
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.1'">
40-
<PackageReference Include="System.Memory" Version="4.5.5" />
40+
<PackageReference Include="System.Memory" Version="4.5.5" />
4141
</ItemGroup>
4242

4343

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
namespace Hexa.NET.Utilities
2+
{
3+
using System.Runtime.CompilerServices;
4+
5+
public struct SemaphoreLight
6+
{
7+
private int currentCount;
8+
private readonly int maxCount;
9+
private int spinLock;
10+
11+
public SemaphoreLight(int initialCount, int maxCount)
12+
{
13+
if (initialCount > maxCount || initialCount < 0 || maxCount <= 0)
14+
{
15+
throw new ArgumentException("Invalid semaphore initial or max count");
16+
}
17+
18+
currentCount = initialCount;
19+
this.maxCount = maxCount;
20+
spinLock = 0;
21+
}
22+
23+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
24+
private void AcquireLock()
25+
{
26+
while (Interlocked.CompareExchange(ref spinLock, 1, 0) != 0)
27+
{
28+
Thread.Yield(); // Minimiert CPU-Belastung, aber ist noch kein Spin-Waiting
29+
}
30+
}
31+
32+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
33+
private void ReleaseLock()
34+
{
35+
Volatile.Write(ref spinLock, 0);
36+
}
37+
38+
public void Wait()
39+
{
40+
while (true)
41+
{
42+
AcquireLock();
43+
if (currentCount > 0)
44+
{
45+
currentCount--;
46+
ReleaseLock();
47+
break;
48+
}
49+
ReleaseLock();
50+
Thread.Sleep(1); // Minimale Blockierung, um CPU zu entlasten, kein Spin-Waiting
51+
}
52+
}
53+
54+
public void Release()
55+
{
56+
AcquireLock();
57+
if (currentCount < maxCount)
58+
{
59+
currentCount++;
60+
}
61+
else
62+
{
63+
throw new InvalidOperationException("Semaphore released too many times");
64+
}
65+
ReleaseLock();
66+
}
67+
}
68+
}

0 commit comments

Comments
 (0)