/// <summary> /// Not allowed to set data larger than the buffer size /// </summary> public void Put(T[] dataToSet) { var sourceDataLength = dataToSet.Length; if (sourceDataLength > _capacity) { throw new ArgumentException("Amount of data that is trying to be set is larger than the capacity of this buffer"); } bool isOverflowed; int nextTail; lock (_lockObj) { // Calculate the amount of data (including the data being read at the moment, if a read is ongoing) var capacityInUse = BufferLogicHelper.CalculateUsedCapacity(_isEmpty, _head, _tail, _capacity); if (BufferLogicHelper.WillDataBeOverwritten(sourceDataLength, capacityInUse, _capacity)) { // We just throw away a chunk if there is no room LostData += sourceDataLength; } // Calculate the next tail, this way we also know whether we are overflowing nextTail = BufferLogicHelper.CalculateNextIndex(_tail, sourceDataLength, _capacity, out isOverflowed); } if (isOverflowed) { // Data spans across the end and beginning of the storage array, we need to do two copies var itemsToWriteAtEnd = _capacity - _tail; Array.Copy(dataToSet, 0, _storage, _tail, itemsToWriteAtEnd); var itemsToWriteAtBeginning = sourceDataLength - itemsToWriteAtEnd; Array.Copy(dataToSet, itemsToWriteAtEnd, _storage, 0, itemsToWriteAtBeginning); } else { Array.Copy(dataToSet, 0, _storage, _tail, sourceDataLength); } lock (_lockObj) { _tail = nextTail; // We just added data, the storage can never be empty now _isEmpty = false; // Check if we need to set the event if (_notifyEventEnabled && !_notifyEvent.IsSet && BufferLogicHelper.CalculateUsedCapacity(_isEmpty, _head, _tail, _capacity) >= _notifyThreshold) { // There is not enough data anymore, reset the event _notifyEvent.Set(); } } }
public void Test_WillDataBeOverwritten() { Assert.IsFalse(BufferLogicHelper.WillDataBeOverwritten(10, 0, 10)); Assert.IsTrue(BufferLogicHelper.WillDataBeOverwritten(5, 6, 10)); Assert.IsFalse(BufferLogicHelper.WillDataBeOverwritten(5, 5, 10)); }