 
 package weave.core
 {
+	import mx.core.mx_internal;
 	import mx.rpc.AsyncResponder;
 	import mx.rpc.AsyncToken;
 	import mx.rpc.events.FaultEvent;

		private function _handleFault(event:FaultEvent = null, asyncToken:AsyncToken = null):void
		{
			// stop if asyncToken is no longer relevant
			if (_pendingInvoke || _asyncToken != asyncToken)
				return;
			
			// no longer busy

	import weave.api.core.ICallbackCollection;
	import weave.api.core.IDisposableObject;
	import weave.api.core.ILinkableObject;
	
	/**
	 * Use this class to build dependency trees involving asynchronous calls.
	 * When the callbacks of a LinkablePromise are triggered, a function will be invoked.
	 * If the function returns an AsyncToken, LinkablePromise's callbacks will be triggered again when a ResultEvent or FaultEvent is received from the AsyncToken.
	 * Dependency trees can be built using newLinkableChild() and registerLinkableChild().
	 * 
	 * @see weave.api.core.ISessionManager#newLinkableChild()
	 * @see weave.api.core.ISessionManager#registerLinkableChild()
	 * @author adufilie
	 */
	public class LinkablePromise implements ILinkableObject, IDisposableObject
	{
		/**
		 * Creates a LinkablePromise from an iterative task function.
		 * @param asyncTask A function which is designed to be called repeatedly across multiple frames until it returns a value of 1.
		 * @param priority The task priority, which should be one of the static constants in WeaveAPI.
		 * @param description A description of the task.
		 * @see weave.api.core.IStageUtils#startTask()
		 */
		public static function fromIterativeTask(iterativeTask:Function, priority:uint, description:String = null, validateNow:Boolean = false):LinkablePromise
		{
			var promise:LinkablePromise;
			var asyncToken:AsyncToken;
			
			function asyncStart():AsyncToken
			{
				WeaveAPI.StageUtils.startTask(promise, iterativeTask, priority, asyncComplete);
				return asyncToken = new AsyncToken();
			}
			
			function asyncComplete():void
			{
				asyncToken.mx_internal::applyResult(ResultEvent.createEvent(null, asyncToken));
			}
			
			return promise = new LinkablePromise(asyncStart, null, description, validateNow);
		}
		
		/**
		 * @param task A function to invoke, which may return an AsyncToken.
		 * @param taskParams Parameters to pass to the task function.
		 * @param description A description of the task.
		 */
		public function LinkablePromise(task:Function, taskParams:Array = null, description:String = null, validateNow:Boolean = false)
		{
			_task = task;
			_taskParams = taskParams;
			_description = description;
			_callbackCollection = WeaveAPI.SessionManager.getCallbackCollection(this);
			_callbackCollection.addImmediateCallback(null, _immediateCallback);
			_callbackCollection.addGroupedCallback(null, _groupedCallback);
			if (validateNow)
				validate();
		}
		
		private var _task:Function;
		private var _taskParams:Array;
		private var _description:String;
		
		private var _callbackCollection:ICallbackCollection;
		private var _lazy:Boolean = true;
		private var _invalidated:Boolean = true;
		private var _asyncToken:AsyncToken;
		private var _selfTriggeredCount:uint = 0;
		private var _result:Object;
		private var _error:Object;
		
		/**
		 * The result of calling the invoke function.
		 * When this value is accessed, validate() will be called.
		 */
		public function get result():Object
		{
			validate();
			return _result;
		}
		
		/**
		 * The error that occurred calling the invoke function.
		 * When this value is accessed, validate() will be called.
		 */
		public function get error():Object
		{
			validate();
			return _error;
		}
		
		/**
		 * If this LinkablePromise is set to lazy mode, this will switch it to non-lazy mode and automatically invoke the async task when necessary.
		 */
		public function validate():void
		{
			if (!_lazy)
				return;
			
			_lazy = false;
			
			if (_invalidated)
				_callbackCollection.triggerCallbacks();
		}
		
		private function _immediateCallback():void
		{
