mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-16 15:24:10 +02:00
Moving corlib files out of "System" directory into root
This commit is contained in:
parent
4cd58262e4
commit
7dbfd15292
179 changed files with 3 additions and 0 deletions
32
BeefLibs/corlib/src/Threading/CancellationToken.bf
Normal file
32
BeefLibs/corlib/src/Threading/CancellationToken.bf
Normal file
|
@ -0,0 +1,32 @@
|
|||
// This file contains portions of code released by Microsoft under the MIT license as part
|
||||
// of an open-sourcing initiative in 2014 of the C# core libraries.
|
||||
// The original source was submitted to https://github.com/Microsoft/referencesource
|
||||
|
||||
namespace System.Threading
|
||||
{
|
||||
struct CancellationToken
|
||||
{
|
||||
private CancellationTokenSource m_source;
|
||||
|
||||
public static CancellationToken None
|
||||
{
|
||||
get { return default(CancellationToken); }
|
||||
}
|
||||
|
||||
public bool IsCancellationRequested
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_source != null && m_source.IsCancellationRequested;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanBeCanceled
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_source != null && m_source.CanBeCanceled;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
26
BeefLibs/corlib/src/Threading/CancellationTokenSource.bf
Normal file
26
BeefLibs/corlib/src/Threading/CancellationTokenSource.bf
Normal file
|
@ -0,0 +1,26 @@
|
|||
// This file contains portions of code released by Microsoft under the MIT license as part
|
||||
// of an open-sourcing initiative in 2014 of the C# core libraries.
|
||||
// The original source was submitted to https://github.com/Microsoft/referencesource
|
||||
|
||||
namespace System.Threading
|
||||
{
|
||||
class CancellationTokenSource
|
||||
{
|
||||
private const int CANNOT_BE_CANCELED = 0;
|
||||
private const int NOT_CANCELED = 1;
|
||||
private const int NOTIFYING = 2;
|
||||
private const int NOTIFYINGCOMPLETE = 3;
|
||||
|
||||
private volatile int m_state;
|
||||
|
||||
public bool IsCancellationRequested
|
||||
{
|
||||
get { return m_state >= NOTIFYING; }
|
||||
}
|
||||
|
||||
internal bool CanBeCanceled
|
||||
{
|
||||
get { return m_state != CANNOT_BE_CANCELED; }
|
||||
}
|
||||
}
|
||||
}
|
35
BeefLibs/corlib/src/Threading/Event.bf
Normal file
35
BeefLibs/corlib/src/Threading/Event.bf
Normal file
|
@ -0,0 +1,35 @@
|
|||
namespace System.Threading
|
||||
{
|
||||
public class WaitEvent
|
||||
{
|
||||
Platform.BfpEvent* mEvent;
|
||||
|
||||
public this(bool initiallySet = false)
|
||||
{
|
||||
Platform.BfpEventFlags flags = .AllowAutoReset | .AllowManualReset;
|
||||
if (initiallySet)
|
||||
flags |= .InitiallySet_Manual;
|
||||
mEvent = Platform.BfpEvent_Create(flags);
|
||||
}
|
||||
|
||||
public ~this()
|
||||
{
|
||||
Platform.BfpEvent_Release(mEvent);
|
||||
}
|
||||
|
||||
public void Set(bool requireManualReset = false)
|
||||
{
|
||||
Platform.BfpEvent_Set(mEvent, requireManualReset);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Platform.BfpEvent_Reset(mEvent, null);
|
||||
}
|
||||
|
||||
public bool WaitFor(int waitMS = -1)
|
||||
{
|
||||
return Platform.BfpEvent_WaitFor(mEvent, (int32)waitMS);
|
||||
}
|
||||
}
|
||||
}
|
967
BeefLibs/corlib/src/Threading/Interlocked.bf
Normal file
967
BeefLibs/corlib/src/Threading/Interlocked.bf
Normal file
|
@ -0,0 +1,967 @@
|
|||
using System.Diagnostics;
|
||||
|
||||
namespace System.Threading
|
||||
{
|
||||
static class Interlocked
|
||||
{
|
||||
public enum AtomicOrdering : uint8
|
||||
{
|
||||
Unordered,
|
||||
Relaxed,
|
||||
Acquire,
|
||||
Release,
|
||||
AcqRel,
|
||||
SeqCst,
|
||||
ORDERMASK = 7,
|
||||
|
||||
Flag_Volatile = 8,
|
||||
Flag_ReturnModified = 0x10 // Generally atomic instructions return original value, this overrides that
|
||||
}
|
||||
|
||||
public enum RMWAtomicOrdering : uint8
|
||||
{
|
||||
Relaxed = (.)AtomicOrdering.Relaxed,
|
||||
Acquire = (.)AtomicOrdering.Acquire,
|
||||
Release = (.)AtomicOrdering.Release,
|
||||
AcqRel = (.)AtomicOrdering.AcqRel,
|
||||
SeqCst = (.)AtomicOrdering.SeqCst,
|
||||
Flag_Volatile = (.)AtomicOrdering.Flag_Volatile,
|
||||
}
|
||||
|
||||
public enum LoadAtomicOrdering : uint8
|
||||
{
|
||||
Relaxed = (.)AtomicOrdering.Relaxed,
|
||||
Acquire = (.)AtomicOrdering.Acquire,
|
||||
SeqCst = (.)AtomicOrdering.SeqCst,
|
||||
Flag_Volatile = (.)AtomicOrdering.Flag_Volatile,
|
||||
}
|
||||
|
||||
public enum StoreAtomicOrdering : uint8
|
||||
{
|
||||
Relaxed = (.)AtomicOrdering.Relaxed,
|
||||
Release = (.)AtomicOrdering.Release,
|
||||
SeqCst = (.)AtomicOrdering.SeqCst,
|
||||
Flag_Volatile = (.)AtomicOrdering.Flag_Volatile,
|
||||
}
|
||||
|
||||
public enum FenceAtomicOrdering : uint8
|
||||
{
|
||||
Acquire = (.)AtomicOrdering.Acquire,
|
||||
Release = (.)AtomicOrdering.Release,
|
||||
AcqRel = (.)AtomicOrdering.AcqRel,
|
||||
SeqCst = (.)AtomicOrdering.SeqCst
|
||||
}
|
||||
|
||||
[Intrinsic("atomic_fence")]
|
||||
static extern void AtomicFence(AtomicOrdering ordering);
|
||||
[Inline]
|
||||
public static void Fence<TAtomicOrdering>(TAtomicOrdering ordering = .SeqCst) where TAtomicOrdering : const FenceAtomicOrdering
|
||||
{
|
||||
AtomicFence((AtomicOrdering)ordering);
|
||||
}
|
||||
|
||||
[Intrinsic("atomic_fence")]
|
||||
public static extern void CompilerBarrier();
|
||||
|
||||
[Intrinsic("atomic_load")]
|
||||
static extern uint8 Load(ref uint8 location, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_load")]
|
||||
static extern uint16 Load(ref uint16 location, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_load")]
|
||||
public static extern uint32 Load(ref uint32 location, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_load")]
|
||||
static extern uint64 Load(ref uint64 location, AtomicOrdering ordering);
|
||||
[Inline]
|
||||
public static T Load<T, TAtomicOrdering>(ref T location, TAtomicOrdering ordering = .SeqCst) where TAtomicOrdering : const LoadAtomicOrdering
|
||||
{
|
||||
if (sizeof(T) == sizeof(uint8))
|
||||
{
|
||||
var result = Load(ref *(uint8*)&location, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(uint16))
|
||||
{
|
||||
var result = Load(ref *(uint16*)&location, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(uint32))
|
||||
{
|
||||
var result = Load(ref *(uint32*)&location, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(uint64))
|
||||
{
|
||||
var result = Load(ref *(uint64*)&location, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
|
||||
[Intrinsic("atomic_store")]
|
||||
static extern void Store(ref uint8 location, uint8 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_store")]
|
||||
static extern void Store(ref uint16 location, uint16 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_store")]
|
||||
static extern void Store(ref uint32 location, uint32 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_store")]
|
||||
static extern void Store(ref uint64 location, uint64 value, AtomicOrdering ordering);
|
||||
[Inline]
|
||||
public static void Store<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where TAtomicOrdering : const StoreAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(uint8))
|
||||
Store(ref *(uint8*)&location, *(uint8*)&value, (AtomicOrdering)ordering);
|
||||
else if (sizeof(T) == sizeof(uint16))
|
||||
Store(ref *(uint16*)&location, *(uint16*)&value, (AtomicOrdering)ordering);
|
||||
else if (sizeof(T) == sizeof(uint32))
|
||||
Store(ref *(uint32*)&location, *(uint32*)&value, (AtomicOrdering)ordering);
|
||||
else if (sizeof(T) == sizeof(uint64))
|
||||
Store(ref *(uint64*)&location, *(uint64*)&value, (AtomicOrdering)ordering);
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
|
||||
[Intrinsic("atomic_xchg")]
|
||||
extern static uint8 Exchange(ref uint8 location, uint8 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_xchg")]
|
||||
extern static uint16 Exchange(ref uint16 location, uint16 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_xchg")]
|
||||
extern static uint32 Exchange(ref uint32 location, uint32 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_xchg")]
|
||||
extern static uint64 Exchange(ref uint64 location, uint64 value, AtomicOrdering ordering);
|
||||
/// Atomically sets a value and returns the original value.
|
||||
public static T Exchange<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = Exchange(ref *(uint8*)&location, *(uint8*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = Exchange(ref *(uint16*)&location, *(uint16*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = Exchange(ref *(uint32*)&location, *(uint32*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = Exchange(ref *(uint64*)&location, *(uint64*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
|
||||
[Intrinsic("atomic_cmpxchg")]
|
||||
extern static uint8 CompareExchange(ref uint8 location, uint8 comparand, uint8 value, AtomicOrdering successOrdering);
|
||||
[Intrinsic("atomic_cmpxchg")]
|
||||
extern static uint16 CompareExchange(ref uint16 location, uint16 comparand, uint16 value, AtomicOrdering successOrdering);
|
||||
[Intrinsic("atomic_cmpxchg")]
|
||||
extern static uint32 CompareExchange(ref uint32 location, uint32 comparand, uint32 value, AtomicOrdering successOrdering);
|
||||
[Intrinsic("atomic_cmpxchg")]
|
||||
extern static uint64 CompareExchange(ref uint64 location, uint64 comparand, uint64 value, AtomicOrdering successOrdering);
|
||||
/// Compares 'location' to 'comparand' for equality and, if they are equal, replaces 'location' with 'value' and returns the original value in 'location'.
|
||||
/// @param location The destination, whose value is compared with comparand and possibly replaced.
|
||||
/// @param value The value that replaces the destination value if the comparison results in equality.
|
||||
/// @param comparand The value that is compared to the value at location.
|
||||
[Inline]
|
||||
public static T CompareExchange<T, TAtomicOrdering>(ref T location, T comparand, T value, TAtomicOrdering successOrdering = .SeqCst) where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
var comparand;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = CompareExchange(ref *(uint8*)&location, *(uint8*)&comparand, *(uint8*)&value, (AtomicOrdering)successOrdering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = CompareExchange(ref *(uint16*)&location, *(uint16*)&comparand, *(uint16*)&value, (AtomicOrdering)successOrdering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = CompareExchange(ref *(uint32*)&location, *(uint32*)&comparand, *(uint32*)&value, (AtomicOrdering)successOrdering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = CompareExchange(ref *(uint64*)&location, *(uint64*)&comparand, *(uint64*)&value, (AtomicOrdering)successOrdering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
|
||||
[Intrinsic("atomic_cmpxchg")]
|
||||
extern static uint8 CompareExchange(ref uint8 location, uint8 comparand, uint8 value, AtomicOrdering successOrdering, AtomicOrdering failOrdering);
|
||||
[Intrinsic("atomic_cmpxchg")]
|
||||
extern static uint16 CompareExchange(ref uint16 location, uint16 comparand, uint16 value, AtomicOrdering successOrdering, AtomicOrdering failOrdering);
|
||||
[Intrinsic("atomic_cmpxchg")]
|
||||
extern static uint32 CompareExchange(ref uint32 location, uint32 comparand, uint32 value, AtomicOrdering successOrdering, AtomicOrdering failOrdering);
|
||||
[Intrinsic("atomic_cmpxchg")]
|
||||
extern static uint64 CompareExchange(ref uint64 location, uint64 comparand, uint64 value, AtomicOrdering successOrdering, AtomicOrdering failOrdering);
|
||||
/// Compares 'location' to 'comparand' for equality and, if they are equal, replaces 'location' with 'value' and returns the original value in 'location'.
|
||||
/// @param location The destination, whose value is compared with comparand and possibly replaced.
|
||||
/// @param value The value that replaces the destination value if the comparison results in equality.
|
||||
/// @param comparand The value that is compared to the value at location.
|
||||
[Inline]
|
||||
public static T CompareExchange<T, TSuccessOrdering, TFailOrdering>(ref T location, T comparand, T value, TSuccessOrdering successOrdering, TFailOrdering failOrdering)
|
||||
where TSuccessOrdering : const RMWAtomicOrdering
|
||||
where TFailOrdering : const LoadAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
var comparand;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = CompareExchange(ref *(uint8*)&location, *(uint8*)&comparand, *(uint8*)&value, (AtomicOrdering)successOrdering, (AtomicOrdering)failOrdering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = CompareExchange(ref *(uint16*)&location, *(uint16*)&comparand, *(uint16*)&value, (AtomicOrdering)successOrdering, (AtomicOrdering)failOrdering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = CompareExchange(ref *(uint32*)&location, *(uint32*)&comparand, *(uint32*)&value, (AtomicOrdering)successOrdering, (AtomicOrdering)failOrdering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = CompareExchange(ref *(uint64*)&location, *(uint64*)&comparand, *(uint64*)&value, (AtomicOrdering)successOrdering, (AtomicOrdering)failOrdering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
|
||||
[Intrinsic("atomic_cmpstore")]
|
||||
extern static bool CompareStore(ref uint8 location, uint8 comparand, uint8 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_cmpstore")]
|
||||
extern static bool CompareStore(ref uint16 location, uint16 comparand, uint16 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_cmpstore")]
|
||||
extern static bool CompareStore(ref uint32 location, uint32 comparand, uint32 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_cmpstore")]
|
||||
extern static bool CompareStore(ref uint64 location, uint64 comparand, uint64 value, AtomicOrdering ordering);
|
||||
/// Compares 'location' to 'comparand' for equality and, if they are equal, replaces 'location' with 'value' and returns the original value in 'location'.
|
||||
/// @param location The destination, whose value is compared with comparand and possibly replaced.
|
||||
/// @param value The value that replaces the destination value if the comparison results in equality.
|
||||
/// @param comparand The value that is compared to the value at location.
|
||||
[Inline]
|
||||
public static bool CompareStore<T, TAtomicOrdering>(ref T location, T comparand, T value, TAtomicOrdering ordering = .SeqCst) where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
var comparand;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
return CompareStore(ref *(uint8*)&location, *(uint8*)&comparand, *(uint8*)&value, (AtomicOrdering)ordering);
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
return CompareStore(ref *(uint16*)&location, *(uint16*)&comparand, *(uint16*)&value, (AtomicOrdering)ordering);
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
return CompareStore(ref *(uint32*)&location, *(uint32*)&comparand, *(uint32*)&value, (AtomicOrdering)ordering);
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
return CompareStore(ref *(uint64*)&location, *(uint64*)&comparand, *(uint64*)&value, (AtomicOrdering)ordering);
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
|
||||
[Intrinsic("atomic_cmpstore_weak")]
|
||||
extern static bool CompareStoreWeak(ref uint8 location, uint8 comparand, uint8 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_cmpstore_weak")]
|
||||
extern static bool CompareStoreWeak(ref uint16 location, uint16 comparand, uint16 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_cmpstore_weak")]
|
||||
extern static bool CompareStoreWeak(ref uint32 location, uint32 comparand, uint32 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_cmpstore_weak")]
|
||||
extern static bool CompareStoreWeak(ref uint64 location, uint64 comparand, uint64 value, AtomicOrdering ordering);
|
||||
/// Compares 'location' to 'comparand' for equality and, if they are equal, replaces 'location' with 'value' and returns the original value in 'location'.
|
||||
/// @param location The destination, whose value is compared with comparand and possibly replaced.
|
||||
/// @param value The value that replaces the destination value if the comparison results in equality.
|
||||
/// @param comparand The value that is compared to the value at location.
|
||||
[Inline]
|
||||
public static bool CompareStoreWeak<T, TAtomicOrdering>(ref T location, T comparand, T value, TAtomicOrdering ordering = .SeqCst) where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
var comparand;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
return CompareStoreWeak(ref *(uint8*)&location, *(uint8*)&comparand, *(uint8*)&value, (AtomicOrdering)ordering);
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
return CompareStoreWeak(ref *(uint16*)&location, *(uint16*)&comparand, *(uint16*)&value, (AtomicOrdering)ordering);
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
return CompareStoreWeak(ref *(uint32*)&location, *(uint32*)&comparand, *(uint32*)&value, (AtomicOrdering)ordering);
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
return CompareStoreWeak(ref *(uint64*)&location, *(uint64*)&comparand, *(uint64*)&value, (AtomicOrdering)ordering);
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
|
||||
//////
|
||||
|
||||
[Intrinsic("atomic_add")]
|
||||
extern static float Add(ref float location, float value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_add")]
|
||||
extern static double Add(ref double location, double value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_add")]
|
||||
extern static uint8 Add(ref uint8 location, uint8 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_add")]
|
||||
extern static uint16 Add(ref uint16 location, uint16 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_add")]
|
||||
extern static uint32 Add(ref uint32 location, uint32 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_add")]
|
||||
extern static uint64 Add(ref uint64 location, uint64 value, AtomicOrdering ordering);
|
||||
[Inline]
|
||||
public static T Add<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IInteger where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = Add(ref *(uint8*)&location, *(uint8*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = Add(ref *(uint16*)&location, *(uint16*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = Add(ref *(uint32*)&location, *(uint32*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = Add(ref *(uint64*)&location, *(uint64*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
[Inline]
|
||||
public static T Add<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IFloating where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(float))
|
||||
{
|
||||
var result = Add(ref *(float*)&location, *(float*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(double))
|
||||
{
|
||||
var result = Add(ref *(double*)&location, *(double*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
[Inline]
|
||||
public static T ExchangeAdd<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IInteger where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = Add(ref *(uint8*)&location, *(uint8*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = Add(ref *(uint16*)&location, *(uint16*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = Add(ref *(uint32*)&location, *(uint32*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = Add(ref *(uint64*)&location, *(uint64*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
[Inline]
|
||||
public static T ExchangeAdd<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IFloating where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(float))
|
||||
{
|
||||
var result = Add(ref *(float*)&location, *(float*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(double))
|
||||
{
|
||||
var result = Add(ref *(double*)&location, *(double*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
[Inline]
|
||||
public static T Increment<T, TAtomicOrdering>(ref T location, TAtomicOrdering ordering = .SeqCst) where T : IInteger where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = Add(ref *(uint8*)&location, 1, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = Add(ref *(uint16*)&location, 1, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = Add(ref *(uint32*)&location, 1, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = Add(ref *(uint64*)&location, 1, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
|
||||
[Intrinsic("atomic_and")]
|
||||
extern static float And(ref float location, float value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_and")]
|
||||
extern static double And(ref double location, double value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_and")]
|
||||
extern static uint8 And(ref uint8 location, uint8 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_and")]
|
||||
extern static uint16 And(ref uint16 location, uint16 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_and")]
|
||||
extern static uint32 And(ref uint32 location, uint32 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_and")]
|
||||
extern static uint64 And(ref uint64 location, uint64 value, AtomicOrdering ordering);
|
||||
[Inline]
|
||||
public static T And<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IInteger where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = And(ref *(uint8*)&location, *(uint8*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = And(ref *(uint16*)&location, *(uint16*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = And(ref *(uint32*)&location, *(uint32*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = And(ref *(uint64*)&location, *(uint64*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
[Inline]
|
||||
public static T ExchangeAnd<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IInteger where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = And(ref *(uint8*)&location, *(uint8*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = And(ref *(uint16*)&location, *(uint16*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = And(ref *(uint32*)&location, *(uint32*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = And(ref *(uint64*)&location, *(uint64*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
|
||||
[Intrinsic("atomic_max")]
|
||||
extern static float Max(ref float location, float value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_max")]
|
||||
extern static double Max(ref double location, double value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_max")]
|
||||
extern static uint8 Max(ref uint8 location, uint8 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_max")]
|
||||
extern static uint16 Max(ref uint16 location, uint16 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_max")]
|
||||
extern static uint32 Max(ref uint32 location, uint32 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_max")]
|
||||
extern static uint64 Max(ref uint64 location, uint64 value, AtomicOrdering ordering);
|
||||
[Inline]
|
||||
public static T Max<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IInteger where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = Max(ref *(uint8*)&location, *(uint8*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = Max(ref *(uint16*)&location, *(uint16*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = Max(ref *(uint32*)&location, *(uint32*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = Max(ref *(uint64*)&location, *(uint64*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
[Inline]
|
||||
public static T ExchangeMax<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IInteger where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = Max(ref *(uint8*)&location, *(uint8*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = Max(ref *(uint16*)&location, *(uint16*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = Max(ref *(uint32*)&location, *(uint32*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = Max(ref *(uint64*)&location, *(uint64*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
|
||||
[Intrinsic("atomic_min")]
|
||||
extern static float Min(ref float location, float value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_min")]
|
||||
extern static double Min(ref double location, double value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_min")]
|
||||
extern static uint8 Min(ref uint8 location, uint8 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_min")]
|
||||
extern static uint16 Min(ref uint16 location, uint16 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_min")]
|
||||
extern static uint32 Min(ref uint32 location, uint32 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_min")]
|
||||
extern static uint64 Min(ref uint64 location, uint64 value, AtomicOrdering ordering);
|
||||
[Inline]
|
||||
public static T Min<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IInteger where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = Min(ref *(uint8*)&location, *(uint8*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = Min(ref *(uint16*)&location, *(uint16*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = Min(ref *(uint32*)&location, *(uint32*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = Min(ref *(uint64*)&location, *(uint64*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
[Inline]
|
||||
public static T ExchangeMin<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IInteger where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = Min(ref *(uint8*)&location, *(uint8*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = Min(ref *(uint16*)&location, *(uint16*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = Min(ref *(uint32*)&location, *(uint32*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = Min(ref *(uint64*)&location, *(uint64*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
|
||||
[Intrinsic("atomic_nand")]
|
||||
extern static float Nand(ref float location, float value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_nand")]
|
||||
extern static double Nand(ref double location, double value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_nand")]
|
||||
extern static uint8 Nand(ref uint8 location, uint8 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_nand")]
|
||||
extern static uint16 Nand(ref uint16 location, uint16 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_nand")]
|
||||
extern static uint32 Nand(ref uint32 location, uint32 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_nand")]
|
||||
extern static uint64 Nand(ref uint64 location, uint64 value, AtomicOrdering ordering);
|
||||
[Inline]
|
||||
public static T Nand<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IInteger where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = Nand(ref *(uint8*)&location, *(uint8*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = Nand(ref *(uint16*)&location, *(uint16*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = Nand(ref *(uint32*)&location, *(uint32*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = Nand(ref *(uint64*)&location, *(uint64*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
[Inline]
|
||||
public static T ExchangeNand<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IInteger where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = Nand(ref *(uint8*)&location, *(uint8*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = Nand(ref *(uint16*)&location, *(uint16*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = Nand(ref *(uint32*)&location, *(uint32*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = Nand(ref *(uint64*)&location, *(uint64*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
|
||||
[Intrinsic("atomic_or")]
|
||||
extern static float Or(ref float location, float value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_or")]
|
||||
extern static double Or(ref double location, double value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_or")]
|
||||
extern static uint8 Or(ref uint8 location, uint8 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_or")]
|
||||
extern static uint16 Or(ref uint16 location, uint16 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_or")]
|
||||
extern static uint32 Or(ref uint32 location, uint32 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_or")]
|
||||
extern static uint64 Or(ref uint64 location, uint64 value, AtomicOrdering ordering);
|
||||
[Inline]
|
||||
public static T Or<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IInteger where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = Or(ref *(uint8*)&location, *(uint8*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = Or(ref *(uint16*)&location, *(uint16*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = Or(ref *(uint32*)&location, *(uint32*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = Or(ref *(uint64*)&location, *(uint64*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
[Inline]
|
||||
public static T ExchangeOr<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IInteger where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = Or(ref *(uint8*)&location, *(uint8*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = Or(ref *(uint16*)&location, *(uint16*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = Or(ref *(uint32*)&location, *(uint32*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = Or(ref *(uint64*)&location, *(uint64*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
|
||||
[Intrinsic("atomic_sub")]
|
||||
extern static float Sub(ref float location, float value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_sub")]
|
||||
extern static double Sub(ref double location, double value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_sub")]
|
||||
extern static uint8 Sub(ref uint8 location, uint8 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_sub")]
|
||||
extern static uint16 Sub(ref uint16 location, uint16 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_sub")]
|
||||
extern static uint32 Sub(ref uint32 location, uint32 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_sub")]
|
||||
extern static uint64 Sub(ref uint64 location, uint64 value, AtomicOrdering ordering);
|
||||
[Inline]
|
||||
public static T Sub<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IInteger where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = Sub(ref *(uint8*)&location, *(uint8*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = Sub(ref *(uint16*)&location, *(uint16*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = Sub(ref *(uint32*)&location, *(uint32*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = Sub(ref *(uint64*)&location, *(uint64*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
[Inline]
|
||||
public static T Sub<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IFloating where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(float))
|
||||
{
|
||||
var result = Sub(ref *(float*)&location, *(float*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(double))
|
||||
{
|
||||
var result = Sub(ref *(double*)&location, *(double*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
[Inline]
|
||||
public static T ExchangeSub<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IInteger where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = Sub(ref *(uint8*)&location, *(uint8*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = Sub(ref *(uint16*)&location, *(uint16*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = Sub(ref *(uint32*)&location, *(uint32*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = Sub(ref *(uint64*)&location, *(uint64*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
[Inline]
|
||||
public static T ExchangeSub<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IFloating where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(float))
|
||||
{
|
||||
var result = Sub(ref *(float*)&location, *(float*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(double))
|
||||
{
|
||||
var result = Sub(ref *(double*)&location, *(double*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
[Inline]
|
||||
public static T Decrement<T, TAtomicOrdering>(ref T location, TAtomicOrdering ordering = .SeqCst) where T : IInteger where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = Sub(ref *(uint8*)&location, 1, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = Sub(ref *(uint16*)&location, 1, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = Sub(ref *(uint32*)&location, 1, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = Sub(ref *(uint64*)&location, 1, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
|
||||
[Intrinsic("atomic_xor")]
|
||||
extern static float Xor(ref float location, float value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_xor")]
|
||||
extern static double Xor(ref double location, double value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_xor")]
|
||||
extern static uint8 Xor(ref uint8 location, uint8 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_xor")]
|
||||
extern static uint16 Xor(ref uint16 location, uint16 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_xor")]
|
||||
extern static uint32 Xor(ref uint32 location, uint32 value, AtomicOrdering ordering);
|
||||
[Intrinsic("atomic_xor")]
|
||||
extern static uint64 Xor(ref uint64 location, uint64 value, AtomicOrdering ordering);
|
||||
[Inline]
|
||||
public static T Xor<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IInteger where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = Xor(ref *(uint8*)&location, *(uint8*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = Xor(ref *(uint16*)&location, *(uint16*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = Xor(ref *(uint32*)&location, *(uint32*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = Xor(ref *(uint64*)&location, *(uint64*)&value, (AtomicOrdering)ordering | .Flag_ReturnModified);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
[Inline]
|
||||
public static T ExchangeXor<T, TAtomicOrdering>(ref T location, T value, TAtomicOrdering ordering = .SeqCst) where T : IInteger where TAtomicOrdering : const RMWAtomicOrdering
|
||||
{
|
||||
var value;
|
||||
if (sizeof(T) == sizeof(int8))
|
||||
{
|
||||
var result = Xor(ref *(uint8*)&location, *(uint8*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int16))
|
||||
{
|
||||
var result = Xor(ref *(uint16*)&location, *(uint16*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int32))
|
||||
{
|
||||
var result = Xor(ref *(uint32*)&location, *(uint32*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
var result = Xor(ref *(uint64*)&location, *(uint64*)&value, (AtomicOrdering)ordering);
|
||||
return *(T*)&result;
|
||||
}
|
||||
else
|
||||
FailOnDataSize();
|
||||
}
|
||||
|
||||
[NoReturn]
|
||||
static void FailOnDataSize()
|
||||
{
|
||||
Runtime.FatalError("Data size not supported");
|
||||
}
|
||||
}
|
||||
}
|
76
BeefLibs/corlib/src/Threading/Monitor.bf
Normal file
76
BeefLibs/corlib/src/Threading/Monitor.bf
Normal file
|
@ -0,0 +1,76 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace System.Threading
|
||||
{
|
||||
public class Monitor
|
||||
{
|
||||
public struct MonitorLockInstance
|
||||
{
|
||||
public Monitor mMonitor;
|
||||
public void Dispose()
|
||||
{
|
||||
mMonitor.Exit();
|
||||
}
|
||||
}
|
||||
|
||||
Platform.BfpCritSect* mCritSect;
|
||||
|
||||
public this()
|
||||
{
|
||||
mCritSect = Platform.BfpCritSect_Create();
|
||||
}
|
||||
|
||||
public ~this()
|
||||
{
|
||||
Platform.BfpCritSect_Release(mCritSect);
|
||||
}
|
||||
|
||||
/// Acquires the monitor lock. Will block if another thread holds the lock.
|
||||
///
|
||||
/// Multiple calls to Enter can be issued, and an equivalent number of Exits
|
||||
/// must be issued to allow another thread to enter.
|
||||
public MonitorLockInstance Enter()
|
||||
{
|
||||
MonitorLockInstance monitorLockInstance;
|
||||
monitorLockInstance.mMonitor = this;
|
||||
Platform.BfpCritSect_Enter(mCritSect);
|
||||
return monitorLockInstance;
|
||||
}
|
||||
|
||||
/// Releases the monitor lock.
|
||||
///
|
||||
/// Other threads will be able to enter the monitor unless this thread has issued
|
||||
/// multiple Enters which have not all be Exited.
|
||||
public void Exit()
|
||||
{
|
||||
Platform.BfpCritSect_Leave(mCritSect);
|
||||
}
|
||||
|
||||
/// Attempt to enter the monitor without waiting.
|
||||
/// @return true if the monitor was entered
|
||||
public bool TryEnter()
|
||||
{
|
||||
return Platform.BfpCritSect_TryEnter(mCritSect, 0);
|
||||
}
|
||||
|
||||
/// Blocks up to a timeout, or if millisecondsTimeout is -1, will wait forever.
|
||||
/// @return true if the monitor was entered
|
||||
public bool TryEnter(int millisecondsTimeout)
|
||||
{
|
||||
return Platform.BfpCritSect_TryEnter(mCritSect, (int32)millisecondsTimeout);
|
||||
}
|
||||
|
||||
private static int32 MillisecondsTimeoutFromTimeSpan(TimeSpan timeout)
|
||||
{
|
||||
int64 tm = int64(timeout.TotalMilliseconds);
|
||||
Debug.Assert((uint64)tm <= Int32.MaxValue);
|
||||
return int32(tm);
|
||||
}
|
||||
|
||||
public bool TryEnter(TimeSpan timeout)
|
||||
{
|
||||
return TryEnter(MillisecondsTimeoutFromTimeSpan(timeout));
|
||||
}
|
||||
}
|
||||
}
|
10
BeefLibs/corlib/src/Threading/SemaphoreSlim.bf
Normal file
10
BeefLibs/corlib/src/Threading/SemaphoreSlim.bf
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace System.Threading
|
||||
{
|
||||
class SemaphoreSlim
|
||||
{
|
||||
public void Release()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
26
BeefLibs/corlib/src/Threading/SpinWait.bf
Normal file
26
BeefLibs/corlib/src/Threading/SpinWait.bf
Normal file
|
@ -0,0 +1,26 @@
|
|||
namespace System.Threading
|
||||
{
|
||||
struct SpinWait
|
||||
{
|
||||
internal const int YIELD_THRESHOLD = 10; // When to switch over to a true yield.
|
||||
internal const int SLEEP_0_EVERY_HOW_MANY_TIMES = 5; // After how many yields should we Sleep(0)?
|
||||
internal const int SLEEP_1_EVERY_HOW_MANY_TIMES = 20; // After how many yields should we Sleep(1)?
|
||||
|
||||
private int m_count;
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return m_count; }
|
||||
}
|
||||
|
||||
public void SpinOnce() mut
|
||||
{
|
||||
//TODO: Implement
|
||||
}
|
||||
|
||||
public void Reset() mut
|
||||
{
|
||||
m_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
143
BeefLibs/corlib/src/Threading/Tasks/Future.bf
Normal file
143
BeefLibs/corlib/src/Threading/Tasks/Future.bf
Normal file
|
@ -0,0 +1,143 @@
|
|||
// This file contains portions of code released by Microsoft under the MIT license as part
|
||||
// of an open-sourcing initiative in 2014 of the C# core libraries.
|
||||
// The original source was submitted to https://github.com/Microsoft/referencesource
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace System.Threading.Tasks
|
||||
{
|
||||
public class Task<TResult> : Task
|
||||
{
|
||||
internal TResult m_result; // The value itself, if set.
|
||||
protected bool mHasCompleted;
|
||||
protected int32 mRefCount = 1;
|
||||
|
||||
internal TResult ResultOnSuccess
|
||||
{
|
||||
get
|
||||
{
|
||||
//Contract.Assert(!IsWaitNotificationEnabledOrNotRanToCompletion, "Should only be used when the task completed successfully and there's no wait notification enabled");
|
||||
return m_result;
|
||||
}
|
||||
}
|
||||
|
||||
public TResult Result
|
||||
{
|
||||
get { return IsWaitNotificationEnabledOrNotRanToCompletion ? GetResultCore(true) : m_result; }
|
||||
}
|
||||
|
||||
public this(Func<Object, TResult> func, Object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
|
||||
: this(func, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken,
|
||||
creationOptions, InternalTaskOptions.None, null)
|
||||
{
|
||||
//StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
|
||||
//PossiblyCaptureContext(ref stackMark);
|
||||
}
|
||||
|
||||
internal this(Func<TResult> valueSelector, Task parent, CancellationToken cancellationToken,
|
||||
TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) :
|
||||
base(valueSelector, null, parent, cancellationToken, creationOptions, internalOptions, scheduler)
|
||||
{
|
||||
if ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
|
||||
{
|
||||
Runtime.FatalError();
|
||||
}
|
||||
}
|
||||
|
||||
internal this(Delegate valueSelector, Object state, Task parent, CancellationToken cancellationToken,
|
||||
TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) :
|
||||
base(valueSelector, state, parent, cancellationToken, creationOptions, internalOptions, scheduler)
|
||||
{
|
||||
if ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
|
||||
{
|
||||
Runtime.FatalError();
|
||||
}
|
||||
}
|
||||
|
||||
public new TaskAwaiter<TResult> GetAwaiter()
|
||||
{
|
||||
return TaskAwaiter<TResult>(this);
|
||||
}
|
||||
|
||||
public void Ref()
|
||||
{
|
||||
//Interlocked.Increment(ref mRefCount);
|
||||
mRefCount++;
|
||||
}
|
||||
|
||||
public void Deref()
|
||||
{
|
||||
//if (Interlocked.Decrement(ref mRefCount) == 1)
|
||||
|
||||
if (--mRefCount == 0)
|
||||
delete this;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Deref();
|
||||
}
|
||||
|
||||
// Implements Result. Result delegates to this method if the result isn't already available.
|
||||
internal TResult GetResultCore(bool waitCompletionNotification)
|
||||
{
|
||||
// If the result has not been calculated yet, wait for it.
|
||||
if (!IsCompleted) InternalWait(Timeout.Infinite, default(CancellationToken)); // won't throw if task faulted or canceled; that's handled below
|
||||
|
||||
// Notify the debugger of the wait completion if it's requested such a notification
|
||||
//TODO: Implement
|
||||
//if (waitCompletionNotification) NotifyDebuggerOfWaitCompletionIfNecessary();
|
||||
|
||||
// Throw an exception if appropriate.
|
||||
//TODO: ? if (!IsRanToCompletion) ThrowIfExceptional(true);
|
||||
|
||||
// We shouldn't be here if the result has not been set.
|
||||
//Contract.Assert(IsRanToCompletion, "Task<T>.Result getter: Expected result to have been set.");
|
||||
|
||||
return m_result;
|
||||
}
|
||||
|
||||
List<Action<Task<TResult>>> mContinuations = new List<Action<Task<TResult>>>() ~ delete _;
|
||||
|
||||
public Task ContinueWith(Action<Task<TResult>> continuationAction)
|
||||
{
|
||||
bool callDirectly = false;
|
||||
using (mMonitor.Enter())
|
||||
{
|
||||
if (!mHasCompleted)
|
||||
mContinuations.Add(continuationAction);
|
||||
else
|
||||
callDirectly = true;
|
||||
}
|
||||
if (callDirectly)
|
||||
{
|
||||
// The task has already completed, call directly
|
||||
Ref();
|
||||
continuationAction(this);
|
||||
Deref();
|
||||
}
|
||||
return null;
|
||||
//TODO: Not correct implementation
|
||||
//StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
|
||||
//return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
|
||||
}
|
||||
|
||||
public void Notify(bool allowDelete = true)
|
||||
{
|
||||
var continueList = scope List<Action<Task<TResult>>>(16);
|
||||
using (mMonitor.Enter())
|
||||
{
|
||||
mHasCompleted = true;
|
||||
for (var action in mContinuations)
|
||||
continueList.Add(action);
|
||||
}
|
||||
|
||||
Ref();
|
||||
for (var action in continueList)
|
||||
action(this);
|
||||
Deref();
|
||||
}
|
||||
}
|
||||
}
|
1405
BeefLibs/corlib/src/Threading/Tasks/Task.bf
Normal file
1405
BeefLibs/corlib/src/Threading/Tasks/Task.bf
Normal file
File diff suppressed because it is too large
Load diff
108
BeefLibs/corlib/src/Threading/Tasks/TaskScheduler.bf
Normal file
108
BeefLibs/corlib/src/Threading/Tasks/TaskScheduler.bf
Normal file
|
@ -0,0 +1,108 @@
|
|||
// This file contains portions of code released by Microsoft under the MIT license as part
|
||||
// of an open-sourcing initiative in 2014 of the C# core libraries.
|
||||
// The original source was submitted to https://github.com/Microsoft/referencesource
|
||||
|
||||
namespace System.Threading.Tasks
|
||||
{
|
||||
abstract class TaskScheduler
|
||||
{
|
||||
private static readonly TaskScheduler s_defaultTaskScheduler = new ThreadPoolTaskScheduler() ~ delete _;
|
||||
|
||||
public static TaskScheduler Default
|
||||
{
|
||||
get
|
||||
{
|
||||
return s_defaultTaskScheduler;
|
||||
}
|
||||
}
|
||||
|
||||
public static TaskScheduler Current
|
||||
{
|
||||
get
|
||||
{
|
||||
TaskScheduler current = InternalCurrent;
|
||||
return current ?? TaskScheduler.Default;
|
||||
}
|
||||
}
|
||||
|
||||
internal static TaskScheduler InternalCurrent
|
||||
{
|
||||
get
|
||||
{
|
||||
Task currentTask = Task.InternalCurrent;
|
||||
return ( (currentTask != null)
|
||||
&& ((currentTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0)
|
||||
) ? currentTask.ExecutingTaskScheduler : null;
|
||||
}
|
||||
}
|
||||
|
||||
protected internal abstract void QueueTask(Task task);
|
||||
protected abstract bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the scheduler that a work item has made progress.
|
||||
/// </summary>
|
||||
internal virtual void NotifyWorkItemProgress()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
internal bool TryRunInline(Task task, bool taskWasPreviouslyQueued)
|
||||
{
|
||||
TaskScheduler ets = task.ExecutingTaskScheduler;
|
||||
|
||||
// Delegate cross-scheduler inlining requests to target scheduler
|
||||
if(ets != this && ets !=null) return ets.TryRunInline(task, taskWasPreviouslyQueued);
|
||||
|
||||
//StackGuard currentStackGuard;
|
||||
if( (ets == null) ||
|
||||
(task.m_action == null) ||
|
||||
task.IsDelegateInvoked ||
|
||||
task.IsCanceled
|
||||
//|| (currentStackGuard = Task.CurrentStackGuard).TryBeginInliningScope() == false
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Task class will still call into TaskScheduler.TryRunInline rather than TryExecuteTaskInline() so that
|
||||
// 1) we can adjust the return code from TryExecuteTaskInline in case a buggy custom scheduler lies to us
|
||||
// 2) we maintain a mechanism for the TLS lookup optimization that we used to have for the ConcRT scheduler (will potentially introduce the same for TP)
|
||||
bool bInlined = false;
|
||||
//try
|
||||
{
|
||||
task.FireTaskScheduledIfNeeded(this);
|
||||
bInlined = TryExecuteTaskInline(task, taskWasPreviouslyQueued);
|
||||
}
|
||||
/*finally
|
||||
{
|
||||
currentStackGuard.EndInliningScope();
|
||||
}*/
|
||||
|
||||
// If the custom scheduler returned true, we should either have the TASK_STATE_DELEGATE_INVOKED or TASK_STATE_CANCELED bit set
|
||||
// Otherwise the scheduler is buggy
|
||||
/*if (bInlined && !(task.IsDelegateInvoked || task.IsCanceled))
|
||||
{
|
||||
throw new InvalidOperationException(Environment.GetResourceString("TaskScheduler_InconsistentStateAfterTryExecuteTaskInline"));
|
||||
}*/
|
||||
|
||||
return bInlined;
|
||||
}
|
||||
|
||||
internal void InternalQueueTask(Task task)
|
||||
{
|
||||
//task.FireTaskScheduledIfNeeded(this);
|
||||
this.QueueTask(task);
|
||||
}
|
||||
|
||||
protected internal virtual bool TryDequeue(Task task)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
internal virtual bool RequiresAtomicStartTransition
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
}
|
||||
}
|
107
BeefLibs/corlib/src/Threading/Tasks/ThreadPoolTaskScheduler.bf
Normal file
107
BeefLibs/corlib/src/Threading/Tasks/ThreadPoolTaskScheduler.bf
Normal file
|
@ -0,0 +1,107 @@
|
|||
// This file contains portions of code released by Microsoft under the MIT license as part
|
||||
// of an open-sourcing initiative in 2014 of the C# core libraries.
|
||||
// The original source was submitted to https://github.com/Microsoft/referencesource
|
||||
|
||||
namespace System.Threading.Tasks
|
||||
{
|
||||
class ThreadPoolTaskScheduler : TaskScheduler
|
||||
{
|
||||
/// Constructs a new ThreadPool task scheduler object
|
||||
internal this()
|
||||
{
|
||||
}
|
||||
|
||||
// static delegate for threads allocated to handle LongRunning tasks.
|
||||
//private static readonly ParameterizedThreadStart s_longRunningThreadWork = new => LongRunningThreadWork;
|
||||
|
||||
private static void LongRunningThreadWork(Object obj)
|
||||
{
|
||||
//Contract.Requires(obj != null, "TaskScheduler.LongRunningThreadWork: obj is null");
|
||||
Task t = obj as Task;
|
||||
//Contract.Assert(t != null, "TaskScheduler.LongRunningThreadWork: t is null");
|
||||
t.ExecuteEntry(false);
|
||||
}
|
||||
|
||||
/// Schedules a task to the ThreadPool.
|
||||
/// @param task The task to schedule.
|
||||
protected internal override void QueueTask(Task task)
|
||||
{
|
||||
if ((task.Options & TaskCreationOptions.LongRunning) != 0)
|
||||
{
|
||||
// Run LongRunning tasks on their own dedicated thread.
|
||||
Thread thread = new Thread(new => LongRunningThreadWork);
|
||||
thread.IsBackground = true; // Keep this thread from blocking process shutdown
|
||||
thread.Start(task);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal handling for non-LongRunning tasks.
|
||||
//bool forceToGlobalQueue = ((task.Options & TaskCreationOptions.PreferFairness) != 0);
|
||||
ThreadPool.QueueUserWorkItem(task);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// This internal function will do this:
|
||||
/// (1) If the task had previously been queued, attempt to pop it and return false if that fails.
|
||||
/// (2) Propagate the return value from Task.ExecuteEntry() back to the caller.
|
||||
///
|
||||
/// IMPORTANT NOTE: TryExecuteTaskInline will NOT throw task exceptions itself. Any wait code path using this function needs
|
||||
/// to account for exceptions that need to be propagated, and throw themselves accordingly.
|
||||
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
|
||||
{
|
||||
// If the task was previously scheduled, and we can't pop it, then return false.
|
||||
if (taskWasPreviouslyQueued && !ThreadPool.TryPopCustomWorkItem(task))
|
||||
return false;
|
||||
|
||||
// Propagate the return value of Task.ExecuteEntry()
|
||||
bool rval = false;
|
||||
//try
|
||||
{
|
||||
rval = task.ExecuteEntry(false); // handles switching Task.Current etc.
|
||||
}
|
||||
/*finally
|
||||
{
|
||||
// Only call NWIP() if task was previously queued
|
||||
if(taskWasPreviouslyQueued) NotifyWorkItemProgress();
|
||||
}*/
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
protected internal override bool TryDequeue(Task task)
|
||||
{
|
||||
// just delegate to TP
|
||||
return ThreadPool.TryPopCustomWorkItem(task);
|
||||
}
|
||||
|
||||
/*protected override IEnumerable<Task> GetScheduledTasks()
|
||||
{
|
||||
return FilterTasksFromWorkItems(ThreadPool.GetQueuedWorkItems());
|
||||
}
|
||||
|
||||
private IEnumerable<Task> FilterTasksFromWorkItems(IEnumerable<IThreadPoolWorkItem> tpwItems)
|
||||
{
|
||||
for (IThreadPoolWorkItem tpwi in tpwItems)
|
||||
{
|
||||
if (tpwi is Task)
|
||||
{
|
||||
yield return (Task)tpwi;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/// Notifies the scheduler that work is progressing (no-op).
|
||||
internal override void NotifyWorkItemProgress()
|
||||
{
|
||||
//ThreadPool.NotifyWorkItemProgress();
|
||||
}
|
||||
|
||||
/// This is the only scheduler that returns false for this property, indicating that the task entry codepath is unsafe (CAS free)
|
||||
/// since we know that the underlying scheduler already takes care of atomic transitions from queued to non-queued.
|
||||
internal override bool RequiresAtomicStartTransition
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
}
|
||||
}
|
364
BeefLibs/corlib/src/Threading/Thread.bf
Normal file
364
BeefLibs/corlib/src/Threading/Thread.bf
Normal file
|
@ -0,0 +1,364 @@
|
|||
namespace System.Threading
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
internal delegate Object InternalCrossContextDelegate(Object[] args);
|
||||
|
||||
public delegate void ThreadStart();
|
||||
public delegate void ParameterizedThreadStart(Object obj);
|
||||
|
||||
public sealed class Thread
|
||||
{
|
||||
private int mInternalThread;
|
||||
private int32 mPriority;
|
||||
public int32 mMaxStackSize;
|
||||
private String mName ~ delete _;
|
||||
private Delegate mDelegate;
|
||||
|
||||
private Object mThreadStartArg;
|
||||
|
||||
bool mAutoDelete;
|
||||
public static Thread sMainThread = new Thread() ~ delete _;
|
||||
|
||||
[StaticInitPriority(101)]
|
||||
struct RuntimeThreadInit
|
||||
{
|
||||
static Object Thread_Alloc()
|
||||
{
|
||||
return Thread.[Friend]CreateEmptyThread();
|
||||
}
|
||||
|
||||
static Object Thread_GetMainThread()
|
||||
{
|
||||
return Thread.[Friend]sMainThread;
|
||||
}
|
||||
|
||||
static void* Thread_GetInternalThread(Object thread)
|
||||
{
|
||||
return (void*)((Thread)thread).[Friend]mInternalThread;
|
||||
}
|
||||
|
||||
static void Thread_SetInternalThread(Object thread, void* internalThread)
|
||||
{
|
||||
((Thread)thread).[Friend]mInternalThread = (int)internalThread;
|
||||
}
|
||||
|
||||
static bool Thread_IsAutoDelete(Object thread)
|
||||
{
|
||||
return ((Thread)thread).[Friend]mAutoDelete;
|
||||
}
|
||||
|
||||
static void Thread_AutoDelete(Object thread)
|
||||
{
|
||||
delete thread;
|
||||
}
|
||||
|
||||
static int32 Thread_GetMaxStackSize(Object thread)
|
||||
{
|
||||
return ((Thread)thread).mMaxStackSize;
|
||||
}
|
||||
|
||||
static void Thread_StartProc(Object threadObj)
|
||||
{
|
||||
Thread thread = (Thread)threadObj;
|
||||
|
||||
if (thread.mName != null)
|
||||
thread.InformThreadNameChange(thread.mName);
|
||||
|
||||
int32 stackStart = 0;
|
||||
thread.SetStackStart((void*)&stackStart);
|
||||
if (thread.mDelegate is ThreadStart)
|
||||
{
|
||||
((ThreadStart)thread.mDelegate)();
|
||||
}
|
||||
else
|
||||
{
|
||||
((ParameterizedThreadStart)thread.mDelegate)(thread.mThreadStartArg);
|
||||
}
|
||||
}
|
||||
|
||||
public static this()
|
||||
{
|
||||
var cb = ref Runtime.BfRtCallbacks.sCallbacks;
|
||||
|
||||
cb.[Friend]mThread_Alloc = => Thread_Alloc;
|
||||
cb.[Friend]mThread_GetMainThread = => Thread_GetMainThread;
|
||||
cb.[Friend]mThread_ThreadProc = => Thread_StartProc;
|
||||
cb.[Friend]mThread_GetInternalThread = => Thread_GetInternalThread;
|
||||
cb.[Friend]mThread_SetInternalThread = => Thread_SetInternalThread;
|
||||
cb.[Friend]mThread_IsAutoDelete = => Thread_IsAutoDelete;
|
||||
cb.[Friend]mThread_AutoDelete = => Thread_AutoDelete;
|
||||
cb.[Friend]mThread_GetMaxStackSize = => Thread_GetMaxStackSize;
|
||||
}
|
||||
}
|
||||
|
||||
public this(ThreadStart start)
|
||||
{
|
||||
if (start == null)
|
||||
{
|
||||
Runtime.FatalError();
|
||||
}
|
||||
SetStart((Delegate)start, 0); //0 will setup Thread with default stackSize
|
||||
}
|
||||
|
||||
public this(ThreadStart start, int32 maxStackSize)
|
||||
{
|
||||
if (start == null)
|
||||
{
|
||||
Runtime.FatalError();
|
||||
}
|
||||
if (0 > maxStackSize)
|
||||
Runtime.FatalError();
|
||||
SetStart((Delegate)start, maxStackSize);
|
||||
}
|
||||
|
||||
public this(ParameterizedThreadStart start)
|
||||
{
|
||||
if (start == null)
|
||||
{
|
||||
Runtime.FatalError();
|
||||
}
|
||||
SetStart((Delegate)start, 0);
|
||||
}
|
||||
|
||||
public this(ParameterizedThreadStart start, int32 maxStackSize)
|
||||
{
|
||||
if (start == null)
|
||||
{
|
||||
Runtime.FatalError();
|
||||
}
|
||||
if (0 > maxStackSize)
|
||||
Runtime.FatalError();
|
||||
SetStart((Delegate)start, maxStackSize);
|
||||
}
|
||||
|
||||
static this()
|
||||
{
|
||||
#unwarn
|
||||
RuntimeThreadInit runtimeThreadInitRef = ?;
|
||||
sMainThread.ManualThreadInit();
|
||||
}
|
||||
|
||||
static Thread CreateEmptyThread()
|
||||
{
|
||||
return new Thread();
|
||||
}
|
||||
|
||||
public bool AutoDelete
|
||||
{
|
||||
set
|
||||
{
|
||||
// Changing AutoDelete from another thread while we are running is a race condition
|
||||
Runtime.Assert((CurrentThread == this) || (!IsAlive));
|
||||
mAutoDelete = value;
|
||||
}
|
||||
|
||||
get
|
||||
{
|
||||
return mAutoDelete;
|
||||
}
|
||||
}
|
||||
|
||||
extern void ManualThreadInit();
|
||||
extern void StartInternal();
|
||||
extern void SetStackStart(void* ptr);
|
||||
|
||||
public void Start(bool autoDelete = true)
|
||||
{
|
||||
mAutoDelete = autoDelete;
|
||||
StartInternal();
|
||||
}
|
||||
|
||||
public void Start(Object parameter, bool autoDelete = true)
|
||||
{
|
||||
mAutoDelete = autoDelete;
|
||||
if (mDelegate is ThreadStart)
|
||||
{
|
||||
Runtime.FatalError();
|
||||
}
|
||||
mThreadStartArg = parameter;
|
||||
StartInternal();
|
||||
}
|
||||
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
[CLink]
|
||||
static extern int32 _tls_index;
|
||||
#endif
|
||||
|
||||
public static int ModuleTLSIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
return _tls_index;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public void Suspend() { SuspendInternal(); }
|
||||
private extern void SuspendInternal();
|
||||
|
||||
public void Resume() { ResumeInternal(); }
|
||||
private extern void ResumeInternal();
|
||||
|
||||
public void Interrupt() { InterruptInternal(); }
|
||||
private extern void InterruptInternal();
|
||||
|
||||
public ThreadPriority Priority
|
||||
{
|
||||
get { return (ThreadPriority)GetPriorityNative(); }
|
||||
set { SetPriorityNative((int32)value); }
|
||||
}
|
||||
private extern int32 GetPriorityNative();
|
||||
private extern void SetPriorityNative(int32 priority);
|
||||
|
||||
extern bool GetIsAlive();
|
||||
public bool IsAlive
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetIsAlive();
|
||||
}
|
||||
}
|
||||
|
||||
extern bool GetIsThreadPoolThread();
|
||||
public bool IsThreadPoolThread
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetIsThreadPoolThread();
|
||||
}
|
||||
}
|
||||
|
||||
private extern bool JoinInternal(int32 millisecondsTimeout);
|
||||
|
||||
public void Join()
|
||||
{
|
||||
JoinInternal(Timeout.Infinite);
|
||||
}
|
||||
|
||||
public bool Join(int32 millisecondsTimeout)
|
||||
{
|
||||
return JoinInternal(millisecondsTimeout);
|
||||
}
|
||||
|
||||
public bool Join(TimeSpan timeout)
|
||||
{
|
||||
int64 tm = (int64)timeout.TotalMilliseconds;
|
||||
if (tm < -1 || tm > (int64)Int32.MaxValue)
|
||||
Runtime.FatalError();
|
||||
|
||||
return Join((int32)tm);
|
||||
}
|
||||
|
||||
private static extern void SleepInternal(int32 millisecondsTimeout);
|
||||
public static void Sleep(int32 millisecondsTimeout)
|
||||
{
|
||||
SleepInternal(millisecondsTimeout);
|
||||
}
|
||||
|
||||
public static void Sleep(TimeSpan timeout)
|
||||
{
|
||||
int64 tm = (int64)timeout.TotalMilliseconds;
|
||||
if (tm < -1 || tm > (int64)Int32.MaxValue)
|
||||
Runtime.FatalError();
|
||||
Sleep((int32)tm);
|
||||
}
|
||||
|
||||
private static extern void SpinWaitInternal(int32 iterations);
|
||||
|
||||
public static void SpinWait(int iterations)
|
||||
{
|
||||
SpinWaitInternal((int32)iterations);
|
||||
}
|
||||
|
||||
private static extern bool YieldInternal();
|
||||
|
||||
public static bool Yield()
|
||||
{
|
||||
return YieldInternal();
|
||||
}
|
||||
|
||||
public static Thread CurrentThread
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetCurrentThreadNative();
|
||||
}
|
||||
}
|
||||
|
||||
extern int32 GetThreadId();
|
||||
|
||||
public int32 Id
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetThreadId();
|
||||
}
|
||||
}
|
||||
|
||||
private static extern Thread GetCurrentThreadNative();
|
||||
|
||||
void SetStart(Delegate start, int32 maxStackSize)
|
||||
{
|
||||
mDelegate = start;
|
||||
mMaxStackSize = maxStackSize;
|
||||
}
|
||||
|
||||
|
||||
public ~this()
|
||||
{
|
||||
// Make sure we're not deleting manually it mAutoDelete is set
|
||||
Debug.Assert((!mAutoDelete) || (CurrentThread == this));
|
||||
// Delegate to the unmanaged portion.
|
||||
InternalFinalize();
|
||||
// Thread owns delegate
|
||||
delete mDelegate;
|
||||
}
|
||||
|
||||
private extern void InternalFinalize();
|
||||
|
||||
public bool IsBackground
|
||||
{
|
||||
get { return IsBackgroundNative(); }
|
||||
set { SetBackgroundNative(value); }
|
||||
}
|
||||
private extern bool IsBackgroundNative();
|
||||
private extern void SetBackgroundNative(bool isBackground);
|
||||
|
||||
public extern void SetJoinOnDelete(bool joinOnDelete);
|
||||
|
||||
public ThreadState ThreadState
|
||||
{
|
||||
get { return (ThreadState)GetThreadStateNative(); }
|
||||
}
|
||||
|
||||
private extern int32 GetThreadStateNative();
|
||||
|
||||
public void SetName(String name)
|
||||
{
|
||||
if (name == null)
|
||||
{
|
||||
delete mName;
|
||||
mName = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
String.NewOrSet!(mName, name);
|
||||
}
|
||||
if (mInternalThread != 0)
|
||||
InformThreadNameChange(name);
|
||||
}
|
||||
|
||||
public void GetName(String outName)
|
||||
{
|
||||
if (mName != null)
|
||||
outName.Append(mName);
|
||||
}
|
||||
|
||||
private extern void InformThreadNameChange(String name);
|
||||
}
|
||||
}
|
182
BeefLibs/corlib/src/Threading/ThreadPool.bf
Normal file
182
BeefLibs/corlib/src/Threading/ThreadPool.bf
Normal file
|
@ -0,0 +1,182 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
|
||||
//#define DISABLE_THREADS
|
||||
|
||||
namespace System.Threading
|
||||
{
|
||||
public delegate void WorkDelegate();
|
||||
|
||||
enum WorkEntry
|
||||
{
|
||||
case WorkDelegate(WorkDelegate callback);
|
||||
case WorkItem(IThreadPoolWorkItem workItem);
|
||||
}
|
||||
|
||||
struct ThreadStats
|
||||
{
|
||||
public volatile int32 mCount;
|
||||
public volatile int32 mMax;
|
||||
public volatile int32 mActive;
|
||||
}
|
||||
|
||||
internal interface IThreadPoolWorkItem
|
||||
{
|
||||
void ExecuteWorkItem();
|
||||
void MarkAborted();
|
||||
}
|
||||
|
||||
public static class ThreadPool
|
||||
{
|
||||
static int32 sConcurrency = 8;
|
||||
static bool sStarted = false;
|
||||
static List<Thread> sThreads = new List<Thread>() ~ delete _;
|
||||
static bool sShuttingDown;
|
||||
static Monitor sMonitor = new Monitor() ~ delete _;
|
||||
static Monitor sBindingMonitor = new Monitor() ~ delete _;
|
||||
static WaitEvent sThreadWakeEvent = new WaitEvent() ~ delete _;
|
||||
static WaitEvent sThreadClosedEvent = new WaitEvent() ~ delete _;
|
||||
|
||||
static ThreadStats sWorkerThreadStats;
|
||||
static ThreadStats sIOThreadStats;
|
||||
static List<WorkEntry> mWorkEntries = new List<WorkEntry>() ~ delete _;
|
||||
|
||||
static this()
|
||||
{
|
||||
//TODO: This is really bad, fix this pool!
|
||||
sWorkerThreadStats.mMax = 4;
|
||||
sIOThreadStats.mMax = 4;
|
||||
}
|
||||
|
||||
static ~this()
|
||||
{
|
||||
sShuttingDown = true;
|
||||
|
||||
while (true)
|
||||
{
|
||||
sThreadWakeEvent.Set(true);
|
||||
|
||||
using (sMonitor.Enter())
|
||||
if (sThreads.Count == 0)
|
||||
break;
|
||||
sThreadClosedEvent.WaitFor();
|
||||
}
|
||||
|
||||
//Console.WriteLine("ThreadPool.~this done");
|
||||
}
|
||||
|
||||
static void CheckSpawnWorkerThread()
|
||||
{
|
||||
using (sMonitor.Enter())
|
||||
{
|
||||
if ((sWorkerThreadStats.mActive == sWorkerThreadStats.mCount) && (sWorkerThreadStats.mCount < sWorkerThreadStats.mMax))
|
||||
{
|
||||
int threadId = sThreads.Count;
|
||||
sWorkerThreadStats.mCount++;
|
||||
sWorkerThreadStats.mActive++; // We know the thread will immediately become active
|
||||
|
||||
Thread thread = new Thread(new () => { WorkerProc(threadId); });
|
||||
sThreads.Add(thread);
|
||||
thread.Start(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool TryPopCustomWorkItem(WorkEntry workEntry)
|
||||
{
|
||||
using (sMonitor.Enter())
|
||||
{
|
||||
return mWorkEntries.Remove(workEntry);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryPopCustomWorkItem(IThreadPoolWorkItem workItem)
|
||||
{
|
||||
return TryPopCustomWorkItem(.WorkItem(workItem));
|
||||
}
|
||||
|
||||
public static bool QueueUserWorkItem(IThreadPoolWorkItem workItem)
|
||||
{
|
||||
using (sMonitor.Enter())
|
||||
{
|
||||
mWorkEntries.Add(.WorkItem(workItem));
|
||||
CheckSpawnWorkerThread();
|
||||
sThreadWakeEvent.Set();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool QueueUserWorkItem(WorkDelegate waitCallback)
|
||||
{
|
||||
#if DISABLE_THREADS
|
||||
waitCallback(userState);
|
||||
return true;
|
||||
#endif
|
||||
|
||||
Debug.AssertNotStack(waitCallback);
|
||||
using (sMonitor.Enter())
|
||||
{
|
||||
mWorkEntries.Add(.WorkDelegate(waitCallback));
|
||||
CheckSpawnWorkerThread();
|
||||
sThreadWakeEvent.Set();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int32 sBindCount = 0;
|
||||
public static int32 sReleaseBindCount = 0;
|
||||
|
||||
static void Start()
|
||||
{
|
||||
sStarted = true;
|
||||
}
|
||||
|
||||
static void ThreadDone()
|
||||
{
|
||||
using (sMonitor.Enter())
|
||||
{
|
||||
Thread currentThread = Thread.CurrentThread;
|
||||
sThreads.Remove(currentThread);
|
||||
delete currentThread;
|
||||
sThreadClosedEvent.Set();
|
||||
}
|
||||
}
|
||||
|
||||
static void WorkerProc(int id)
|
||||
{
|
||||
let threadName = scope String();
|
||||
threadName.AppendF("ThreadPool Worker {0}", id);
|
||||
Thread.CurrentThread.SetName(threadName);
|
||||
|
||||
while (true)
|
||||
{
|
||||
WorkEntry? workEntryOptional = null;
|
||||
using (sMonitor.Enter())
|
||||
{
|
||||
if (mWorkEntries.Count != 0)
|
||||
workEntryOptional = mWorkEntries.PopFront();
|
||||
}
|
||||
|
||||
if (!workEntryOptional.HasValue)
|
||||
{
|
||||
sThreadWakeEvent.WaitFor();
|
||||
if (sShuttingDown)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
var workEntry = workEntryOptional.Value;
|
||||
switch (workEntry)
|
||||
{
|
||||
case .WorkDelegate(let callback):
|
||||
callback();
|
||||
delete callback;
|
||||
case .WorkItem(let workItem):
|
||||
workItem.ExecuteWorkItem();
|
||||
}
|
||||
}
|
||||
ThreadDone();
|
||||
}
|
||||
}
|
||||
}
|
13
BeefLibs/corlib/src/Threading/ThreadPriority.bf
Normal file
13
BeefLibs/corlib/src/Threading/ThreadPriority.bf
Normal file
|
@ -0,0 +1,13 @@
|
|||
using System.Threading;
|
||||
|
||||
namespace System.Threading
|
||||
{
|
||||
public enum ThreadPriority
|
||||
{
|
||||
Lowest = 0,
|
||||
BelowNormal = 1,
|
||||
Normal = 2,
|
||||
AboveNormal = 3,
|
||||
Highest = 4
|
||||
}
|
||||
}
|
16
BeefLibs/corlib/src/Threading/ThreadState.bf
Normal file
16
BeefLibs/corlib/src/Threading/ThreadState.bf
Normal file
|
@ -0,0 +1,16 @@
|
|||
namespace System.Threading
|
||||
{
|
||||
public enum ThreadState
|
||||
{
|
||||
Running = 0,
|
||||
StopRequested = 1,
|
||||
SuspendRequested = 2,
|
||||
Background = 4,
|
||||
Unstarted = 8,
|
||||
Stopped = 16,
|
||||
WaitSleepJoin = 32,
|
||||
Suspended = 64,
|
||||
AbortRequested = 128,
|
||||
Aborted = 256
|
||||
}
|
||||
}
|
13
BeefLibs/corlib/src/Threading/Timeout.bf
Normal file
13
BeefLibs/corlib/src/Threading/Timeout.bf
Normal file
|
@ -0,0 +1,13 @@
|
|||
using System.Threading;
|
||||
using System;
|
||||
|
||||
namespace System.Threading {
|
||||
|
||||
|
||||
public static class Timeout
|
||||
{
|
||||
public const int32 Infinite = -1;
|
||||
internal const uint32 UnsignedInfinite = (uint32)-1;
|
||||
}
|
||||
|
||||
}
|
58
BeefLibs/corlib/src/Threading/Volatile.bf
Normal file
58
BeefLibs/corlib/src/Threading/Volatile.bf
Normal file
|
@ -0,0 +1,58 @@
|
|||
namespace System.Threading
|
||||
{
|
||||
static class Volatile
|
||||
{
|
||||
//static volatile int32 gAtomicIdx;
|
||||
|
||||
public static T Read<T>(ref T location)
|
||||
{
|
||||
T value = location;
|
||||
Interlocked.Fence();
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void Write<T>(ref T location, T value)
|
||||
{
|
||||
Interlocked.Fence();
|
||||
location = value;
|
||||
}
|
||||
|
||||
/*public static void MoveAtomic(void* dest, void* src, int size)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
int startAtomicIdx = gAtomicIdx;
|
||||
Thread.MemoryBarrier();
|
||||
Internal.MemCpy(dest, src, size);
|
||||
Thread.MemoryBarrier();
|
||||
int endAtomicIdx = Interlocked.Increment(ref gAtomicIdx);
|
||||
if (endAtomicIdx == startAtomicIdx)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static T ReadAtomic<T>(ref T location)
|
||||
{
|
||||
if (sizeof(T) > sizeof(int))
|
||||
{
|
||||
if (sizeof(T) == sizeof(int64))
|
||||
{
|
||||
// Handle 64-bit values on 32-bit machines
|
||||
var location;
|
||||
int64 result = Interlocked.CompareExchange(ref *(int64*)&location, 0, 0);
|
||||
return *(T*)&result;
|
||||
}
|
||||
|
||||
var location;
|
||||
T value = ?;
|
||||
MoveAtomic(&value, &location, sizeof(T));
|
||||
Thread.MemoryBarrier();
|
||||
return value;
|
||||
}
|
||||
|
||||
T value = location;
|
||||
Thread.MemoryBarrier();
|
||||
return value;
|
||||
}*/
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue