public void missingSegments(Set<Integer> segments) {
   synchronized (this) {
     if (missingSegments == null) {
       missingSegments = segments;
     } else {
       missingSegments.addAll(segments);
     }
   }
   callback.onSegmentsLost(segments);
 }
 /**
  * @param origin
  * @param result
  * @return Whether this was the last expected response
  */
 public boolean lastResult(Address origin, R result) {
   Set<Integer> completedSegments = awaitingResponse.get(origin);
   if (missingSegments != null) {
     completedSegments.removeAll(missingSegments);
   }
   callback.onCompletion(origin, completedSegments, result);
   synchronized (this) {
     if (earlyTerminatePredicate != null && earlyTerminatePredicate.test(result)) {
       awaitingResponse.clear();
     } else {
       awaitingResponse.remove(origin);
     }
     return awaitingResponse.isEmpty();
   }
 }
 public void intermediateResults(Address origin, R intermediateResult) {
   callback.onIntermediateResult(origin, intermediateResult);
 }