Skip to content

Commit

Permalink
Fixes #216: Size of SpscGrowableArrayQueue can exceeds max capacity
Browse files Browse the repository at this point in the history
Adjust producer limit in order to allow one more element to be added
in place of the unneeded JUMP when the max capacity producer buffer
has been allocated
  • Loading branch information
franz1981 committed Sep 8, 2018
1 parent 7ed3462 commit 53b3105
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 2 deletions.
Expand Up @@ -114,7 +114,7 @@ final boolean offerColdPath(
long currConsumerIndex = lvConsumerIndex();
// use lookAheadStep to store the consumer distance from final buffer
this.lookAheadStep = -(index - currConsumerIndex);
producerBufferLimit = currConsumerIndex + maxCapacity - 1;
producerBufferLimit = currConsumerIndex + maxCapacity;
}
else
{
Expand Down
Expand Up @@ -106,7 +106,7 @@ final boolean offerColdPath(final AtomicReferenceArray<E> buffer, final long mas
long currConsumerIndex = lvConsumerIndex();
// use lookAheadStep to store the consumer distance from final buffer
this.lookAheadStep = -(index - currConsumerIndex);
producerBufferLimit = currConsumerIndex + maxCapacity - 1;
producerBufferLimit = currConsumerIndex + maxCapacity;
} else {
producerBufferLimit = index + producerMask - 1;
adjustLookAheadStep(newCapacity);
Expand Down
Expand Up @@ -2,13 +2,17 @@

import org.jctools.queues.spec.ConcurrentQueueSpec;
import org.jctools.queues.spec.Ordering;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Queue;

import static org.hamcrest.Matchers.is;

@RunWith(Parameterized.class)
public class QueueSanityTestSpscGrowable extends QueueSanityTest
{
Expand All @@ -27,4 +31,30 @@ public static Collection<Object[]> parameters()
return list;
}

@Test
public void testSizeNeverExceedCapacity()
{
final SpscGrowableArrayQueue<Integer> q = new SpscGrowableArrayQueue<>(8, 16);
final Integer v = 0;
final int capacity = q.capacity();
for (int i = 0; i < capacity; i++)
{
Assert.assertTrue(q.offer(v));
}
Assert.assertFalse(q.offer(v));
Assert.assertThat(q.size(), is(capacity));
for (int i = 0; i < 6; i++)
{
Assert.assertEquals(v, q.poll());
}
//the consumer is left in the chunk previous the last and biggest one
Assert.assertThat(q.size(), is(capacity - 6));
for (int i = 0; i < 6; i++)
{
q.offer(v);
}
Assert.assertThat(q.size(), is(capacity));
Assert.assertFalse(q.offer(v));
}

}

0 comments on commit 53b3105

Please sign in to comment.