// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Threading;
using Iot.Device.Arduino;
namespace ArduinoCsCompiler.Runtime
{
[ArduinoReplacement(typeof(System.Threading.Thread), false, IncludingPrivates = true)]
internal class MiniThread
{
#pragma warning disable 414, SA1306
private IntPtr _DONT_USE_InternalThread;
private int _managedThreadId;
private ExecutionContext? _executionContext;
private SynchronizationContext? _synchronizationContext;
private string _name;
#pragma warning restore 414, SA1306
public MiniThread()
{
_executionContext = null;
_DONT_USE_InternalThread = IntPtr.Zero;
_managedThreadId = 0;
_synchronizationContext = null;
_name = string.Empty;
}
/// <summary>
/// This method performs busy waiting for a specified number of milliseconds.
/// It is not implemented as low-level function because this allows other code to continue.
/// That means this does not block other tasks (and particularly the communication) from working.
/// </summary>
/// <param name="delayMs">Number of milliseconds to sleep</param>
[ArduinoImplementation]
public static void Sleep(int delayMs)
{
if (delayMs <= 0)
{
return;
}
int ticks = Environment.TickCount;
int endTicks = ticks + delayMs;
if (ticks > endTicks)
{
// There will be a wraparound
int previous = ticks;
// wait until the tick count wraps around
while (previous < ticks)
{
previous = ticks;
Yield();
ticks = Environment.TickCount;
}
}
while (endTicks > ticks)
{
// Busy waiting is ok here - the microcontroller has no sleep state
Yield();
ticks = Environment.TickCount;
}
}
public static int OptimalMaxSpinWaitsPerSpinIteration
{
[ArduinoImplementation]
get
{
return 1;
}
}
public int ManagedThreadId
{
[ArduinoImplementation]
get
{
return _managedThreadId;
}
}
public bool IsThreadPoolThread
{
// The backend doesn't do much with this field, but if we implement it here,
// we need to add it's backing field to the class, which would require some
// special handling
[ArduinoImplementation("Thread_get_IsThreadPoolThread")]
get;
[ArduinoImplementation("Thread_set_IsThreadPoolThread")]
set;
}
public bool IsBackground
{
// The backend doesn't do much with this field, but if we implement it here,
// we need to add it's backing field to the class, which would require some
// special handling
[ArduinoImplementation("Thread_get_IsBackground")]
get;
[ArduinoImplementation("Thread_set_IsBackground")]
set;
}
[ArduinoImplementation]
public static void Sleep(TimeSpan delay)
{
Sleep((int)delay.TotalMilliseconds);
}
[ArduinoImplementation("ThreadYield")]
public static bool Yield()
{
return false;
}
[ArduinoImplementation]
public static void UninterruptibleSleep0()
{
Yield();
}
[ArduinoImplementation]
public static void SpinWait(int micros)
{
// No op, we're not fast enough
}
[ArduinoImplementation]
public static int GetCurrentProcessorId()
{
return 0;
}
[ArduinoImplementation]
public static int GetCurrentProcessorNumber()
{
return 0;
}
[ArduinoImplementation("ThreadGetCurrentThreadNative")]
public static Thread GetCurrentThreadNative()
{
throw new NotImplementedException();
}
/// <summary>
/// First arg is of type ThreadHandle, but this is a value type over an IntPtr, so their layout is identical
/// </summary>
[ArduinoImplementation("ThreadStartInternal", CompareByParameterNames = true)]
public static unsafe void StartInternal(IntPtr t, int stackSize, int priority, char* pThreadName)
{
throw new NotImplementedException();
}
[ArduinoImplementation]
public static void MemoryBarrier()
{
// Nothing to do here
}
[ArduinoImplementation("ThreadInitialize")]
public void Initialize()
{
throw new NotImplementedException();
}
[ArduinoImplementation("ThreadJoin")]
public bool Join(int millisecondsTimeout)
{
throw new NotImplementedException();
}
[ArduinoImplementation]
public void SetThreadPoolWorkerThreadName()
{
// Nothing to do, really (we don't keep thread names)
}
}
}