
jadex.platform.service.execution.AsyncExecutionService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jadex-platform Show documentation
Show all versions of jadex-platform Show documentation
The Jadex platform package contains implementations of
platform services as well as the platform component itself.
The newest version!
package jadex.platform.service.execution;
import jadex.bridge.service.BasicService;
import jadex.bridge.service.IServiceProvider;
import jadex.bridge.service.search.SServiceProvider;
import jadex.bridge.service.types.execution.IExecutionService;
import jadex.bridge.service.types.threadpool.IThreadPoolService;
import jadex.commons.collection.SCollection;
import jadex.commons.concurrent.Executor;
import jadex.commons.concurrent.IExecutable;
import jadex.commons.future.CounterResultListener;
import jadex.commons.future.DelegationResultListener;
import jadex.commons.future.Future;
import jadex.commons.future.IFuture;
import jadex.commons.future.IResultListener;
import java.util.Map;
/**
* The asynchronous executor service that executes all tasks in separate executors.
*/
public class AsyncExecutionService extends BasicService implements IExecutionService
{
//-------- attributes --------
/** The threadpool. */
protected IThreadPoolService threadpool;
/** The currently waiting tasks (task->executor). */
protected Map executors;
/** The idle future. */
protected Future idlefuture;
/** The state. */
protected boolean running;
/** The shutdown flag. */
protected boolean shutdown;
/** The provider. */
protected IServiceProvider provider;
/** The running (i.e. non-blocked) executors. */
protected Map runningexes;
//-------- constructors --------
/**
* Create a new asynchronous executor service.
*/
public AsyncExecutionService(IServiceProvider provider)//, int max)
{
this(provider, null);
}
/**
* Create a new asynchronous executor service.
*/
public AsyncExecutionService(IServiceProvider provider, Map properties)//, int max)
{
super(provider.getId(), IExecutionService.class, properties);
this.provider = provider;
this.running = false;
this.executors = SCollection.createHashMap();
this.runningexes = SCollection.createHashMap();
}
//-------- methods --------
/**
* Execute a task in its own thread.
* @param task The task to execute.
* (called from arbitrary threads)
*/
public synchronized void execute(final IExecutable task)
{
if(!customIsValid())
throw new RuntimeException("Not running: "+task);
if(shutdown)
throw new RuntimeException("Shutting down: "+task);
Executor exe = executors.get(task);
if(exe==null)
{
exe = new Executor(threadpool, task)
{
// Hack!!! overwritten to know, when executor ends.
public void run()
{
synchronized(AsyncExecutionService.this)
{
runningexes.put(task, this);
}
super.run();
Future idf = null;
synchronized(AsyncExecutionService.this)
{
synchronized(this)
{
// Do not remove when a new executor has already been added for the task.
// isRunning() refers to running state of executor!
if(!this.isRunning() && executors!=null && executors.get(task)==this)
{
if(executors!=null && this.getThreadCount()==0)
{
executors.remove(task);
}
runningexes.remove(task);
idf = checkIdleFuture();
}
else if(executors!=null && executors.get(task)!=this && runningexes.get(task)==this)
{
runningexes.remove(task);
}
}
}
if(idf!=null)
{
idf.setResult(null);
}
}
};
executors.put(task, exe);
}
if(running)
{
boolean exec = exe.execute();
if(exec)
{
runningexes.put(task, exe);
}
}
}
/**
* Cancel a task. Triggers the task to
* be not executed in future.
* @param task The task to execute.
* @param listener The listener.
*/
public synchronized IFuture cancel(final IExecutable task)
{
// todo: repair me: problem is that method can interfere with execute?!
final Future ret = new Future();
if(!customIsValid())
{
ret.setException(new RuntimeException("Shutting down."));
}
else
{
final Executor exe = (Executor)executors.get(task);
if(exe!=null)
{
IResultListener lis = new IResultListener()
{
public void resultAvailable(Void result)
{
// todo: do not call listener with holding lock
synchronized(AsyncExecutionService.this)
{
ret.setResult(result);
if(executors!=null)
{
executors.remove(task);
}
}
}
public void exceptionOccurred(Exception exception)
{
// todo: do not call future with holding lock
synchronized(AsyncExecutionService.this)
{
ret.setException(exception);
if(executors!=null)
{
executors.remove(task);
}
}
}
};
exe.shutdown().addResultListener(lis);
}
else
{
ret.setResult(null);
}
}
return ret;
}
/**
* Get the currently running tasks.
*/
public synchronized IExecutable[] getRunningTasks()
{
return (IExecutable[])runningexes.keySet().toArray(new IExecutable[runningexes.size()]);
}
/**
* Start the execution service.
* Resumes all scheduled tasks.
*/
public synchronized IFuture startService()
{
final Future ret = new Future();
super.startService().addResultListener(new DelegationResultListener(ret)
{
public void customResultAvailable(Void result)
{
if(shutdown)
{
ret.setException(new RuntimeException("Cannot start: shutdowning service."));
}
else
{
SServiceProvider.getServiceUpwards(provider, IThreadPoolService.class)
.addResultListener(new IResultListener()
{
public void resultAvailable(IThreadPoolService result)
{
try
{
threadpool = result;
running = true;
if(!executors.isEmpty())
{
// Resume all suspended tasks.
IExecutable[] keys = (IExecutable[])executors.keySet()
.toArray(new IExecutable[executors.size()]);
for(int i=0; i idf = null;
synchronized(AsyncExecutionService.this)
{
idf = idlefuture;
idlefuture = null;
}
if(idf!=null)
idf.setResult(null);
}
ret.setResult(null);
}
catch(RuntimeException e)
{
ret.setException(e);
}
}
public void exceptionOccurred(Exception exception)
{
ret.setException(exception);
}
});
}
}
});
return ret;
}
/**
* Shutdown the executor service.
* // todo: make callable more than once
*/
public synchronized IFuture shutdownService()
{
final Future ret = new Future();
super.shutdownService().addResultListener(new DelegationResultListener(ret)
{
public void customResultAvailable(Void result)
{
if(shutdown)
{
ret.setException((new RuntimeException("Already shutdowned.")));
}
else
{
shutdown = true;
IExecutable[] keys = (IExecutable[])executors.keySet()
.toArray(new IExecutable[executors.size()]);
if(keys.length>0)
{
// One listener counts until all executors have shutdowned.
final IResultListener lis = new CounterResultListener(keys.length, new DelegationResultListener(ret));
for(int i=0; i getNextIdleFuture()
{
Future ret;
if(shutdown)
{
ret = new Future(new RuntimeException("Shutdown"));
}
else
{
if(idlefuture==null)
idlefuture = new Future();
ret = idlefuture;
}
return ret;
}
//-------- helper methods --------
/**
* Get the idle future if any and if service is idle.
* Must be called while holding service lock.
* @return An idle future to be notified (if any) after releasing service lock.
*/
protected Future checkIdleFuture()
{
Future ret = null;
// When no more executable threads, inform idle commands.
if(AsyncExecutionService.this.running && idlefuture!=null && runningexes.isEmpty())
{
ret = idlefuture;
idlefuture = null;
}
return ret;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy