Example #1
0
		internal bool SlowEnter (StCancelArgs cargs)
		{
			int lastTime = (cargs.Timeout != Timeout.Infinite) ? Environment.TickCount : 0;
			StWaitBlock wb = null;
			do {
				int sc = spinCount;
#if NET_4_0
				var spinWait = new SpinWait ();
#endif
				do {
					if (state == FREE &&
					    Interlocked.CompareExchange (ref state, BUSY, FREE) == FREE) {
						return true;
					}
					if (top != null || sc-- <= 0) {
						break;
					}
#if NET_4_0
					spinWait.SpinOnce ();
#else
					Thread.SpinWait (1);
#endif
				} while (true);


				if (wb == null) {
					wb = new StWaitBlock (1);
				} else {
					wb.parker.Reset ();
				}

				do {
					StWaitBlock t;
					wb.next = t = top;
					if (Interlocked.CompareExchange (ref top, wb, t) == t) {
						break;
					}
				} while (true);

				if (TryEnter ()) {
					wb.parker.SelfCancel ();
					return true;
				}

				int ws = wb.parker.Park (cargs);

				if (ws != StParkStatus.Success) {
					cargs.ThrowIfException (ws);
					return false;
				}

				if (TryEnter ()) {
					return true;
				}
				
				if (!cargs.AdjustTimeout (ref lastTime)) {
					return false;
				}
			} while (true);
		}
Example #2
0
		internal StMutant (bool initialState, int sc)
		{
			head = tail = new StWaitBlock ();
			if (initialState) {
				head.next = SET;
			}
			spinCount = Environment.ProcessorCount > 0 ? sc : 0;
		}
Example #3
0
		internal override StWaitBlock _WaitAnyPrologue (StParker pk, int key,
		                                                ref StWaitBlock hint, ref int sc)
		{
			StWaitBlock wb = null;
			do {
				if (_TryAcquire ()) {
					return null;
				}

				if (wb == null) {
					wb = new StWaitBlock (pk, WaitType.WaitAny, 1, key);
				}

				if (EnqueueWaiter (wb, out hint)) {
					sc = hint == head ? spinCount : 0;
					return wb;
				}
				
				if (head.next == INFLATED) {
					return null;
				}
			} while (true);
		}
Example #4
0
 internal void Enqueue(StWaitBlock wb) {
     if (head == null) {
         head = wb;
     } else {
         tail.next = wb;
     }
     tail = wb;
 }
Example #5
0
 internal bool CasNext (StWaitBlock n, StWaitBlock nn)
  {
      return (next == n && Interlocked.CompareExchange (ref next, nn, n) == n);
  }
Example #6
0
		internal override StWaitBlock _WaitAllPrologue (StParker pk, ref StWaitBlock hint,
		                                                ref int sc)
		{
         if (_AllowsAcquire) {
            return null;
         }
                
			var wb = new StWaitBlock (pk, WaitType.WaitAll, 1, StParkStatus.StateChange);
         
         if (EnqueueWaiter (wb, out hint)) {
            sc = hint == head ? spinCount : 0;
            return wb;
         }

         return null;
		}
Example #7
0
		internal override void _CancelAcquire (StWaitBlock wb, StWaitBlock ignored)
		{
			CancelAcquire (wb);
		}
Example #8
0
		private void AdvanceTail (StWaitBlock t, StWaitBlock nt)
      {
			if (tail == t) {
				Interlocked.CompareExchange (ref tail, nt, t);
         }
      }
Example #9
0
     internal void SetHeadAndUnlock (StWaitBlock nh)
		{
			do {
				StWaitBlock w;
            if ((w = nh.next) == null || !w.parker.IsLocked || w.request < 0) {
               break;
            }
            nh.next = nh; // Mark old head's wait block as unlinked.
            nh = w;
         } while (true);

         head = nh;
         Interlocked.Exchange (ref qlock, FREE);
      }
Example #10
0
 internal void Init ()
 {
    head = tail = new StWaitBlock ();
 }
