public ResolvedValueProducer declareTaskProducing( final ValueSpecification valueSpecification, final ResolveTask task, final ResolvedValueProducer producer) { do { final MapEx<ResolveTask, ResolvedValueProducer> tasks = getBuilder().getOrCreateTasks(valueSpecification); ResolvedValueProducer result = null; if (tasks != null) { ResolvedValueProducer discard = null; synchronized (tasks) { if (!tasks.isEmpty()) { if (tasks.containsKey(null)) { continue; } final Map.Entry<ResolveTask, ResolvedValueProducer> resolveTask = tasks.getHashEntry(task); if (resolveTask != null) { if (resolveTask.getKey() == task) { // Replace an earlier attempt from this task with the new producer discard = resolveTask.getValue(); producer.addRef(); // The caller already holds an open reference resolveTask.setValue(producer); result = producer; } else { // An equivalent task is doing the work result = resolveTask.getValue(); } result .addRef(); // Either the caller holds an open reference on the producer, or we've // got the task lock } } if (result == null) { final ResolvedValue value = getBuilder().getResolvedValue(valueSpecification); if (value != null) { result = new SingleResolvedValueProducer(task.getValueRequirement(), value); } } if (result == null) { // No matching tasks producer.addRef(); // Caller already holds open reference tasks.put(task, producer); result = producer; result.addRef(); // Caller already holds open reference (this is the producer) } } if (discard != null) { discard.release(this); } } else { final ResolvedValue value = getBuilder().getResolvedValue(valueSpecification); if (value != null) { result = new SingleResolvedValueProducer(task.getValueRequirement(), value); } } return result; } while (true); }
public void discardTask(final ResolveTask task) { // TODO: Could we post "discardTask" tasks to a queue and have them done in batches by a // ContextRunnable? do { final Map<ResolveTask, ResolveTask> tasks = getBuilder().getTasks(task.getValueRequirement()); if (tasks == null) { return; } synchronized (tasks) { if (tasks.containsKey(null)) { continue; } final int rc = task.getRefCount(); if (rc == 0) { // Not referenced by us by definition return; } if (rc != 1) { if (!task.isFinished()) { // Can't discard this -- something might be waiting on a result from it?? return; } } final ResolveTask removed = tasks.remove(task); if (removed == null) { // Task has already been discarded return; } if (removed != task) { // Task has already been discarded and replaced by an equivalent; don't discard that tasks.put(removed, removed); return; } } task.release(this); getBuilder().decrementActiveResolveTasks(); } while (true); }