Skip to content

Commit

Permalink
longs should be enough for everybode.
Browse files Browse the repository at this point in the history
  • Loading branch information
drunkcod committed Nov 14, 2014
1 parent 99d8ac8 commit b9b6ab5
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 10 deletions.
22 changes: 12 additions & 10 deletions Source/Core/CircularQueue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,42 @@ namespace Cone.Core
public class CircularQueue<T>
{
readonly T[] buffer;
int nextAvailable = 0;
int lastWritten = -1;
int nextRead = 0;
public long nextAvailable = 0;
public long head = -1;
public long tail = 0;

public CircularQueue(int bufferSize) {
buffer = new T[bufferSize];
}

public bool TryEnqueue(T value) {
int claimed;
long claimed;
do {
claimed = nextAvailable;
if(buffer.Length <= (claimed - nextRead))
if(buffer.Length <= (claimed - tail))
return false;
} while(Interlocked.CompareExchange(ref nextAvailable, claimed + 1, claimed) != claimed);

buffer[claimed % buffer.Length] = value;

for(int spins = 1, prev = claimed - 1; Interlocked.CompareExchange(ref lastWritten, claimed, prev) != prev; ++spins) {
var prev = claimed - 1;
for(var spins = 1;
Interlocked.CompareExchange(ref head, claimed, prev) != prev; ++spins) {
Thread.SpinWait(spins);
}

return true;
}

public bool TryDeque(out T value) {
int pos;
long pos;
do {
pos = nextRead;
if(pos == nextAvailable) {
pos = tail;
if(head < pos) {
value = default(T);
return false;
}
} while(Interlocked.CompareExchange(ref nextRead, pos + 1, pos) != pos);
} while(Interlocked.CompareExchange(ref tail, pos + 1, pos) != pos);

value = buffer[pos % buffer.Length];
return true;
Expand Down
1 change: 1 addition & 0 deletions Specs/Cone.Specs/Cone.Specs.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
<Compile Include="ConeMethodClassifierSpec.cs" />
<Compile Include="Conesole\ConesoleConfigurationSpec.cs" />
<Compile Include="ConeTestNamerSpec.cs" />
<Compile Include="Core\CircularQueueSpec.cs" />
<Compile Include="Core\ConeAttributeProviderSpec.cs" />
<Compile Include="Core\ConeFixtureMethodCollectionSpec.cs" />
<Compile Include="Core\ConeFixtureSpec.cs" />
Expand Down
42 changes: 42 additions & 0 deletions Specs/Cone.Specs/Core/CircularQueueSpec.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Cone.Core
{
[Describe(typeof(CircularQueue<>))]
public class CircularQueueSpec
{
public void TryEnqueue_fails_when_at_capacity() {
var q = new CircularQueue<int>(1);
Assume.That(() => q.TryEnqueue(0));

Check.That(() => !q.TryEnqueue(1));
}

public void TryEnqueue_fails_if_write_catches_up_to_read() {
var q = new CircularQueue<int>(2);
int ignored;
Assume.That(() => q.TryEnqueue(0));
Assume.That(() => q.TryDeque(out ignored));

Assume.That(() => q.TryEnqueue(0));
Assume.That(() => q.TryEnqueue(1));
Check.That(() => !q.TryEnqueue(2));
}

public void is_first_in_first_out() {
var q = new CircularQueue<int>(2);

Assume.That(() => q.TryEnqueue(0));
Assume.That(() => q.TryEnqueue(1));

int value;
Check.That(
() => q.TryDeque(out value) && value == 0,
() => q.TryDeque(out value) && value == 1
);
}
}
}

0 comments on commit b9b6ab5

Please sign in to comment.