Example #11
0
		protected void AdvanceTail (StWaitBlock t, StWaitBlock nt)
		{
			if (t == tail) {
				Interlocked.CompareExchange (ref tail, nt, t);
			}
		}
Example #12
0
		internal override void _CancelAcquire (StWaitBlock wb, StWaitBlock hint)
		{
			while (hint.next == wb) {

				/*
				 * Remove the cancelled wait blocks that are at the front
				 * of the queue.
				 */

				StWaitBlock h;
				StWaitBlock hn = (h = head).next;

				if (hn == INFLATED) {
					return;
				}

				if (hn != null && hn != SET && hn.parker.IsLocked) {
					TryAdvanceHead (h, hn);
					continue;
				}

				/*
				 * If the queue is empty, return.
				 */

				StWaitBlock t, tn;
				if ((t = tail) == h) {
					return;
				}

				/*
				 * Do the necessary consistency checks before trying to
				 * unlink the wait block.
				 */

				if ((tn = t.next) != null) {
					AdvanceTail (t, tn);
					continue;
				}

				/*
				 * If the wait block is not at the tail of the queue, try
				 * to unlink it.
				 */

				if (wb != t) {
					StWaitBlock wbn;
					if ((wbn = wb.next) == wb || hint.CasNext (wb, wbn)) {
						return;
					}
				}

				/*
				 * The wait block is at the tail of the queue; so, take
				 * into account the *toUnlink* wait block.
				 */

				StWaitBlock dp;
				if ((dp = toUnlink) != null) {
					StWaitBlock d, dn;
					if ((d = dp.next) == dp ||
					    ((dn = d.next) != null && dp.CasNext (d, dn))) {
						CasToUnlink (dp, null);
					}
					if (dp == hint) {
						return; // *wb* is an already the saved node.
					}
				} else if (CasToUnlink (null, hint)) {
					return;
				}
			}
		}
Example #13
0
		protected abstract bool EnqueueWaiter (StWaitBlock wb, out StWaitBlock pred);
Example #14
0
		/*
		 * No need to worry about inflating as this is not called by Semaphore.
		 */

		internal bool TryWait (int acquireCount, StCancelArgs cargs)
		{
			if (acquireCount <= 0 || acquireCount > maximumCount) {
				throw new ArgumentException ("acquireCount");
			}

			if (TryAcquireInternal (acquireCount)) {
				return true;
			}

			if (cargs.Timeout == 0) {
				return false;
			}

			var wb = new StWaitBlock (WaitType.WaitAny, acquireCount);
			int sc = EnqueueAcquire (wb, acquireCount);

			int ws = wb.parker.Park (sc, cargs);
			if (ws == StParkStatus.Success) {
				return true;
			}

			CancelAcquire (wb);
			cargs.ThrowIfException (ws);
			return false;
		}
Example #15
0
		private void CancelAcquire (StWaitBlock wb)
		{
			/*
			 * If the wait block is still linked and it isn't the last wait block
			 * of the queue and the queue's lock is free unlink the wait block.
			 */

			StWaitBlock wbn;
			if ((wbn = wb.next) != wb && wbn != null && queue.TryLock ()) {
				queue.Unlink (wb);
				ReleaseWaitersAndUnlockQueue (null);
			}
		}
Example #16
0
		private int EnqueueAcquire (StWaitBlock wb, int acquireCount)
		{
			bool isFirst = queue.Enqueue (wb);

			/*
			 * If the wait block was inserted at the front of the queue and
			 * the current thread can now acquire the requested permits, try 
			 * to lock the queue and execute the release processing.
			 */

			if (isFirst && state >= acquireCount && queue.TryLock ()) {
				ReleaseWaitersAndUnlockQueue (wb);
			}

			return isFirst ? spinCount : 0;
		}
Example #17
0
		private void ReleaseWaitersAndUnlockQueue(StWaitBlock self) {
			do {
				StWaitBlock qh = queue.head;
				StWaitBlock  w;

				while (state > 0 && (w = qh.next) != null) {
					StParker pk = w.parker;

					if (w.waitType == WaitType.WaitAny) {
						if (!TryAcquireInternalQueued (w.request)) {
							break;
						}

						if (pk.TryLock ()) {
							if (w == self) {
								pk.UnparkSelf (w.waitKey);
							} else {
								pk.Unpark (w.waitKey);
							}
						} else {
							UndoAcquire (w.request);
						}
					} else if (pk.TryLock ()) {
						if (w == self) {
							pk.UnparkSelf (w.waitKey);
						} else {
							pk.Unpark (w.waitKey);
						}
					}

					qh.next = qh;
					qh = w;
				}

				queue.SetHeadAndUnlock (qh);
			} while (IsReleasePending);
		}
Example #18
0
        internal StWaitBlock Dequeue() {
            StWaitBlock wb;
            if ((wb = head) == null) {
                return null;
            }

            if ((head = wb.next) == null) {
                tail = null;
            }
            return wb;
        }
Example #19
0
        internal void Remove(StWaitBlock wb) {

            if (wb.next == wb) {
                return;
            }

            StWaitBlock p = head;
            StWaitBlock pv = null;
            while (p != null) {
                if (p == wb) {
                    if (pv == null) {
                        if ((head = wb.next) == null) {
                            tail = null;
                        }
                    } else {
                        if ((pv.next = wb.next) == null)
                            tail = pv;
                    }
                    wb.next = wb;
                    return;
                }
                pv = p;
                p = p.next;
            }
            
            throw new InvalidOperationException();
        }
Example #20
0
		protected bool TryAdvanceHead (StWaitBlock h, StWaitBlock nh)
		{
			if (h == head && Interlocked.CompareExchange (ref head, nh, h) == h) {
				h.next = h; // Mark the old head as unlinked.
				return true;
			}
			return false;
		}
Example #21
0
      internal bool Enqueue (StWaitBlock wb)
      {
         do {
				StWaitBlock t = tail;

				if (t == null) {
					wb.next = wb;
					return false; // Useful for the inflate operation.
				}

				StWaitBlock tn = t.next;

				if (tn != null) {
					AdvanceTail (t, tn);
					continue;
				}

				if (t.CasNext (null, wb)) {
					AdvanceTail (t, wb);
					return t == head;
				}
         } while (true);
      }
Example #22
0
		private bool CasToUnlink (StWaitBlock tu, StWaitBlock ntu)
		{
			return toUnlink == tu &&
			       Interlocked.CompareExchange (ref toUnlink, ntu, tu) == tu;
		}
Example #23
0
      internal void Unlink (StWaitBlock wb)
      {
         if (wb.next == wb || wb == head) {
            return;
         }

         StWaitBlock n;
         StWaitBlock pv = head;
         while ((n = pv.next) != wb) {
            if (n.parker.IsLocked) {
               pv.next = n.next;
               n.next = n;
            } else {
               pv = n;
            }
         }

         do {
            pv.next = n.next;
            n.next = n;
         } while ((n = pv.next).next != null && n.parker.IsLocked);
      }
Example #24
0
		internal override StWaitBlock _WaitAllPrologue (StParker pk, ref StWaitBlock hint,
																		ref int sc) {
			return _AllowsAcquire
				  ? null
			     : WaitPrologue(pk, WaitType.WaitAll, StParkStatus.StateChange, ref hint, ref sc);
		}
Example #25
0
		internal override StWaitBlock _WaitAnyPrologue (StParker pk, int key,
																		ref StWaitBlock hint, ref int sc)
		{
			return TryAcquireInternal (1)
				  ? null
			     : WaitPrologue(pk, WaitType.WaitAny, key, ref hint, ref sc);
		}
Example #26
0
		private StWaitBlock WaitPrologue (StParker pk, WaitType type, int key, 
													 ref StWaitBlock hint, ref int sc) 
		{
			if (state == SEM_INFLATED) {
				hint = INFLATED;
				return null;
			}

			var wb = new StWaitBlock (pk, type, 1, key);
			sc = EnqueueAcquire (wb, 1);
			
			if (state == SEM_INFLATED && pk.TryCancel ()) {
				pk.UnparkSelf (StParkStatus.Inflated);
				hint = INFLATED;
				return null;
			}

			return wb;
		}