Skip to content

Commit

Permalink
[bcl]Switch BlockingCollection to do CAS over ints and not longs.
Browse files Browse the repository at this point in the history
The reasoning behind doing CAS on longs was to avoid overflowing
which is not a problem because 2-completement math does the trick.

This is much more reliable than using longs on 32 bits.
  • Loading branch information
kumpera committed Sep 3, 2013
1 parent 0923ad6 commit 4f41e84
Showing 1 changed file with 9 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ namespace System.Collections.Concurrent
[ComVisible (false)]
[DebuggerDisplay ("Count={Count}")]
[DebuggerTypeProxy (typeof (CollectionDebuggerView<>))]
[StructLayout (LayoutKind.Sequential, Pack = 8)]
public class BlockingCollection<T> : IEnumerable<T>, ICollection, IEnumerable, IDisposable
{
const int spinCount = 5;
Expand All @@ -53,9 +52,7 @@ public class BlockingCollection<T> : IEnumerable<T>, ICollection, IEnumerable, I

readonly int upperBound;

int manualPadding;

long completeId;
int completeId;

/* The whole idea of the collection is to use these two long values in a transactional
* way to track and manage the actual data inside the underlying lock-free collection
Expand All @@ -64,8 +61,8 @@ public class BlockingCollection<T> : IEnumerable<T>, ICollection, IEnumerable, I
* They are manipulated with CAS and are guaranteed to increase over time and use
* of the instance thus preventing ABA problems.
*/
long addId = long.MinValue;
long removeId = long.MinValue;
int addId = int.MinValue;
int removeId = int.MinValue;


/* For time based operations, we share this instance of Stopwatch and base calculation
Expand Down Expand Up @@ -123,11 +120,12 @@ public bool TryAdd (T item, int millisecondsTimeout, CancellationToken cancellat
do {
cancellationToken.ThrowIfCancellationRequested ();

long cachedAddId = addId;
long cachedRemoveId = removeId;
int cachedAddId = addId;
int cachedRemoveId = removeId;
int itemsIn = cachedAddId - cachedRemoveId;

// If needed, we check and wait that the collection isn't full
if (upperBound != -1 && cachedAddId - cachedRemoveId > upperBound) {
if (upperBound != -1 && itemsIn > upperBound) {
if (millisecondsTimeout == 0)
return false;

Expand Down Expand Up @@ -212,8 +210,8 @@ bool TryTake (out T item, int milliseconds, CancellationToken cancellationToken,
do {
cancellationToken.ThrowIfCancellationRequested ();

long cachedRemoveId = removeId;
long cachedAddId = addId;
int cachedRemoveId = removeId;
int cachedAddId = addId;

// Empty case
if (cachedRemoveId == cachedAddId) {
Expand Down

0 comments on commit 4f41e84

Please sign in to comment.