}
private boolean getAdditionalRequirementsAndPushResults(final GraphBuildingContext context, final FunctionApplicationWorker substituteWorker,
final Map<ValueSpecification, ValueRequirement> inputs, final ValueSpecification resolvedOutput, final Set<ValueSpecification> resolvedOutputs, final boolean lastWorkerResult) {
// the substituteWorker is not ref-counted from here
final ComputationTarget target = getComputationTarget(context);
Set<ValueRequirement> additionalRequirements = null;
try {
//DebugUtils.getAdditionalRequirements_enter();
additionalRequirements = getFunction().getFunction().getAdditionalRequirements(context.getCompilationContext(), target, inputs.keySet(), resolvedOutputs);
//DebugUtils.getAdditionalRequirements_leave();
} catch (Throwable t) {
//DebugUtils.getAdditionalRequirements_leave();
s_logger.warn("Exception thrown by getAdditionalRequirements", t);
context.exception(t);
}
if (additionalRequirements == null) {
s_logger.info("Function {} returned NULL for getAdditionalRequirements on {}", getFunction(), inputs);
final ResolutionFailure failure = functionApplication(context).requirements(inputs).getAdditionalRequirementsFailed();
if (substituteWorker != null) {
substituteWorker.storeFailure(failure);
substituteWorker.finished(context);
context.discardTaskProducing(resolvedOutput, getTask());
}
getWorker().storeFailure(failure);
return false;
}
if (additionalRequirements.isEmpty()) {
return pushResult(context, substituteWorker, inputs, resolvedOutput, resolvedOutputs, lastWorkerResult);
}
s_logger.debug("Resolving additional requirements for {} on {}", getFunction(), inputs);
final AtomicInteger lock = new AtomicInteger(1);
final ResolvedValueCallback callback = new ResolvedValueCallbackChain() {
private final AtomicBoolean _pumped = new AtomicBoolean(false);
@Override
public void failed(final GraphBuildingContext context, final ValueRequirement value, final ResolutionFailure failure) {
s_logger.info("Couldn't resolve additional requirement {} for {}", value, getFunction());
final ResolutionFailure additionalRequirement = functionApplication(context).requirements(inputs).additionalRequirement(value, failure);
getWorker().storeFailure(additionalRequirement);
if (substituteWorker != null) {
substituteWorker.storeFailure(additionalRequirement);
substituteWorker.finished(context);
context.discardTaskProducing(resolvedOutput, getTask());
}
if (!_pumped.getAndSet(true)) {
pump(context);
}
}
@Override
public void resolved(final GraphBuildingContext context, final ValueRequirement valueRequirement, final ResolvedValue resolvedValue, final ResolutionPump pump) {
s_logger.debug("Resolved additional requirement {} to {}", valueRequirement, resolvedValue);
inputs.put(resolvedValue.getValueSpecification(), valueRequirement);
if (pump != null) {
context.close(pump);
}
if (lock.decrementAndGet() == 0) {
s_logger.debug("Additional requirements complete");
if (!pushResult(context, substituteWorker, inputs, resolvedOutput, resolvedOutputs, lastWorkerResult)) {
pump(context);
}
}
}
@Override
public void recursionDetected() {
// No-op
}
@Override
public int cancelLoopMembers(final GraphBuildingContext context, final Map<Chain, Chain.LoopState> visited) {
int result = PumpingState.this.cancelLoopMembers(context, visited);
if (substituteWorker != null) {
result += substituteWorker.cancelLoopMembers(context, visited);
}
return result;
}
@Override
public String toString() {
return "AdditionalRequirements" + getObjectId() + "[" + getFunction() + ", " + inputs + "]";
}
};
String functionExclusionValueName = getValueRequirement().getValueName();
Collection<FunctionExclusionGroup> functionExclusion = null;
for (ValueRequirement inputRequirement : additionalRequirements) {
final ResolvedValueProducer inputProducer;
if ((inputRequirement.getValueName() == functionExclusionValueName) && inputRequirement.getTargetReference().equals(target.toSpecification())) {
if (functionExclusion == null) {
functionExclusion = getFunctionExclusion(context, getFunction().getFunction());
if (functionExclusion == null) {
functionExclusionValueName = null;
}