/**
   * Adds target requirements to the graph. The requirements are queued and the call returns;
   * construction of the graph will happen on a background thread (if additional threads is
   * non-zero), or when the call to {@link #getDependencyGraph} is made. If it was not possible to
   * satisfy one or more requirements that must be checked after graph construction is complete.
   *
   * <p>The caller must ensure that the same requirement is not passed multiple times to the
   * builder. Depending on scheduling and memory availability, the cases may be identified and
   * coalesced (by {@link GraphBuildingContext#resolveRequirement}) into a single logical operation.
   * Alternatively the resolutions may run to completion to include terminal outputs in the result.
   * If the function library contains an ambiguity or other aspect that means the resolved value
   * specification could differ this will result in an invalid dependency graph.
   *
   * @param requirements requirements to add, not null and not containing nulls.
   */
  public void addTarget(final Collection<ValueRequirement> requirements) {
    ArgumentChecker.noNulls(requirements, "requirements");

    // Check that the market data availability provider, the function resolver and the calc config
    // name are non-null
    checkInjectedInputs();

    // Use the context as a build complete lock so that housekeeping thread cannot observe a "built"
    // state within this atomic block of work
    synchronized (getContext()) {
      for (final ValueRequirement requirement : requirements) {
        addTargetImpl(requirement);
      }
    }
    // If the run-queue was empty, we may not have started enough threads, so double check
    startBackgroundConstructionJob();
  }
  /**
   * Adds a target requirement to the graph. The requirement is queued and the call returns;
   * construction of the graph will happen on a background thread (if additional threads is
   * non-zero), or when the call to {@link #getDependencyGraph} is made. If it was not possible to
   * satisfy the requirement that must be checked after graph construction is complete.
   *
   * <p>The caller must ensure that the same requirement is not passed multiple times to the
   * builder. Depending on scheduling and memory availability, the cases may be identified and
   * coalesced (by {@link GraphBuildingContext#resolveRequirement}) into a single logical operation.
   * Alternatively the resolutions may run to completion to include terminal outputs in the result.
   * If the function library contains an ambiguity or other aspect that means the resolved value
   * specification could differ this will result in an invalid dependency graph.
   *
   * @param requirement requirement to add, not null
   */
  public void addTarget(final ValueRequirement requirement) {
    ArgumentChecker.notNull(requirement, "requirement");

    // Check that the market data availability provider, the function resolver and the calc config
    // name are non-null
    checkInjectedInputs();

    // Use the context as a build complete lock so that housekeeping thread cannot observe a "built"
    // state within this atomic block of work
    synchronized (getContext()) {
      // Add the value requirement to the graph (actually adds a suitable resolution task to the run
      // queue)
      addTargetImpl(requirement);
    }
    // If the run-queue was empty, we won't have started a thread, so double check
    startBackgroundConstructionJob();
  }