All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.infinispan.distexec.DistributedExecutionCompletionService Maven / Gradle / Ivy

There is a newer version: 9.1.7.Final
Show newest version
package org.infinispan.distexec;

import java.util.Comparator;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;

import org.infinispan.commons.util.concurrent.FutureListener;
import org.infinispan.commons.util.concurrent.NotifyingFuture;
import org.infinispan.remoting.transport.Address;

/**
 * A {@link CompletionService} that uses a supplied {@link DistributedExecutorService} to execute
 * tasks. This class arranges that submitted tasks are, upon completion, placed on a queue
 * accessible using take. The class is lightweight enough to be suitable for transient use
 * when processing groups of tasks.
 * 

* This class must be used instead of a {@link ExecutorCompletionService} provided from * java.util.concurrent package. The {@link ExecutorCompletionService} may not be used since it * requires the use of a non serializable RunnableFuture object. * * @author William Burns * @author Vladimir Blagojevic */ public class DistributedExecutionCompletionService implements CompletionService { protected final DistributedExecutorService executor; protected final BlockingQueue> completionQueue; protected final QueueingListener listener; protected class QueueingListener implements FutureListener { @Override public void futureDone(Future future) { // This is a safe cast since this listener should only used // in this class completionQueue.add((NotifyingFuture)future); } } /** * Creates an ExecutorCompletionService using the supplied executor for base task execution and a * {@link LinkedBlockingQueue} as a completion queue. * * @param executor * the executor to use * @throws NullPointerException * if executor is null */ public DistributedExecutionCompletionService(DistributedExecutorService executor) { this(executor, null); } /** * Creates an ExecutorCompletionService using the supplied executor for base task execution and * the supplied queue as its completion queue. * * Note: {@link PriorityBlockingQueue} for completionQueue can only be used with accompanying * {@link Comparator} as our internal implementation of {@link Future} for each subtask does not * implement Comparable interface. Note that we do not provide any guarantees about which * particular internal class implements Future interface and these APIs will remain internal. * * @param executor * the executor to use * @param completionQueue * the queue to use as the completion queue normally one dedicated for use by this * service * @throws NullPointerException * if executor is null */ public DistributedExecutionCompletionService(DistributedExecutorService executor, BlockingQueue> completionQueue) { if (executor == null) throw new NullPointerException(); this.executor = executor; if (completionQueue == null) { this.completionQueue = new LinkedBlockingQueue>(); } else { this.completionQueue = completionQueue; } this.listener = new QueueingListener(); } /** * {@inheritDoc CompletionService} *

* This future object may not be used as a NotifyingFuture. That is because * internally this class sets the listener to provide ability to add to the queue. */ @Override public Future submit(Callable task) { if (task == null) throw new NullPointerException(); NotifyingFuture f = (NotifyingFuture) executor.submit(task); f.attachListener(listener); return f; } /** * {@inheritDoc CompletionService} *

* This future object may not be used as a NotifyingFuture. That is because * internally this class sets the listener to provide ability to add to the queue. */ @Override public Future submit(Runnable task, V result) { if (task == null) throw new NullPointerException(); NotifyingFuture f = (NotifyingFuture) executor.submit(task, result); f.attachListener(listener); return f; } /** * {@inheritDoc CompletionService} *

* This future may safely be used as a NotifyingFuture if desired. This * is because if it tries to set a listener it will be called immediately * since the task has already been completed. */ @Override public NotifyingFuture take() throws InterruptedException { return completionQueue.take(); } /** * {@inheritDoc CompletionService} *

* This future may safely be used as a NotifyingFuture if desired. This * is because if it tries to set a listener it will be called immediately * since the task has already been completed. */ @Override public NotifyingFuture poll() { return completionQueue.poll(); } /** * {@inheritDoc CompletionService} *

* This future may safely be used as a NotifyingFuture if desired. This * is because if it tries to set a listener it will be called immediately * since the task has already been completed. */ @Override public NotifyingFuture poll(long timeout, TimeUnit unit) throws InterruptedException { return completionQueue.poll(timeout, unit); } public Future submit(Callable task, K... input) { NotifyingFuture f = executor.submit(task, input); f.attachListener(listener); return f; } public List> submitEverywhere(Callable task) { List> fl = executor.submitEverywhere(task); for (Future f : fl) { ((NotifyingFuture) f).attachListener(listener); } return fl; } public List> submitEverywhere(Callable task, K... input) { List> fl = executor.submitEverywhere(task, input); for (Future f : fl) { ((NotifyingFuture) f).attachListener(listener); } return fl; } public Future submit(Address target, Callable task) { NotifyingFuture f = executor.submit(target, task); f.attachListener(listener); return f; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy