/// <summary> /// Returns the next item to be taken from the back without removing it. /// </summary> /// <exception cref="System.InvalidOperationException">No more items to be taken.</exception> public T Peek(T item) { T result = default(T); while (true) { int revision = _revision; if (IsOperationSafe()) { var entries = ThreadingHelper.VolatileRead(ref _entriesNew); bool done = false; try { result = entries.Peek(); } finally { var isOperationSafe = IsOperationSafe(entries, revision); if (isOperationSafe) { done = true; } } if (done) { return(result); } } else { CooperativeGrow(); } } }
/// <summary> /// Sets the value associated with the specified key. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> public void Set(TKey key, TValue value) { while (true) { int revision = _revision; if (IsOperationSafe()) { bool isNew; var entries = ThreadingHelper.VolatileRead(ref _entriesNew); if (SetExtracted(key, value, entries, out isNew) != -1) { if (IsOperationSafe(entries, revision)) { if (isNew) { Interlocked.Increment(ref _count); } break; } else { int oldStatus = Interlocked.CompareExchange(ref _status, (int)BucketStatus.GrowRequested, (int)BucketStatus.Free); if (oldStatus == (int)BucketStatus.Free) { _revision++; } } } } else { CooperativeGrow(); } } }
internal void Release() { if (ThreadingHelper.VolatileRead(ref _capture).Flags.IsEmpty()) { _target = default(T); Thread.MemoryBarrier(); } }
/// <summary> /// Adds the specified key and associated value. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> /// <exception cref="System.ArgumentException">the key is already present</exception> public void Add(TKey key, TValue value) { bool result = false; int revision; while (true) { revision = _revision; if (IsOperationSafe()) { bool isCollision = false; var entries = ThreadingHelper.VolatileRead(ref _entriesNew); bool done = false; try { if (AddExtracted(key, value, entries, out isCollision) != -1) { result = true; } } finally { var isOperationSafe = IsOperationSafe(entries, revision); if (isOperationSafe) { if (result) { Interlocked.Increment(ref _count); done = true; } else { if (isCollision) { var oldStatus = Interlocked.CompareExchange(ref _status, (int)BucketStatus.GrowRequested, (int)BucketStatus.Free); if (oldStatus == (int)BucketStatus.Free) { _revision++; } } else { throw new ArgumentException("the key is already present"); } } } } if (done) { return; } } else { CooperativeGrow(); } } }
private void WaitCanWrite() { if (Thread.CurrentThread != ThreadingHelper.VolatileRead(ref _ownerThread)) { var check = Interlocked.CompareExchange(ref _master, -1, 0); while (true) { switch (check) { case -2: // Write mode already requested case -1: // There is another writer // Go to wait _freeToWrite.Wait(); check = Interlocked.CompareExchange(ref _master, -1, 0); break; case 0: // Free to proceed // GO! _freeToRead.Reset(); if (Interlocked.CompareExchange(ref _ownerThread, Thread.CurrentThread, null) == null) { // Success Interlocked.Increment(ref _writeCount); return; } else { // It was reserved by another thread break; } case 1: // There are readers currently // Requesting write mode check = Interlocked.CompareExchange(ref _master, -2, 1); if (check == 1) { _freeToRead.Reset(); check = -2; } break; } } } }
private bool CanRead() { if (Thread.CurrentThread == ThreadingHelper.VolatileRead(ref _ownerThread)) { Interlocked.Increment(ref _readCount); _currentReadingCount.Value++; return(true); } if (Interlocked.CompareExchange(ref _master, 1, 0) >= 0) { _freeToWrite.Reset(); Interlocked.Increment(ref _readCount); _currentReadingCount.Value++; return(true); } return(false); }
/// <summary> /// Adds the specified item at the front. /// </summary> /// <param name="item">The item.</param> public void Enqueue(T item) { bool result = false; while (true) { if (IsOperationSafe()) { var entries = ThreadingHelper.VolatileRead(ref _entriesNew); bool done = false; try { Interlocked.Increment(ref _workingThreads); if (entries.Enqueue(item)) { result = true; } } finally { Interlocked.Decrement(ref _workingThreads); if (result) { Interlocked.Increment(ref _count); done = true; } else { var oldStatus = Interlocked.CompareExchange(ref _status, (int)BucketStatus.GrowRequested, (int)BucketStatus.Free); if (oldStatus == (int)BucketStatus.Free) { _revision++; } } } if (done) { return; } } else { CooperativeGrow(); } } }
/// <summary> /// Tries to retrieve the key and associated value at the specified index. /// </summary> /// <param name="index">The index.</param> /// <param name="key">The key.</param> /// <param name="value">The value.</param> /// <returns> /// <c>true</c> if the value was retrieved; otherwise, <c>false</c>. /// </returns> public bool TryGet(int index, out TKey key, out TValue value) { value = default(TValue); key = default(TKey); bool result = false; int revision; while (true) { revision = _revision; if (IsOperationSafe()) { var entries = ThreadingHelper.VolatileRead(ref _entriesNew); bool done = false; try { TValue tmpValue; TKey tmpKey; if (TryGetExtracted(index, entries, out tmpKey, out tmpValue)) { key = tmpKey; value = tmpValue; result = true; } } finally { var isOperationSafe = IsOperationSafe(entries, revision); if (isOperationSafe) { done = true; } } if (done) { return(result); } } else { CooperativeGrow(); } } }
/// <summary> /// Removes the specified key. /// </summary> /// <param name="key">The key.</param> /// <returns> /// <c>true</c> if the specified key was removed; otherwise, <c>false</c>. /// </returns> public bool Remove(TKey key) { bool result = false; int revision; while (true) { revision = _revision; if (IsOperationSafe()) { var entries = ThreadingHelper.VolatileRead(ref _entriesNew); bool done = false; try { if (RemoveExtracted(key, entries)) { result = true; } } finally { var isOperationSafe = IsOperationSafe(entries, revision); if (isOperationSafe) { if (result) { Interlocked.Decrement(ref _count); } done = true; } } if (done) { return(result); } } else { CooperativeGrow(); } } }
/// <summary> /// Attempts to retrieve and remove the next item from the back. /// </summary> /// <param name="item">The item.</param> /// <returns> /// <c>true</c> if the item was taken; otherwise, <c>false</c>. /// </returns> public bool TryDequeue(out T item) { item = default(T); bool result = false; while (true) { if (IsOperationSafe()) { var entries = ThreadingHelper.VolatileRead(ref _entriesNew); bool done = false; try { Interlocked.Increment(ref _workingThreads); T tmpItem; if (entries.TryDequeue(out tmpItem)) { item = tmpItem; result = true; } } finally { Interlocked.Decrement(ref _workingThreads); if (result) { Interlocked.Decrement(ref _count); } done = true; } if (done) { return(result); } } else { CooperativeGrow(); } } }
/// <summary> /// Tries to retrieve the item at the specified index. /// </summary> /// <param name="index">The index.</param> /// <param name="item">The item.</param> /// <returns> /// <c>true</c> if the item was retrieved; otherwise, <c>false</c>. /// </returns> public bool TryGet(int index, out T item) { item = default(T); bool result = false; int revision; while (true) { revision = _revision; if (IsOperationSafe()) { var entries = ThreadingHelper.VolatileRead(ref _entriesNew); bool done = false; try { T tmpItem; if (TryGetExtracted(index, entries, out tmpItem)) { item = tmpItem; result = true; } } finally { var isOperationSafe = IsOperationSafe(entries, revision); if (isOperationSafe) { done = true; } } if (done) { return(result); } } else { CooperativeGrow(); } } }
/// <summary> /// Determines whether the specified key is contained. /// </summary> /// <param name="key">The key.</param> /// <returns> /// <c>true</c> if the specified key is contained; otherwise, <c>false</c>. /// </returns> public bool ContainsKey(TKey key) { bool result = false; int revision; while (true) { revision = _revision; if (IsOperationSafe()) { var entries = ThreadingHelper.VolatileRead(ref _entriesNew); bool done = false; try { if (ContainsKeyExtracted(key, entries)) { result = true; } } finally { var isOperationSafe = IsOperationSafe(entries, revision); if (isOperationSafe) { done = true; } } if (done) { return(result); } } else { CooperativeGrow(); } } }
/// <summary> /// Attempts to add the specified key and associated value. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> /// <returns>The value found in the destination after the attempt, regardless of collisions.</returns> public TValue TryAdd(TKey key, TValue value) { bool result = false; int revision; KeyValuePair <TKey, TValue> previous = default(KeyValuePair <TKey, TValue>); TValue found = value; while (true) { revision = _revision; if (IsOperationSafe()) { bool isCollision = false; var entries = ThreadingHelper.VolatileRead(ref _entriesNew); bool done = false; try { if (TryAddExtracted(key, value, entries, out previous) != -1) { result = true; } else { isCollision = !_keyComparer.Equals(previous.Key, key); } } finally { var isOperationSafe = IsOperationSafe(entries, revision); if (isOperationSafe) { if (result) { Interlocked.Increment(ref _count); done = true; } else { if (isCollision) { var oldStatus = Interlocked.CompareExchange(ref _status, (int)BucketStatus.GrowRequested, (int)BucketStatus.Free); if (oldStatus == (int)BucketStatus.Free) { _revision++; } } else { done = true; found = previous.Value; } } } } if (done) { return(found); } } else { CooperativeGrow(); } } }