You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2016/05/04 19:48:51 UTC

[06/15] incubator-tinkerpop git commit: Added support for Traversal interruption.

Added support for Traversal interruption.

Check for Thread.interrupted() in loops within steps and throw an unchecked TraversalInterruptedException. Would be better to throw InterruptedException but that would involve a breaking change which would be nice to avoid.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/0d4c07fd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/0d4c07fd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/0d4c07fd

Branch: refs/heads/TINKERPOP-1288
Commit: 0d4c07fd57dd1179c50d7acdedb21bb4e8e6ab52
Parents: 3e7d19d
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Mon Apr 18 08:50:33 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed May 4 06:43:35 2016 -0400

----------------------------------------------------------------------
 .../benchmark/util/AbstractBenchmarkBase.java   |  2 +-
 .../traversal/step/map/ComputerResultStep.java  |  2 +
 .../traversal/step/map/VertexProgramStep.java   |  2 +
 .../traversal/step/branch/LocalStep.java        |  2 +
 .../traversal/step/filter/FilterStep.java       |  2 +
 .../process/traversal/step/map/FlatMapStep.java |  2 +
 .../process/traversal/step/map/GraphStep.java   |  2 +
 .../process/traversal/step/map/MatchStep.java   |  2 +
 .../traversal/step/map/NoOpBarrierStep.java     |  2 +
 .../traversal/step/util/AbstractStep.java       |  3 ++
 .../traversal/step/util/ComputerAwareStep.java  |  2 +
 .../util/TraversalInterruptedException.java     |  9 +++++
 .../traversal/util/DefaultTraversalTest.java    | 41 ++++++++++++++++++++
 13 files changed, 72 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0d4c07fd/gremlin-benchmark/src/main/java/org/apache/tinkerpop/benchmark/util/AbstractBenchmarkBase.java
