Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 27 additions & 15 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,33 +15,33 @@ jobs:
with:
path: ${{ github.event.repository.name }}

- name: Checkout `worlds`
- name: Checkout `types`
uses: actions/checkout@v4.1.2
with:
repository: simulation-tree/worlds
repository: simulation-tree/types
token: ${{ secrets.PAT }}
path: worlds
path: types

- name: Checkout `types`
- name: Checkout `collections`
uses: actions/checkout@v4.1.2
with:
repository: simulation-tree/types
repository: simulation-tree/collections
token: ${{ secrets.PAT }}
path: types
path: collections

- name: Checkout `unmanaged`
- name: Checkout `worlds`
uses: actions/checkout@v4.1.2
with:
repository: simulation-tree/unmanaged
repository: simulation-tree/worlds
token: ${{ secrets.PAT }}
path: unmanaged
path: worlds

- name: Checkout `collections`
- name: Checkout `unmanaged`
uses: actions/checkout@v4.1.2
with:
repository: simulation-tree/collections
repository: simulation-tree/unmanaged
token: ${{ secrets.PAT }}
path: collections
path: unmanaged

- name: Setup
uses: actions/setup-dotnet@v4
Expand All @@ -51,29 +51,41 @@ jobs:
- name: Set VERSION variable from tag
run: echo "VERSION=${GITHUB_REF/refs\/tags\/v/}" >> $GITHUB_ENV

- name: Build `Simulation.Core`
run: dotnet build "${{ github.event.repository.name }}/core" -c Debug /p:Version=${VERSION}

- name: Build `Simulation.Core`
run: dotnet build "${{ github.event.repository.name }}/core" -c Release /p:Version=${VERSION}

- name: Build `Simulation.Generator`
run: dotnet build "${{ github.event.repository.name }}/generator" -c Debug /p:Version=${VERSION}

- name: Build `Simulation.Generator`
run: dotnet build "${{ github.event.repository.name }}/generator" -c Release /p:Version=${VERSION}

- name: Build `Simulation`
run: dotnet build "${{ github.event.repository.name }}/source" -c Debug /p:Version=${VERSION}

- name: Build `Simulation`
run: dotnet build "${{ github.event.repository.name }}/source" -c Release /p:Version=${VERSION}

- name: Build `Simulation.Tests`
run: dotnet build "${{ github.event.repository.name }}/tests" -c Debug /p:Version=${VERSION}

- name: Build `Simulation.Tests`
run: dotnet build "${{ github.event.repository.name }}/tests" -c Release /p:Version=${VERSION}

- name: Test
run: dotnet test "${{ github.event.repository.name }}/tests" -c Release --logger "trx"

- name: Pack `Simulation.Core`
run: dotnet pack "${{ github.event.repository.name }}/core" -c Release /p:Version=${VERSION} --no-build --output .
run: dotnet pack "${{ github.event.repository.name }}/core" /p:Version=${VERSION} --no-build --output .

- name: Pack `Simulation.Generator`
run: dotnet pack "${{ github.event.repository.name }}/generator" -c Release /p:Version=${VERSION} --no-build --output .
run: dotnet pack "${{ github.event.repository.name }}/generator" /p:Version=${VERSION} --no-build --output .

- name: Pack `Simulation`
run: dotnet pack "${{ github.event.repository.name }}/source" -c Release /p:Version=${VERSION} --no-build --output .
run: dotnet pack "${{ github.event.repository.name }}/source" /p:Version=${VERSION} --no-build --output .

- name: Add NuGet Source
run: dotnet nuget add source https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json --name github --username ${{ github.repository_owner }} --password ${{ github.token }} --store-password-in-clear-text
Expand Down
24 changes: 12 additions & 12 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,33 +28,33 @@ jobs:
with:
path: ${{ github.event.repository.name }}

- name: Checkout `worlds`
- name: Checkout `types`
uses: actions/checkout@v4.1.2
with:
repository: simulation-tree/worlds
repository: simulation-tree/types
token: ${{ secrets.PAT }}
path: worlds
path: types

- name: Checkout `types`
- name: Checkout `collections`
uses: actions/checkout@v4.1.2
with:
repository: simulation-tree/types
repository: simulation-tree/collections
token: ${{ secrets.PAT }}
path: types
path: collections

- name: Checkout `unmanaged`
- name: Checkout `worlds`
uses: actions/checkout@v4.1.2
with:
repository: simulation-tree/unmanaged
repository: simulation-tree/worlds
token: ${{ secrets.PAT }}
path: unmanaged
path: worlds

- name: Checkout `collections`
- name: Checkout `unmanaged`
uses: actions/checkout@v4.1.2
with:
repository: simulation-tree/collections
repository: simulation-tree/unmanaged
token: ${{ secrets.PAT }}
path: collections
path: unmanaged

- name: Setup
uses: actions/setup-dotnet@v4
Expand Down
66 changes: 36 additions & 30 deletions core/Simulation.Core.csproj
Original file line number Diff line number Diff line change
@@ -1,35 +1,41 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<IsAotCompatible>True</IsAotCompatible>
<IsTrimmable>True</IsTrimmable>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<Authors>popcron</Authors>
<Company>simulation-tree</Company>
<Description>Logic upon data</Description>
<RepositoryUrl>https://github.com/simulation-tree/simulation</RepositoryUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageTags>ecs</PackageTags>
<Title>Simulation Core</Title>
<RootNamespace>Simulation</RootNamespace>
<PackageId />
<GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<IsAotCompatible>True</IsAotCompatible>
<IsTrimmable>True</IsTrimmable>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<Authors>popcron</Authors>
<Company>simulation-tree</Company>
<Description>Logic upon data</Description>
<RepositoryUrl>https://github.com/simulation-tree/simulation</RepositoryUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageTags>ecs</PackageTags>
<Title>Simulation Core</Title>
<RootNamespace>Simulation</RootNamespace>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<IncludeBuildOutput>false</IncludeBuildOutput>
<OutDir>bin/$(TargetFramework)/$(Configuration)</OutDir>
</PropertyGroup>

<ItemGroup>
<None Include="..\README.md">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>
<ItemGroup>
<None Include="..\README.md">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\collections\source\Collections.csproj" />
<ProjectReference Include="..\..\types\core\Types.Core.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\collections\source\Collections.csproj"/>
<ProjectReference Include="..\..\types\core\Types.Core.csproj"/>
</ItemGroup>

<ItemGroup>
<Content Include="bin/**/*" Pack="true" PackagePath="lib" Visible="false"/>
<Content Include="buildTransitive/**/*" Pack="true" PackagePath="buildTransitive"/>
</ItemGroup>

</Project>
152 changes: 152 additions & 0 deletions core/SystemGroup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;

namespace Simulation
{
/// <summary>
/// A group of systems that all run on a separate foreground thread.
/// </summary>
public sealed class SystemGroup<T> : IDisposable, IListener<T> where T : unmanaged
{
private readonly CancellationTokenSource cts;
private readonly Thread thread;
private IListener<T>[] systems;
private bool disposed;
private volatile int messageVersion;
private volatile bool finishedSignal;
private T message;

int IListener.Count => 1;

/// <summary>
/// Creates a new system group.
/// </summary>
public SystemGroup(ReadOnlySpan<char> threadName)
{
systems = [];
cts = new();
thread = new Thread(Run);
thread.Name = threadName.ToString();
thread.IsBackground = false;
thread.Start();
}

void IListener.CollectMessageHandlers(Span<MessageHandler> messageHandlers)
{
messageHandlers[0] = MessageHandler.Get<IListener<T>, T>(this);
}

private void Run()
{
SpinWait waiter = new();
int lastMessageVersion = 0;
while (true)
{
while (lastMessageVersion == messageVersion && !cts.IsCancellationRequested)
{
waiter.SpinOnce();
}

if (cts.IsCancellationRequested)
{
break;
}

Thread.MemoryBarrier();
T currentMessage = message;
lastMessageVersion = messageVersion;

foreach (IListener<T> system in systems)
{
system.Receive(ref currentMessage);
}

waiter.Reset();
finishedSignal = true;
}
}

/// <summary>
/// Disposes the system group and finishes work on its thread.
/// </summary>
public void Dispose()
{
ThrowIfDisposed();

disposed = true;
cts.Cancel();
if (thread.IsAlive)
{
thread.Join();
}

cts.Dispose();
}

/// <summary>
/// Adds the given <paramref name="system"/> to the group.
/// </summary>
public void Add<S>(S system) where S : IListener<T>
{
ThrowIfDisposed();

Array.Resize(ref systems, systems.Length + 1);
systems[^1] = system;
}

/// <summary>
/// Removes the system of type <typeparamref name="S"/> from the group.
/// </summary>
public void Remove<S>() where S : IListener<T>
{
ThrowIfDisposed();

List<IListener<T>> systemList = new(systems);
for (int i = 0; i < systemList.Count; i++)
{
if (systemList[i] is S system)
{
systemList.RemoveAt(i);
if (system is IDisposable disposable)
{
disposable.Dispose();
}

break;
}
}

systems = systemList.ToArray();
}

/// <summary>
/// Signals the thread to process the given <paramref name="message"/>.
/// </summary>
public void Receive(ref T message)
{
ThrowIfDisposed();

finishedSignal = false;
this.message = message;
Thread.MemoryBarrier();
Interlocked.Increment(ref messageVersion);

SpinWait waiter = new();
while (!finishedSignal)
{
waiter.SpinOnce();
}
}

[Conditional("DEBUG")]
private void ThrowIfDisposed()
{
if (disposed)
{
throw new ObjectDisposedException(nameof(SystemGroup<T>), "This system group has already been disposed");
}
}
}
}
10 changes: 10 additions & 0 deletions core/buildTransitive/Simulation.Core.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<ItemGroup>
<Reference Include="Simulation.Core">
<HintPath>$(MSBuildThisFileDirectory)..\lib\net9.0\$(Configuration)\Simulation.Core.dll</HintPath>
</Reference>
</ItemGroup>

</Project>
Loading