public bool Acquire(int id, StCancelArgs cargs)
 {
     m.Enter();
     try {
         if (permits >= id)
         {
             permits -= id;
             return(true);
         }
         while (true)
         {
             int lastTime = Environment.TickCount;
             cv.Wait(cargs);
             if (permits >= id)
             {
                 permits -= id;
                 return(true);
             }
             if (!cargs.AdjustTimeout(ref lastTime))
             {
                 return(false);
             }
         }
     } finally {
         m.Exit();
     }
 }
        public bool Offer(T data, StCancelArgs cargs)
        {
            m.WaitOne();
            try {
                if (buffer.Count < capacity)
                {
                    buffer.Enqueue(data);
                    nonEmpty.Pulse();
                    return(true);
                }
                while (true)
                {
                    int lastTime = Environment.TickCount;
                    nonFull.Wait(cargs);

                    if (buffer.Count < capacity)
                    {
                        buffer.Enqueue(data);
                        nonEmpty.Pulse();
                        return(true);
                    }
                    if (!cargs.AdjustTimeout(ref lastTime))
                    {
                        return(false);
                    }
                }
            } finally {
                m.Exit();
            }
        }
 public bool Poll(out T di, StCancelArgs cargs)
 {
     m.WaitOne();
     try {
         if (buffer.Count > 0)
         {
             di = buffer.Dequeue();
             nonFull.Pulse();
             return(true);
         }
         while (true)
         {
             int lastTime = Environment.TickCount;
             nonEmpty.Wait(cargs);
             if (buffer.Count > 0)
             {
                 di = buffer.Dequeue();
                 nonFull.Pulse();
                 return(true);
             }
             if (!cargs.AdjustTimeout(ref lastTime))
             {
                 di = default(T);
                 return(false);
             }
         }
     } finally {
         m.Exit();
     }
 }
Example #4
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 #5
0
		internal static bool WaitAll (StWaitable[] ws, StCancelArgs cargs)
		{
			if (ws == null) {
				throw new ArgumentNullException ("ws");
			}

			int nevts;
			int len = ws.Length;
			var sws = new StWaitable [len];

			int waitHint = SortAndCheckAllowAcquire (ws, sws, out nevts);

			if (waitHint < 0) {
				throw new DuplicateWaitObjectException ();
			}

			/*
			 * Return success if all synchronizers are notification events and are set.
			 */

			if (waitHint != 0) {
				if (nevts == 0) {
					return true;
				}
			} else if (cargs.Timeout == 0) {
				return false;
			}

			/*
			 * If a timeout was specified, get the current time in order
			 * to adjust the timeout value later, if we re-wait.
			 */

			int lastTime = (cargs.Timeout != Timeout.Infinite) ? Environment.TickCount : 0;
			StWaitBlock[] wbs = null;
			StWaitBlock[] hints = null;
			do {
				int inflated = 0;
				AbandonedMutexException ame = null;

				if (waitHint == 0) {

					if (wbs == null) {
						wbs = new StWaitBlock [len];
						hints = new StWaitBlock [len];
					}

					/*
					 * Create a parker for cooperative release, specifying as many
					 * releasers as the number of waitables. The parker is not reused
					 * because other threads may have references to it.
					 */

					var pk = new StParker (len);
					int inflatedCount = 0;

					int gsc = 1;
					int sc = 0;
					for (int i = 0; i < len; i++) {
						if ((wbs [i] = sws [i]._WaitAllPrologue (pk, ref hints [i], ref sc)) == null) {
							if (hints [i] == INFLATED) {
								inflated |= 1 << i;
								inflatedCount += 1;
							} else if (pk.TryLock ()) {
								pk.UnparkSelf (StParkStatus.StateChange);
							}
						} else if (gsc != 0) {
							if (sc == 0) {
								gsc = 0;
							} else if (sc > gsc) {
								gsc = sc;
							}
						}
					}

					if (inflatedCount > 0 && pk.TryLock (inflatedCount)) {
						pk.UnparkSelf (StParkStatus.StateChange);
					}
					
					int wst = pk.Park (gsc, cargs);

					/*
					 * We opt for a less efficient but simpler implementation instead
					 * of using the same approach as the WaitAny operation, because:
					 *  - When parking, the thread would have to call into the park spot
					 *    even if it was already unparked, since we have to wait for the
					 *    other handles as well;
					 *  - We would have to deal with cancellation in a different way,
					 *    relying on interrupts instead of the TryCancel/Unpark pair;
					 *  - The Unpark operation might not wake the target thread, which
					 *    could lead to bugs.
					 */ 

					if (wst == StParkStatus.StateChange && inflatedCount > 0) {
						if (!cargs.AdjustTimeout (ref lastTime)) {
							return false;
						}
						wst = InflatedWaitMultiple (ws, true, inflated, inflatedCount, cargs);
					}
				
					if (wst != StParkStatus.StateChange) {
						for (int i = 0; i < len; i++) {
							StWaitBlock wb = wbs [i];
							if (wb != null) {
								sws [i]._CancelAcquire (wb, hints [i]);
							}
						}

						if (wst == StParkStatus.Inflated) {
							waitHint = 0;
							continue;
						}

						cargs.ThrowIfException (wst);
						return false;
					}
				}

				/*
				 * All waitables where we inserted wait blocks seem to allow an 
				 * immediate acquire operation; so, try to acquire all non-inflated
				 * waitables that are not notification events.
				 */

				int idx;
				for (idx = 0; idx < nevts; idx++) {
					try {
						if ((inflated & (1 << idx)) == 0 && !sws[idx]._TryAcquire()) {
							break;
						}
					} catch (AbandonedMutexException e) {
						ame = e;
						ame.MutexIndex = idx;
					}
				}

				if (idx == nevts) {
					if (ame != null) {
						throw ame;
					}
					return true;
				}

				/*
				 * We failed to acquire all waitables, so undo the acquires
				 * that we did above.
				 */

				for (int i = idx + 1; i < nevts; ++i) {
					if ((inflated & (1 << idx)) != 0) {
						sws[i]._UndoAcquire ();	
					}
				}

				while (--idx >= 0) {
					sws[idx]._UndoAcquire ();
				}
				
				if (!cargs.AdjustTimeout (ref lastTime)) {
					return false;
				}

				waitHint = 0;
			} while (true);
		}