----------------------------------------------------------------------
diff --git a/gremlin-benchmark/src/main/java/org/apache/tinkerpop/benchmark/util/AbstractBenchmarkBase.java b/gremlin-benchmark/src/main/java/org/apache/tinkerpop/benchmark/util/AbstractBenchmarkBase.java
index 5b73045..2f8bb66 100644
--- a/gremlin-benchmark/src/main/java/org/apache/tinkerpop/benchmark/util/AbstractBenchmarkBase.java
+++ b/gremlin-benchmark/src/main/java/org/apache/tinkerpop/benchmark/util/AbstractBenchmarkBase.java
@@ -50,7 +50,7 @@ public abstract class AbstractBenchmarkBase {
     protected static final String DEFAULT_BENCHMARK_DIRECTORY = "./benchmarks/";
 
     protected static final String[] JVM_ARGS = {
-            "-server", "-Xms1g", "-Xmx1g"
+            "-server", "-Xms2g", "-Xmx2g"
     };
 
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0d4c07fd/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ComputerResultStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ComputerResultStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ComputerResultStep.java
index b5fd8e8..c8b56a2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ComputerResultStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/ComputerResultStep.java
@@ -25,6 +25,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException;
 import org.apache.tinkerpop.gremlin.structure.Element;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.Property;
@@ -62,6 +63,7 @@ public final class ComputerResultStep<S> extends AbstractStep<ComputerResult, S>
     @Override
     protected Traverser.Admin<S> processNextStart() throws NoSuchElementException {
         while (true) {
+            if(Thread.interrupted()) throw new TraversalInterruptedException();
             if (this.currentIterator.hasNext())
                 return this.currentIterator.next();
             else {

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0d4c07fd/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/VertexProgramStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/VertexProgramStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/VertexProgramStep.java
index f9e2936..ab095f2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/VertexProgramStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/VertexProgramStep.java
@@ -31,6 +31,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ProfileStep;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 
 import java.util.NoSuchElementException;
@@ -83,6 +84,7 @@ public abstract class VertexProgramStep extends AbstractStep<ComputerResult, Com
     protected boolean previousTraversalVertexProgram() {
         Step<?, ?> currentStep = this;
         while (!(currentStep instanceof EmptyStep)) {
+            if(Thread.interrupted()) throw new TraversalInterruptedException();
             if (currentStep instanceof TraversalVertexProgramStep)
                 return true;
             currentStep = currentStep.getPreviousStep();

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0d4c07fd/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/LocalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/LocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/LocalStep.java
index e2affd4..e0a6520 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/LocalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/LocalStep.java
@@ -24,6 +24,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
 import java.util.Collections;
@@ -61,6 +62,7 @@ public final class LocalStep<S, E> extends AbstractStep<S, E> implements Travers
             this.localTraversal.addStart(this.starts.next());
         }
         while (true) {
+            if(Thread.interrupted()) throw new TraversalInterruptedException();
             if (this.localTraversal.hasNext())
                 return this.localTraversal.getEndStep().next();
             else if (this.starts.hasNext()) {

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0d4c07fd/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/FilterStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/FilterStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/FilterStep.java
index e07d951..d264ec7 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/FilterStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/FilterStep.java
@@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.filter;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -34,6 +35,7 @@ public abstract class FilterStep<S> extends AbstractStep<S, S> {
     @Override
     protected Traverser.Admin<S> processNextStart() {
         while (true) {
+            if(Thread.interrupted()) throw new TraversalInterruptedException();
             final Traverser.Admin<S> traverser = this.starts.next();
             if (this.filter(traverser))
                 return traverser;

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0d4c07fd/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FlatMapStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FlatMapStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FlatMapStep.java
index 3d7dc24..ea66696 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FlatMapStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FlatMapStep.java
@@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.map;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException;
 import org.apache.tinkerpop.gremlin.util.iterator.EmptyIterator;
 
 import java.util.Iterator;
@@ -40,6 +41,7 @@ public abstract class FlatMapStep<S, E> extends AbstractStep<S, E> {
     @Override
     protected Traverser.Admin<E> processNextStart() {
         while (true) {
+            if(Thread.interrupted()) throw new TraversalInterruptedException();
             if (this.iterator.hasNext()) {
                 return this.head.split(this.iterator.next(), this);
             } else {

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0d4c07fd/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java
index 3f169b0..ea72fb3 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GraphStep.java
@@ -28,6 +28,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.GraphComputing;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
 import org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Element;
 import org.apache.tinkerpop.gremlin.structure.T;
@@ -125,6 +126,7 @@ public class GraphStep<S, E extends Element> extends AbstractStep<S, E> implemen
     @Override
     protected Traverser.Admin<E> processNextStart() {
         while (true) {
+            if(Thread.interrupted()) throw new TraversalInterruptedException();
             if (this.iterator.hasNext()) {
                 return this.isStart ? this.getTraversal().getTraverserGenerator().generate(this.iterator.next(), (Step) this, 1l) : this.head.split(this.iterator.next(), this);
             } else {

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0d4c07fd/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
index c6e3bbe..907764b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchStep.java
@@ -31,6 +31,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.Connec
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 
@@ -446,6 +447,7 @@ public final class MatchStep<S, E> extends ComputerAwareStep<S, Map<String, E>>
         @Override
         protected Traverser.Admin<Object> processNextStart() throws NoSuchElementException {
             while (true) {
+                if(Thread.interrupted()) throw new TraversalInterruptedException();
                 final Traverser.Admin traverser = this.starts.next();
                 // no end label
                 if (null == this.matchKey) {

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0d4c07fd/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/NoOpBarrierStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/NoOpBarrierStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/NoOpBarrierStep.java
index bedf078..cb2985b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/NoOpBarrierStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/NoOpBarrierStep.java
@@ -26,6 +26,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
 import org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
 import java.util.Collections;
@@ -64,6 +65,7 @@ public final class NoOpBarrierStep<S> extends AbstractStep<S, S> implements Loca
     @Override
     public void processAllStarts() {
         while (this.starts.hasNext() && (this.maxBarrierSize == Integer.MAX_VALUE || this.barrier.size() < this.maxBarrierSize)) {
+            if(Thread.interrupted()) throw new TraversalInterruptedException();
             final Traverser.Admin<S> traverser = this.starts.next();
             traverser.setStepId(this.getNextStep().getId()); // when barrier is reloaded, the traversers should be at the next step
             this.barrier.add(traverser);

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0d4c07fd/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
index 8ad847a..2f83e9e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/AbstractStep.java
@@ -22,6 +22,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.util.EmptyTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
 import java.util.Collections;
@@ -123,6 +124,7 @@ public abstract class AbstractStep<S, E> implements Step<S, E> {
             }
         } else {
             while (true) {
+                if(Thread.interrupted()) throw new TraversalInterruptedException();
                 final Traverser.Admin<E> traverser = this.processNextStart();
                 if (null != traverser.get() && 0 != traverser.bulk())
                     return this.prepareTraversalForNextStep(traverser);
@@ -137,6 +139,7 @@ public abstract class AbstractStep<S, E> implements Step<S, E> {
         else {
             try {
                 while (true) {
+                    if(Thread.interrupted()) throw new TraversalInterruptedException();
                     this.nextEnd = this.processNextStart();
                     if (null != this.nextEnd.get() && 0 != this.nextEnd.bulk())
                         return true;

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0d4c07fd/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ComputerAwareStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ComputerAwareStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ComputerAwareStep.java
index 5acff58..227ccf3 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ComputerAwareStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ComputerAwareStep.java
@@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.util;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.GraphComputing;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalInterruptedException;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import org.apache.tinkerpop.gremlin.util.iterator.EmptyIterator;
 
@@ -41,6 +42,7 @@ public abstract class ComputerAwareStep<S, E> extends AbstractStep<S, E> impleme
     @Override
     protected Traverser.Admin<E> processNextStart() throws NoSuchElementException {
         while (true) {
+            if(Thread.interrupted()) throw new TraversalInterruptedException();
             if (this.previousIterator.hasNext())
                 return this.previousIterator.next();
             this.previousIterator = this.traverserStepIdAndLabelsSetByChild ? this.computerAlgorithm() : this.standardAlgorithm();

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0d4c07fd/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalInterruptedException.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalInterruptedException.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalInterruptedException.java
new file mode 100644
index 0000000..216a762
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalInterruptedException.java
@@ -0,0 +1,9 @@
+package org.apache.tinkerpop.gremlin.process.traversal.util;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+
+/**
+ * Thrown if a {@link Traversal} is interrupted during execution. This is an unchecked exception.
+ */
+public class TraversalInterruptedException extends RuntimeException {
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/0d4c07fd/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalTest.java
index d252ccf..c1a4c6b 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/DefaultTraversalTest.java
@@ -28,17 +28,29 @@ import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier;
 import org.apache.tinkerpop.gremlin.util.function.HashSetSupplier;
+import org.hamcrest.CoreMatchers;
 import org.junit.Test;
 
 import java.util.Arrays;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.is;
+import static org.hamcrest.number.OrderingComparison.greaterThan;
+import static org.hamcrest.number.OrderingComparison.lessThan;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -46,6 +58,35 @@ import static org.junit.Assert.assertTrue;
 public class DefaultTraversalTest {
 
     @Test
+    public void shouldRespectThreadInterruption() throws Exception {
+        final AtomicBoolean exceptionThrown = new AtomicBoolean(false);
+        final AtomicInteger counter = new AtomicInteger(0);
+        final CountDownLatch startedIterating = new CountDownLatch(100);
+        final List<Integer> l = IntStream.range(0, 1000000).boxed().collect(Collectors.toList());
+        final Thread t = new Thread(() -> {
+            try {
+                __.inject(l).unfold().sideEffect(i -> {
+                    startedIterating.countDown();
+                    counter.incrementAndGet();
+                }).iterate();
+                fail("Traversal should have been interrupted");
+            } catch (Exception ex) {
+                exceptionThrown.set(ex instanceof TraversalInterruptedException);
+            }
+        });
+
+        t.start();
+        startedIterating.await();
+        t.interrupt();
+        t.join();
+
+        // ensure that some but not all of the traversal was iterated and that the right exception was tossed
+        assertThat(counter.get(), greaterThan(0));
+        assertThat(counter.get(), lessThan(1000000));
+        assertThat(exceptionThrown.get(), CoreMatchers.is(true));
+    }
+
+    @Test
     public void shouldCloneTraversalCorrectly() {
         final DefaultGraphTraversal<?, ?> original = new DefaultGraphTraversal<>();
         original.out().groupCount("m").values("name").count();