using System;
using System.Collections.Generic;
using System.Linq;
namespace RobotNet10.Realtime;
///
/// Provides CPU affinity management for Linux real-time applications.
///
public class CpuAffinity : IDisposable
{
private LinuxNative.cpu_set_t _cpuSet;
private bool _disposed = false;
///
/// Initializes a new instance of CpuAffinity.
///
public CpuAffinity()
{
LinuxNative.CPU_ZERO(ref _cpuSet);
}
///
/// Adds a CPU to the affinity set.
///
/// CPU number (0-based)
public void AddCpu(int cpu)
{
if (cpu < 0 || cpu >= LinuxNative.CPU_SETSIZE)
{
throw new ArgumentOutOfRangeException(nameof(cpu),
$"CPU number must be between 0 and {LinuxNative.CPU_SETSIZE - 1}");
}
LinuxNative.CPU_SET(cpu, ref _cpuSet);
}
///
/// Removes a CPU from the affinity set.
///
/// CPU number (0-based)
public void RemoveCpu(int cpu)
{
if (cpu < 0 || cpu >= LinuxNative.CPU_SETSIZE)
{
throw new ArgumentOutOfRangeException(nameof(cpu),
$"CPU number must be between 0 and {LinuxNative.CPU_SETSIZE - 1}");
}
LinuxNative.CPU_CLR(cpu, ref _cpuSet);
}
///
/// Checks if a CPU is in the affinity set.
///
/// CPU number (0-based)
/// True if CPU is in the set, false otherwise
public bool IsCpuSet(int cpu)
{
if (cpu < 0 || cpu >= LinuxNative.CPU_SETSIZE)
{
return false;
}
return LinuxNative.CPU_ISSET(cpu, ref _cpuSet) != 0;
}
///
/// Gets the number of CPUs in the affinity set.
///
public int CpuCount => LinuxNative.CPU_COUNT(ref _cpuSet);
///
/// Gets all CPUs in the affinity set.
///
/// List of CPU numbers
public List GetCpus()
{
var cpus = new List();
for (int i = 0; i < LinuxNative.CPU_SETSIZE; i++)
{
if (IsCpuSet(i))
{
cpus.Add(i);
}
}
return cpus;
}
///
/// Sets CPU affinity for the current thread.
///
/// List of CPU numbers to set
public static void SetAffinity(params int[] cpus)
{
var affinity = new CpuAffinity();
foreach (var cpu in cpus)
{
affinity.AddCpu(cpu);
}
affinity.Apply();
}
///
/// Applies the CPU affinity to the current thread.
///
public void Apply()
{
if (_disposed)
{
throw new ObjectDisposedException(nameof(CpuAffinity));
}
IntPtr cpusetsize = new IntPtr(LinuxNative.CPU_SETSIZE / 8); // Size in bytes
int result = LinuxNative.sched_setaffinity(0, cpusetsize, ref _cpuSet);
if (result != 0)
{
LinuxNative.ThrowLastError("sched_setaffinity");
}
}
///
/// Gets the current CPU affinity for the current thread.
///
/// CpuAffinity object representing current affinity
public static CpuAffinity GetAffinity()
{
var cpuSet = new LinuxNative.cpu_set_t();
IntPtr cpusetsize = new IntPtr(LinuxNative.CPU_SETSIZE / 8);
int result = LinuxNative.sched_getaffinity(0, cpusetsize, ref cpuSet);
if (result != 0)
{
LinuxNative.ThrowLastError("sched_getaffinity");
}
var affinity = new CpuAffinity();
affinity._cpuSet = cpuSet;
return affinity;
}
///
/// Clears all CPUs from the affinity set.
///
public void Clear()
{
LinuxNative.CPU_ZERO(ref _cpuSet);
}
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
}
}
}