示例#1
0
文件: Layer2d.cs 项目: chkn/cirrus
        // FIXME: Only render dirty rects
        public void Render(BoundingRect rect)
        {
            var ctx = Surface.GetDrawingContext ();
            ApplyTransform (ctx);

            // If we were alredy rendering, stop it
            if (renderFiber != null && renderFiber.Status == FutureStatus.Pending)
                renderFiber.Cancel ();

            renderFiber = Render (rect, ctx);

            // Render children last
            //foreach (var child in Children) {
            //	child.Render (rect.GetIntersection (child.Bounds));
            //}
        }
示例#2
0
 public FutureCancelledException(Future f)
     : base("This Future has been cancelled.")
 {
     CancelledFuture = f;
 }
示例#3
0
        protected bool Chain(Future f)
        {
            chained = f;

            // UBER IMPORTANTE! Must acquire reader lock on chained future's status to prevent race condition
            chained.status_lock.EnterReadLock ();
            try {

                if (chained.Status == FutureStatus.Pending) {

                    Unschedule ();
                    chained.OnComplete += Reschedule;
                    return true;
                }

            }
            finally {
                chained.status_lock.ExitReadLock ();
            }
            return false;
        }
示例#4
0
 protected void Reschedule(Future completed)
 {
     completed.OnComplete -= Reschedule;
     Schedule (thread);
 }
示例#5
0
文件: Future.cs 项目: chkn/cirrus
		// This method is thread-safe, however if this method is called from a different thread than
		//  this Future is scheduled on, it is not guaranteed that this Future will not be scheduled for execution
		//  until this method returns.
		// Additionally, unscheduling a Future from one Thread and then scheduling it to a DIFFERENT thread
		//  is currently not supported due to a race condition.
		protected internal void Unschedule ()
		{
			Future actual;
			var prev = Interlocked.Exchange<Future> (ref previous, null);
			if (prev == null) {
				// already unscheduled
				return;
			}
			
		unlink_next:
			// set next = null if next == this
			actual = Interlocked.CompareExchange<Future> (ref next, null, this);
			if (actual == this || actual == null) {
				// we were the only ones scheduled.. Thread.current_fiber will get set to null naturally.
				return;
			}

			// Set next.previous = previous
			actual = Interlocked.CompareExchange<Future> (ref actual.previous, prev, this);
			if (actual != this) {
				// someone just scheduled themselves b/w us and next (I think.. is there a possibility this would loop forever?)
				this.next = actual;
				goto unlink_next;
			}
			
			
			// Set previous.next = next
			Interlocked.CompareExchange<Future> (ref prev.next, next, this);
			
		}
示例#6
0
文件: Future.cs 项目: chkn/cirrus
		// This is thread-safe.
		protected internal void Schedule (Thread thread)
		{
			Future current, target, actual, potential;
			
		top:
			actual = Interlocked.CompareExchange<Future> (ref this.previous, this, null);
			if (actual != null)
				return; // already scheduled

			// Scheduling algorithm:
			// This must be done carefully, since other Futures may be concurrently (un)scheduling themselves
			// from different threads.
		
			// 1. Assume there are no currently scheduled fibers.
			//  Maintain circularity of the scheduler
			this.next = this;
			
		set_current_to_this:
			// 2. Slip ourselves in to the thread.current_fiber if there isn't any.
			//  Either way, also grabs current = thread.current_fiber
			current = Interlocked.CompareExchange<Future> (ref thread.current_fiber, this, null);
			
			// 2a. If there actually wasn't any previously scheduled fiber,
			//  we have to wake the thread up...
			if (current == null) {
				thread.Enabled.Set ();
				return;
			}
			
		//acquire_new_target:
			// 3. We really want the fiber scheduled *previously* to the current one
			//     (less likely to be unscheduled, for one)
			target = current.previous;
			
		find_new_current:
			// 3a. If we're unlucky, the current fiber was unscheduled during this time.
			//   Negotiate for a new current fiber (possibly this one)
			while (target == null) {
				potential = current.next;
				actual = Interlocked.CompareExchange<Future> (ref thread.current_fiber, potential, current);
				current = (actual == current? potential : actual);
				if (current == null)
					goto set_current_to_this;
				
				target = current.previous;	
			}
			
		begin_update:
			// 4. We can still update our fields without worry here because nobody points to us yet.
			this.next = current;
			this.previous = target;
			
			// 4a. Set current.previous = this
			actual = Interlocked.CompareExchange<Future> (ref current.previous, this, target);
			if (actual == null) {
				// current was unscheduled
				target = null;
				goto find_new_current;
			}
			if (actual != target) {
				// some other fiber beat us to the chase; or target unscheduled itself
				target = actual;
				goto begin_update;
			}
			
			// 4b. Set target.next = this
			actual = Interlocked.CompareExchange<Future> (ref target.next, this, current);
			if (actual == null) {
				// was only fiber and unscheduled itself
				goto top;
			}
			if ((actual != current) && (actual != this) && (actual != this.previous)) {
				// some other fiber beat us to the chase,
				// OR, more likely, a fiber is in the process of unscheduling itself b/w current & target.
				// this is ok if our previous has been updated too; otherwise ???
				throw new Exception ("should not be reached");
			}
		}