-
Notifications
You must be signed in to change notification settings - Fork 210
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Piotr Rżysko <piotr.rzysko@gmail.com>
- Loading branch information
1 parent
018d42e
commit 1a9cc70
Showing
14 changed files
with
209 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 55 additions & 0 deletions
55
...es-consumers/src/main/java/pl/allegro/tech/hermes/consumers/queue/FullDrainMpscQueue.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package pl.allegro.tech.hermes.consumers.queue; | ||
|
||
import org.jctools.queues.MessagePassingQueue; | ||
import org.jctools.queues.MpscArrayQueue; | ||
import org.slf4j.Logger; | ||
|
||
import static org.slf4j.LoggerFactory.getLogger; | ||
|
||
public class FullDrainMpscQueue<T> implements MpscQueue<T> { | ||
|
||
private static final Logger logger = getLogger(FullDrainMpscQueue.class); | ||
|
||
private final MpscArrayQueue<T> queue; | ||
|
||
public FullDrainMpscQueue(int capacity) { | ||
this.queue = new MpscArrayQueue<>(capacity); | ||
} | ||
|
||
@Override | ||
public boolean offer(T element) { | ||
return queue.offer(element); | ||
} | ||
|
||
/** | ||
* The {@link MpscArrayQueue#drain(MessagePassingQueue.Consumer)} method may skip items with allocated slots | ||
* by producers (who won CAS) but were not added to the queue yet. This may happend to broken elements chain. | ||
* See explanation at http://psy-lob-saw.blogspot.com/2014/07/poll-me-maybe.html | ||
* | ||
* This is an alternative approach which waits for all items to become available | ||
* by using {@link MpscArrayQueue#poll()} underneath (which spin-waits when getting next item). | ||
*/ | ||
@Override | ||
public void drain(MessagePassingQueue.Consumer<T> consumer) { | ||
int size = queue.size(); | ||
for (int i = 0; i < size; i++) { | ||
T element = queue.poll(); | ||
if (element != null) { | ||
consumer.accept(element); | ||
} else { | ||
logger.warn("Unexpected null value while draining queue [idx={}, size={}]", i, size); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public int size() { | ||
return queue.size(); | ||
} | ||
|
||
@Override | ||
public int capacity() { | ||
return queue.capacity(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
hermes-consumers/src/main/java/pl/allegro/tech/hermes/consumers/queue/MpscQueue.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package pl.allegro.tech.hermes.consumers.queue; | ||
|
||
import org.jctools.queues.MessagePassingQueue; | ||
|
||
public interface MpscQueue<T> { | ||
|
||
boolean offer(T element); | ||
|
||
void drain(MessagePassingQueue.Consumer<T> consumer); | ||
|
||
int size(); | ||
|
||
int capacity(); | ||
} |
33 changes: 33 additions & 0 deletions
33
...onsumers/src/main/java/pl/allegro/tech/hermes/consumers/queue/WaitFreeDrainMpscQueue.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package pl.allegro.tech.hermes.consumers.queue; | ||
|
||
import org.jctools.queues.MessagePassingQueue; | ||
import org.jctools.queues.MpscArrayQueue; | ||
|
||
public class WaitFreeDrainMpscQueue<T> implements MpscQueue<T> { | ||
|
||
private final MpscArrayQueue<T> queue; | ||
|
||
public WaitFreeDrainMpscQueue(int capacity) { | ||
this.queue = new MpscArrayQueue<>(capacity); | ||
} | ||
|
||
@Override | ||
public boolean offer(T element) { | ||
return queue.offer(element); | ||
} | ||
|
||
@Override | ||
public void drain(MessagePassingQueue.Consumer<T> consumer) { | ||
queue.drain(consumer); | ||
} | ||
|
||
@Override | ||
public int size() { | ||
return queue.size(); | ||
} | ||
|
||
@Override | ||
public int capacity() { | ||
return queue.capacity(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
...onsumers/src/test/java/pl/allegro/tech/hermes/consumers/queue/FullDrainMpscQueueTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package pl.allegro.tech.hermes.consumers.queue; | ||
|
||
public class FullDrainMpscQueueTest extends MpscQueuesAbstractTest { | ||
|
||
@Override | ||
protected <T> MpscQueue<T> createMpscQueue(int size) { | ||
return new FullDrainMpscQueue<>(size); | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
...onsumers/src/test/java/pl/allegro/tech/hermes/consumers/queue/MpscQueuesAbstractTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package pl.allegro.tech.hermes.consumers.queue; | ||
|
||
import org.junit.Test; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
public abstract class MpscQueuesAbstractTest { | ||
|
||
protected abstract <T> MpscQueue<T> createMpscQueue(int size); | ||
|
||
@Test | ||
public void shouldDrainItemsFromNonEmptyQueue() { | ||
// given | ||
MpscQueue<Integer> queue = createMpscQueue(16); | ||
assertThat(queue.capacity()).isEqualTo(16); | ||
|
||
// when | ||
queue.offer(1); | ||
queue.offer(2); | ||
queue.offer(3); | ||
|
||
// then | ||
assertThat(queue.size()).isEqualTo(3); | ||
|
||
// when | ||
List<Integer> drained = new ArrayList<>(); | ||
queue.drain(drained::add); | ||
|
||
// then | ||
assertThat(drained).contains(1, 2, 3); | ||
|
||
// and | ||
assertThat(queue.size()).isZero(); | ||
} | ||
|
||
@Test | ||
public void shouldDrainEmptyQueue() { | ||
// given | ||
MpscQueue<Integer> queue = createMpscQueue(16); | ||
|
||
// when | ||
List<Integer> drained = new ArrayList<>(); | ||
queue.drain(drained::add); | ||
|
||
// then | ||
assertThat(drained).isEmpty(); | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
...mers/src/test/java/pl/allegro/tech/hermes/consumers/queue/WaitFreeDrainMpscQueueTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package pl.allegro.tech.hermes.consumers.queue; | ||
|
||
public class WaitFreeDrainMpscQueueTest extends MpscQueuesAbstractTest { | ||
|
||
@Override | ||
protected <T> MpscQueue<T> createMpscQueue(int size) { | ||
return new WaitFreeDrainMpscQueue<>(size); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters