/// <summary> /// Sets atomically current <see cref="Value"/> by provided setter method /// </summary> /// <param name="setter">The setter to use</param> /// <param name="order">The <see cref="MemoryOrder"/> to achieve</param> /// <returns>An updated value</returns> public T Set(Func <T, T> setter, MemoryOrder order) { bool lockTaken = false; if (order == MemoryOrder.SeqCst) { Monitor.Enter(_instanceLock, ref lockTaken); } try { T currentValue; T tempValue; do { currentValue = _value; tempValue = setter(currentValue); } while (_value != currentValue || Interlocked.CompareExchange(ref _value, tempValue, currentValue) != currentValue); return(currentValue); } finally { if (lockTaken) { Monitor.Exit(_instanceLock); } } }
public void AtomicReferenceArray_Should_Copy_Source(MemoryOrder memoryOrder) { var item1 = new object(); var item2 = new object(); var source = new object[] { item1, null, item2, null }; var ar = new AtomicReferenceArray <object>(source, memoryOrder); Assert.True(source.SequenceEqual(ar)); Assert.Null(source[1]); Assert.Null(ar[1]); source[1] = new object(); Assert.False(source.SequenceEqual(ar)); Assert.Null(source[3]); Assert.Null(ar[3]); Assert.Null(source[3]); Assert.Null(ar[3]); source[3] = new object(); Assert.NotNull(source[3]); Assert.Null(ar[3]); Assert.False(source.SequenceEqual(ar)); }
public Config(string description, MemoryOrder memoryOrder, bool useExchange, bool expectedToFail) { Description = description; MemoryOrder = memoryOrder; UseExchange = useExchange; ExpectedToFail = expectedToFail; }
/// <summary> /// Gets the underlying value with provided <paramref name="order"/> /// </summary> /// <param name="order">The <see cref="MemoryOrder"/> to achieve</param> /// <returns>The underlying value with provided <paramref name="order"/></returns> /// <remarks>Providing <see cref="MemoryOrder.Relaxed"/> reads the value as <see cref="MemoryOrder.Acquire"/></remarks> public T Load(MemoryOrder order) { switch (order) { case MemoryOrder.Relaxed: return(this._value); case MemoryOrder.Consume: throw new NotSupportedException(); case MemoryOrder.Acquire: return(this._value); case MemoryOrder.Release: throw new InvalidOperationException("Cannot get (load) value with Release semantics"); case MemoryOrder.AcqRel: return(this._value); case MemoryOrder.SeqCst: return(Volatile.Read(ref _value)); default: throw new ArgumentOutOfRangeException("order"); } }
public void AtomicReferenceArray_Store_MemoryOrder_Should_Success(MemoryOrder order) { var source = Enumerable.Range(0, 3).Select(x => new object()).ToArray(); var atomicReferenceArray = new AtomicReferenceArray <object>(source.Length, order); for (int i = 0; i < atomicReferenceArray.Count; i++) { atomicReferenceArray.Store(i, source[i], order); } for (int i = 0; i < atomicReferenceArray.Count; i++) { Assert.Equal(source[i], atomicReferenceArray.Load(i, order)); } for (int i = 0; i < atomicReferenceArray.Count; i++) { atomicReferenceArray.Store(i, source[i], order); } for (int i = 0; i < atomicReferenceArray.Count; i++) { Assert.Equal(source[i], atomicReferenceArray.Load(i, order)); } }
public T Load(MemoryOrder order) { if (order == MemoryOrder.Consume) { throw new NotSupportedException(); } if (order == MemoryOrder.Release) { throw new InvalidOperationException("Cannot get (load) value with Release semantics"); } switch (order) { case MemoryOrder.Relaxed: return(Platform.reinterpret_cast <long, T>(ref AcqRelValue.Int64Value)); case MemoryOrder.Acquire: case MemoryOrder.AcqRel: case MemoryOrder.SeqCst: #if ARM_CPU var tmp = Platform.reinterpret_cast <long, T>(ref AcqRelValue.Int64Value); Platform.MemoryBarrier(); return(tmp); #else long value = Volatile.Read(ref AcqRelValue.Int64Value); return(Platform.reinterpret_cast <long, T>(ref value)); #endif default: throw new ArgumentOutOfRangeException("order"); } }
public T Load(MemoryOrder order) { lock (_atomic._instanceLock) { return(((IAtomic <T>)_atomic).Load(order)); } }
public void Store(ref T value, MemoryOrder order) { lock (_atomic._instanceLock) { ((IAtomic <T>)_atomic).Store(value, order); } }
public void Store(ref T value, MemoryOrder order) { switch (order) { case MemoryOrder.Relaxed: this.AcqRelValue.Int32Value = Platform.reinterpret_cast <T, int>(ref value); break; case MemoryOrder.Consume: throw new NotSupportedException(); case MemoryOrder.Acquire: throw new InvalidOperationException("Cannot set (store) value with Acquire semantics"); case MemoryOrder.Release: case MemoryOrder.AcqRel: this.AcqRelValue.Int32Value = Platform.reinterpret_cast <T, int>(ref value); break; case MemoryOrder.SeqCst: #if ARM_CPU Platform.MemoryBarrier(); this.AcqRelValue.Int32Value = Platform.reinterpret_cast <T, int>(ref value); #else Interlocked.Exchange(ref AcqRelValue.Int32Value, Platform.reinterpret_cast <T, int>(ref value)); #endif break; default: throw new ArgumentOutOfRangeException("order"); } }
private void RecordStore(T data, MemoryOrder mo, ShadowThread runningThread, bool isReleaseSequence) { var storeTarget = _history.GetNext(); storeTarget.RecordStore(runningThread.Id, runningThread.Clock, mo, data); bool isAtLeastRelease = mo == MemoryOrder.Release || mo == MemoryOrder.AcquireRelease || mo == MemoryOrder.SequentiallyConsistent; // Here 'sourceClock' is the clock that other threads must synchronize with if they read-acquire this data. // If this store is a release (or stronger), then those threads must synchronize with the latest clocks that // this thread has synchronized with (i.e. the releases it has acquired: runningThread.ReleasesAcquired). // Otherwise, if this store is relaxed, then those threads need only synchronize with the latest release fence of this thread // (i.e. runningThread.FenceReleasesAcquired) var sourceClock = isAtLeastRelease ? runningThread.ReleasesAcquired : runningThread.FenceReleasesAcquired; var previous = _history[_history.CurrentIndex - 1]; var targetClock = storeTarget.ReleasesToAcquire; if (isReleaseSequence) { targetClock.Assign(previous.ReleasesToAcquire); targetClock.Join(sourceClock); } else { targetClock.Assign(sourceClock); } }
public T Exchange(T newData, MemoryOrder mo, ShadowThread runningThread) { var oldData = _history.RecordRMWLoad(mo, runningThread); _history.RecordRMWStore(newData, mo, runningThread); return(oldData); }
void IAtomicRef <T> .Store(ref T value, MemoryOrder order) { switch (order) { case MemoryOrder.Relaxed: Platform.Write(ref _value, ref value); break; case MemoryOrder.Consume: throw new NotSupportedException(); case MemoryOrder.Acquire: throw new InvalidOperationException("Cannot set (store) value with Acquire semantics"); case MemoryOrder.Release: case MemoryOrder.AcqRel: Platform.WriteRelease(ref _value, ref value); break; case MemoryOrder.SeqCst: Platform.WriteSeqCst(ref _value, ref value); break; default: throw new ArgumentOutOfRangeException("order"); } }
/// <summary> /// Creates new instance of <see cref="Atomic{T}"/> /// </summary> /// <param name="value">The value to store</param> /// <param name="order">Affects the way store operation occur. Default is <see cref="MemoryOrder.SeqCst"/> semantics which hurt performance</param> /// <param name="align">True to store the underlying value aligned, otherwise False</param> public Atomic(T value, MemoryOrder order = MemoryOrder.SeqCst, bool align = false) { if (!order.IsSpported()) { throw new ArgumentException(string.Format("{0} is not supported", order)); } _storage = GetStorage(order, align); if (Intrinsics != null && Intrinsics.Supports <T>()) { _writer = Intrinsics; } else if (_storage as Atomic <T> == this) { _writer = this; } else if (_storage.Supports <T>()) { _writer = _storage; } else { throw new NotSupportedException(string.Format("{0} type is not supported", typeof(T))); } if (object.ReferenceEquals(_storage, this) || _storage is LockBasedAtomic) { _instanceLock = new object(); } _order = order; _storage.Value = value; }
public Config(string description, MemoryOrder storeMemoryOrder, MemoryOrder loadMemoryOrder, bool expectedToFail) { Description = description; StoreMemoryOrder = storeMemoryOrder; LoadMemoryOrder = loadMemoryOrder; ExpectedToFail = expectedToFail; }
public void Fence(MemoryOrder mo, VectorClock sequentiallyConsistentFence) { switch (mo) // TODO: Should this be done in Fence.Insert ? { case MemoryOrder.Acquire: AcquireFence(); break; case MemoryOrder.Release: ReleaseFence(); break; case MemoryOrder.AcquireRelease: AcquireFence(); ReleaseFence(); break; case MemoryOrder.SequentiallyConsistent: AcquireFence(); sequentiallyConsistentFence.Join(ReleasesAcquired); ReleasesAcquired.Assign(sequentiallyConsistentFence); ReleaseFence(); break; default: throw new Exception($"Unsupported memory fence order {mo}"); } }
/// <summary> /// Gets an element at <paramref name="index"/> with provided <paramref name="order"/> /// </summary> /// <param name="index">The index of element from which to load</param> /// <param name="order">The <see cref="MemoryOrder"/> to achieve</param> /// <returns>The underlying value with provided <paramref name="order"/></returns> public long Load(int index, MemoryOrder order) { if (order == MemoryOrder.Consume) { throw new NotSupportedException(); } if (order == MemoryOrder.Release) { throw new InvalidOperationException("Cannot get (load) value with Release semantics"); } switch (order) { case MemoryOrder.Relaxed: return(this._data[index]); case MemoryOrder.Acquire: case MemoryOrder.AcqRel: case MemoryOrder.SeqCst: #if ARM_CPU var tmp = this._data[index]; Platform.MemoryBarrier(); return(tmp); #else return(Volatile.Read(ref this._data[index])); #endif default: throw new ArgumentOutOfRangeException("order"); } }
public void AtomicLongArray_Should_Copy_Source(MemoryOrder memoryOrder) { var item1 = 1L; var item2 = 2L; var source = new [] { item1, 0, item2, 0 }; var ar = new AtomicLongArray(source, memoryOrder); Assert.True(source.SequenceEqual(ar)); Assert.Equal(0, source[1]); Assert.Equal(0, ar[1]); source[1] = -1; Assert.False(source.SequenceEqual(ar)); Assert.Equal(0, source[3]); Assert.Equal(0, ar[3]); Assert.Equal(0, source[3]); Assert.Equal(0, ar[3]); source[3] = -1; Assert.Equal(-1, source[3]); Assert.Equal(0, ar[3]); Assert.False(source.SequenceEqual(ar)); }
/// <summary> /// Sets the underlying value with provided <paramref name="order"/> /// </summary> /// <param name="value">The value to store</param> /// <param name="order">The <see cref="MemoryOrder"/> to achieve</param> /// <remarks>Providing <see cref="MemoryOrder.Relaxed"/> writes the value as <see cref="MemoryOrder.Acquire"/></remarks> public void Store(T value, MemoryOrder order) { switch (order) { case MemoryOrder.Relaxed: this._value = value; break; case MemoryOrder.Consume: throw new NotSupportedException(); case MemoryOrder.Acquire: throw new InvalidOperationException("Cannot set (store) value with Acquire semantics"); case MemoryOrder.Release: case MemoryOrder.AcqRel: // ARM JIT should emit DMB this._value = value; break; case MemoryOrder.SeqCst: Interlocked.Exchange(ref _value, value); break; default: throw new ArgumentOutOfRangeException("order"); } }
/// <summary> /// Gets the underlying value with provided <paramref name="order"/> /// </summary> /// <param name="order">The <see cref="MemoryOrder"/> to achieve</param> /// <returns>The underlying value with provided <paramref name="order"/></returns> /// <remarks>Providing <see cref="MemoryOrder.Relaxed"/> reads the value as <see cref="MemoryOrder.Acquire"/></remarks> public T Load(MemoryOrder order) { switch (order) { case MemoryOrder.Relaxed: return(this._value); case MemoryOrder.Consume: throw new NotSupportedException(); case MemoryOrder.Acquire: return(this._value); case MemoryOrder.Release: throw new InvalidOperationException("Cannot get (load) value with Release semantics"); case MemoryOrder.AcqRel: return(this._value); case MemoryOrder.SeqCst: #if ARM_CPU var tmp = this._value; Platform.MemoryBarrier(); return(tmp); #else return(this._value); #endif default: throw new ArgumentOutOfRangeException("order"); } }
/// <summary> /// Sets atomically current <see cref="Value"/> by provided setter method /// </summary> /// <param name="index">The index of element at which to store</param> /// <param name="setter">The setter to use</param> /// <param name="data">Any arbitrary value to be passed to <paramref name="setter"/></param> /// <param name="order">The <see cref="MemoryOrder"/> to achieve</param> /// <returns>An updated value</returns> public T Set <TData>(int index, Func <T, TData, T> setter, TData data, MemoryOrder order) { bool lockTaken = false; if (order == MemoryOrder.SeqCst) { Monitor.Enter(_instanceLock, ref lockTaken); } try { T currentValue; T tempValue; do { currentValue = _data[index]; tempValue = setter(currentValue, data); } while (_data[index] != currentValue || Interlocked.CompareExchange(ref _data[index], tempValue, currentValue) != currentValue); return(currentValue); } finally { if (lockTaken) { Monitor.Exit(_instanceLock); } } }
/// <summary> /// Sets an element at <paramref name="index"/> with provided <paramref name="order"/> /// </summary> /// <param name="index">The index of element at which to store</param> /// <param name="value">The value to store</param> /// <param name="order">The <see cref="MemoryOrder"/> to achieve</param> /// <remarks>Providing <see cref="MemoryOrder.Relaxed"/> writes the value as <see cref="MemoryOrder.Acquire"/></remarks> public void Store(int index, T value, MemoryOrder order) { switch (order) { case MemoryOrder.Relaxed: this._data[index] = value; break; case MemoryOrder.Consume: throw new NotSupportedException(); case MemoryOrder.Acquire: throw new InvalidOperationException("Cannot set (store) value with Acquire semantics"); case MemoryOrder.Release: case MemoryOrder.AcqRel: #if ARM_CPU Platform.MemoryBarrier(); #endif this._data[index] = value; break; case MemoryOrder.SeqCst: Interlocked.Exchange(ref _data[index], value); break; default: throw new ArgumentOutOfRangeException("order"); } }
public T Load(MemoryOrder mo, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { Preamble(); var result = _memoryOrdered.Load(mo, TE.RunningThread); TE.RecordEvent(memberName, sourceFilePath, sourceLineNumber, $"Load ({mo}) <-- {Str(result)}"); return(result); }
/// <summary> /// Creates new instance of <see cref="AtomicLong"/> /// </summary> /// <param name="initialValue">The value to store</param> /// <param name="order">Affects the way store operation occur. Load operations are always use <see cref="MemoryOrder.Acquire"/> semantics</param> public AtomicReference(T initialValue, MemoryOrder order = MemoryOrder.AcqRel) { order.ThrowIfNotSupported(); _instanceLock = order == MemoryOrder.SeqCst ? new object() : null; _order = order; this._value = initialValue; }
public T Exchange(T newData, MemoryOrder mo, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { Preamble(); var oldData = _memoryOrdered.Exchange(newData, mo, TE.RunningThread); TE.RecordEvent(memberName, sourceFilePath, sourceLineNumber, $"Exchange ({mo}): --> {Str(newData)} ({Str(oldData)})"); return(oldData); }
public static void Insert(MemoryOrder mo, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { TE.MaybeSwitch(); var runningThread = TE.RunningThread; runningThread.Fence(mo, TE.SequentiallyConsistentFence); TE.RecordEvent(memberName, sourceFilePath, sourceLineNumber, $"Fence: {mo}"); }
public int Decrement(MemoryOrder mo, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0) { Preamble(); var newValue = _memoryOrdered.CurrentValue - 1; var oldValue = _memoryOrdered.Exchange(newValue, mo, TE.RunningThread); TE.RecordEvent(memberName, sourceFilePath, sourceLineNumber, $"Decrement ({mo}): --> {Str(newValue)} ({Str(oldValue)})"); return(newValue); }
/// <summary> /// Creates new instance of <see cref="Atomic{T}"/> /// </summary> /// <param name="value">The value to store</param> /// <param name="order">Affects the way store operation occur. Default is <see cref="MemoryOrder.SeqCst"/> semantics which hurt performance</param> /// <param name="align">True to store the underlying value aligned, otherwise False</param> public Atomic(T value, MemoryOrder order = MemoryOrder.SeqCst, bool align = false) { order.ThrowIfNotSupported(); _storage = GetStorage(order, align); _order = order; _storage.Value = value; }
public Config(string description, MemoryOrder enqueueMemoryOrder, MemoryOrder dequeueMemoryOrder, bool useEnqueueReleaseFence, bool useDequeueAcquireFence, bool expectedToFail) { Description = description; EnqueueMemoryOrder = enqueueMemoryOrder; DequeueMemoryOrder = dequeueMemoryOrder; UseEnqueueReleaseFence = useEnqueueReleaseFence; UseDequeueAcquireFence = useDequeueAcquireFence; ExpectedToFail = expectedToFail; }
/// <summary> /// Creates new instance of <see cref="AtomicLong"/> /// </summary> /// <param name="value">The value to store</param> /// <param name="order">Affects the way store operation occur. Load operations are always use <see cref="MemoryOrder.Acquire"/> semantics</param> /// <param name="align">True to store the underlying value aligned, otherwise False</param> public AtomicLong(long value, MemoryOrder order = MemoryOrder.SeqCst, bool align = false) { if (!order.IsSpported()) { throw new ArgumentException(string.Format("{0} is not supported", order)); } _order = order; this._storage = BoxedInt64.Create(value, align); }
/// <summary> /// Creates new instance of <see cref="AtomicLong"/> /// </summary> /// <param name="initialValue">The value to store</param> /// <param name="order">Affects the way store operation occur. Load operations are always use <see cref="MemoryOrder.Acquire"/> semantics</param> public AtomicReference(T initialValue, MemoryOrder order = MemoryOrder.AcqRel) { if (!order.IsSpported()) { throw new ArgumentException(string.Format("{0} is not supported", order)); } _order = order; this._value = initialValue; }
public void AtomicIntegerArray_Load_Acquire_Should_Success(MemoryOrder order) { var atomicIntegerArray = new AtomicIntegerArray(new int[3], order); for (int i = 0; i < atomicIntegerArray.Count; i++) { Assert.Equal(0, atomicIntegerArray.Load(i, MemoryOrder.Acquire)); atomicIntegerArray.Store(i, i, MemoryOrder.Release); } for (int i = 0; i < atomicIntegerArray.Count; i++) { Assert.Equal(i, atomicIntegerArray.Load(i, MemoryOrder.Acquire)); } }
public void AtomicIntegerArray_Indexer_MemoryOrder_Should_Success(MemoryOrder order) { var atomicIntegerArray = new AtomicIntegerArray(new int[3], order); for (int i = 0; i < atomicIntegerArray.Count; i++) { Assert.Equal(0, atomicIntegerArray[i]); atomicIntegerArray[i] = i; } for (int i = 0; i < atomicIntegerArray.Count; i++) { Assert.Equal(i, atomicIntegerArray[i]); } }
public void AtomicReferenceArray_Ctor_Should_Track_Length(MemoryOrder order) { Assert.Throws<ArgumentException>(() => new AtomicReferenceArray<object>(-1, order)); GC.KeepAlive(new AtomicReferenceArray<object>(0, order)); GC.KeepAlive(new AtomicReferenceArray<object>(1, order)); }
public void AtomicIntegerArray_Store_Should_Success(int initialValue, int storeValue, MemoryOrder order) { var atomicIntegerArray = new AtomicIntegerArray(new int[] {initialValue}, MemoryOrder.Relaxed); atomicIntegerArray.Store(0, storeValue, order); Assert.Equal(storeValue, atomicIntegerArray[0]); }
public void AtomicIntegerArray_IsLockFree_Should_Success(int initialValue, MemoryOrder order, bool isLockFree) { var atomicIntegerArray = new AtomicIntegerArray(new[] { initialValue }, order); Assert.Equal(atomicIntegerArray.IsLockFree, isLockFree); }
public void AtomicLong_IsLockFree_Should_Success(long initialValue, MemoryOrder order, bool isLockFree) { var atomicLong = new AtomicLong(initialValue, order); Assert.Equal(atomicLong.IsLockFree, isLockFree); }
public void AtomicLong_Store_Should_Success(long initialValue, long storeValue, MemoryOrder order) { var atomicLong = new AtomicLong(initialValue, MemoryOrder.Relaxed); atomicLong.Store(storeValue, order); Assert.Equal(storeValue, atomicLong.Value); }
public void AtomicIntegerArray_Decrement_Should_Success(MemoryOrder memoryOrder) { var ar = new AtomicIntegerArray(10, memoryOrder); foreach (var o in ar) { Assert.Equal(0, o); } for (int i = 0; i < ar.Count; i++) { Assert.Equal(0, ar[i]); } for (int i = 0; i < ar.Count; i++) { ar[i] = i; ar.DecrementAt(i); } Assert.Equal(Enumerable.Range(-1, 10), ar); }
public void AtomicIntegerArray_Store_MemoryOrder_Should_Success(MemoryOrder order) { var atomicIntegerArray = new AtomicIntegerArray(new int[3], order); for (int i = 0; i < atomicIntegerArray.Count; i++) { atomicIntegerArray.Store(i, i, order); } for (int i = 0; i < atomicIntegerArray.Count; i++) { Assert.Equal(i, atomicIntegerArray.Load(i, order)); } for (int i = 0; i < atomicIntegerArray.Count; i++) { atomicIntegerArray.Store(i, i, order); } for (int i = 0; i < atomicIntegerArray.Count; i++) { Assert.Equal(i, atomicIntegerArray.Load(i, order)); } }
public void AtomicInteger_IsLockFree_Should_Success(int initialValue, MemoryOrder order, bool isLockFree) { var atomicInteger = new AtomicInteger(initialValue, order); Assert.Equal(atomicInteger.IsLockFree, isLockFree); }
public void AtomicInteger_Store_Should_Success(int initialValue, int storeValue, MemoryOrder order) { var atomicInteger = new AtomicInteger(initialValue, order); atomicInteger.Store(storeValue, order); Assert.Equal(storeValue, atomicInteger.Value); }
public void AtomicIntegerArray_With_Null_Source_Should_Fail(MemoryOrder memoryOrder) { Assert.Throws<ArgumentNullException>(() => new AtomicIntegerArray(null, memoryOrder)); }
public void AtomicIntegerArray_Ctor_Should_Track_Length(MemoryOrder order) { Assert.Throws<ArgumentException>(() => new AtomicIntegerArray(-1, order)); GC.KeepAlive(new AtomicIntegerArray(0, order)); GC.KeepAlive(new AtomicIntegerArray(1, order)); }
public void AtomicIntegerArray_Items_With_Length_Ctor_Should_Be_Null(int length, MemoryOrder memoryOrder) { var ar = new AtomicIntegerArray(length, memoryOrder); foreach (var o in ar) { Assert.Equal(0, o); } for (int i = 0; i < ar.Count; i++) { Assert.Equal(0, ar[i]); } }
public void AtomicIntegerArray_Should_Copy_Source(MemoryOrder memoryOrder) { var item1 = 1; var item2 = 2; var source = new [] { item1, 0, item2, 0}; var ar = new AtomicIntegerArray(source, memoryOrder); Assert.True(source.SequenceEqual(ar)); Assert.Equal(0, source[1]); Assert.Equal(0, ar[1]); source[1] = -1; Assert.False(source.SequenceEqual(ar)); Assert.Equal(0, source[3]); Assert.Equal(0, ar[3]); Assert.Equal(0, source[3]); Assert.Equal(0, ar[3]); source[3] = -1; Assert.Equal(-1, source[3]); Assert.Equal(0, ar[3]); Assert.False(source.SequenceEqual(ar)); }
public void AtomicReferenceArray_Should_Copy_Source(MemoryOrder memoryOrder) { var item1 = new object(); var item2 = new object(); var source = new object[] { item1, null, item2, null}; var ar = new AtomicReferenceArray<object>(source, memoryOrder); Assert.True(source.SequenceEqual(ar)); Assert.Null(source[1]); Assert.Null(ar[1]); source[1] = new object(); Assert.False(source.SequenceEqual(ar)); Assert.Null(source[3]); Assert.Null(ar[3]); Assert.Null(source[3]); Assert.Null(ar[3]); source[3] = new object(); Assert.NotNull(source[3]); Assert.Null(ar[3]); Assert.False(source.SequenceEqual(ar)); }
public void AtomicBoolean_IsLockFree_Should_Success(bool initialValue, MemoryOrder order, bool isLockFree) { var atomicBoolean = new AtomicBoolean(initialValue, order); Assert.Equal(atomicBoolean.IsLockFree, isLockFree); }
public void AtomicReferenceArray_Items_With_Length_Ctor_Should_Be_Null(int length, MemoryOrder memoryOrder) { var ar = new AtomicReferenceArray<object>(length, memoryOrder); foreach (var o in ar) { Assert.Null(o); } for (int i = 0; i < ar.Count; i++) { Assert.Null(ar[i]); } }
public void AtomicBoolean_Store_Should_Success(bool initialValue, bool storeValue, MemoryOrder order) { var atomicBoolean = new AtomicBoolean(initialValue, order); atomicBoolean.Store(storeValue, order); Assert.Equal(storeValue, atomicBoolean.Value); }
public void AtomicReferenceArray_With_Null_Source_Should_Fail(MemoryOrder memoryOrder) { Assert.Throws<ArgumentNullException>(() => new AtomicReferenceArray<object>(null, memoryOrder)); }