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

jadex.base.service.execution.AsyncExecutionService Maven / Gradle / Ivy

Go to download

The Jadex platform base package contains functionality useful for constructing platforms.

The newest version!
package jadex.base.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
{
//	//-------- static part --------
//	
//	public static MultiCollection	DEBUG	= new MultiCollection();
	
	//-------- attributes --------
	
	/** The threadpool. */
	protected IThreadPoolService threadpool;
	
	/** The currently waiting tasks (task->executor). */
	protected Map executors;
		
	/** The idle commands. */
//	protected Set idlecommands;
	protected Future idlefuture;
	
	/** The state. */
	protected boolean running;
	
	/** The shutdown flag. */
	protected boolean shutdown;
	
	/** The provider. */
	protected IServiceProvider provider;
	
	/** The executor cache. */
//	protected List executorcache;
	
	/** The maximum number of cached executors. */
//	protected int max;
	
	//-------- constructors --------
	
	/**
	 *  Create a new asynchronous executor service. 
	 * /
	public AsyncExecutorService(IThreadPool threadpool)
	{
		this(threadpool, 100);
	}*/
	
	/**
	 *  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.threadpool = threadpool;
//		this.max = max;
		this.running	= false;
		this.executors	= SCollection.createHashMap();
//		this.executors	= SCollection.createWeakHashMap();
//		this.executorcache = SCollection.createArrayList();
	}

	//-------- 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)
	{	
//		synchronized(DEBUG)
//		{
//			DEBUG.put(task, "execute called");
//		}
//		System.out.println("execute called: "+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)
		{
//			synchronized(DEBUG)
//			{
//				DEBUG.put(task, "creating executor");
//			}
//			System.out.println("Created executor for:"+task);
//			if(executorcache.size()>0)
//			{
//				exe = (Executor)executorcache.remove(0);
//				exe.setExecutable(task);
//			}
//			else
//			{
				exe = new Executor(threadpool, task)
				{
//					// Hack!!! overwritten for debugging.
//					protected boolean code()
//					{
//						synchronized(DEBUG)
//						{
//							DEBUG.put(task, "executing code(): "+this);
//						}
//						boolean	ret	= super.code();
//						synchronized(DEBUG)
//						{						
//							DEBUG.put(task, "code() finished: "+this);
//						}
//						return ret;
//					}
					
					// Hack!!! overwritten to know, when executor ends.
					public void run()
					{
						super.run();
						
//						ICommand[]	commands	= null;
						Future idf = null;
						
						synchronized(AsyncExecutionService.this)
						{
							synchronized(this)
							{
								// isRunning() refers to running state of executor!
								// Do not remove when a new executor has already been added for the task.
								if(!this.isRunning() && executors!=null && executors.get(task)==this)	
								{
									idf	= removeTask(task);
								}
							}
						}
						
						if(idf!=null)
							idf.setResult(null);
						
//						for(int i=0; commands!=null && i 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)
					{
						Future	idf;
						// todo: do not call listener with holding lock
						synchronized(AsyncExecutionService.this)
						{
							ret.setResult(result);
							idf	= removeTask(task);
						}
						if(idf!=null)
							idf.setResult(null);
					}
	
					public void exceptionOccurred(Exception exception)
					{
						Future	idf;
						// todo: do not call future with holding lock
						synchronized(AsyncExecutionService.this)
						{
							ret.setException(exception);
							idf	= removeTask(task);
						}
						if(idf!=null)
							idf.setResult(null);
						
					}
				};
				exe.shutdown().addResultListener(lis);
	//			executors.remove(task);
			}
			else
			{
				ret.setResult(null);
			}
		}
		
		return ret;
	}
	
	/**
	 *  Get the currently running or waiting tasks.
	 */
	public synchronized IExecutable[]	getTasks()
	{
		return (IExecutable[])executors.keySet().toArray(new IExecutable[executors.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;
//								new RuntimeException("AsyncExecustionService.start()").printStackTrace();
								
								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);
//								ret.setResult(getServiceIdentifier());
							}
							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.
						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;
	}
	
//	/**
//	 *  Add a command to be executed whenever the executor
//	 *  is idle (i.e. no executables running).
//	 */
//	public void addIdleCommand(ICommand command)
//	{
//		if(idlecommands==null)
//		{
//			synchronized(this)
//			{
//				if(idlecommands==null)
//				{
//					idlecommands	= SCollection.createLinkedHashSet();
//				}
//			}
//		}
//		
//		idlecommands.add(command);
//	}
//
//	/**
//	 *  Remove a previously added idle command.
//	 */
//	public synchronized void removeIdleCommand(ICommand command)
//	{
//		if(idlecommands!=null)
//			idlecommands.remove(command);
//	}

	//-------- helper methods --------
	
	/**
	 *  Remove a task from the execution queue.
	 *  Must be called while holding service lock.
	 *  @return	An idle future to be notified (if any) after releasing service lock.
	 */
	protected Future	removeTask(IExecutable task)
	{
		Future	ret	= null;
		
//		System.out.println("Removing executor for: "+task+", "+this);
		if(executors!=null)
		{
			executors.remove(task); // weak for testing
	//		setExecutable(null);
	//		if(executorcache.size()




© 2015 - 2024 Weber Informatics LLC | Privacy Policy