Esempio n. 1
0
 /// <summary>
 /// Returns the WaitEntry of the current thread
 /// </summary>
 /// <returns></returns>
 /// In order to avoid creation and destuction of WaitEntry
 /// objects each thread has its own WaitEntry object.
 private WaitEntry GetThreadWaitEntry()
 {
     if (null == _waitEntry)
     {
         _waitEntry = new WaitEntry();
     }
     _waitEntry.Reset();
     return(_waitEntry);
 }
Esempio n. 2
0
        private WaitEntry PopWaiter()
        {
            WaitEntry waitEntry = this._headWaitEntry._nextWaiterEntry;
            WaitEntry entry2    = waitEntry._nextWaiterEntry;

            this.RemoveWaiter(waitEntry, true);
            this._headWaitEntry._nextWaiterEntry = entry2;
            if (null != entry2)
            {
                entry2._prevWaiterEntry = this._headWaitEntry;
            }
            return(waitEntry);
        }
Esempio n. 3
0
        public WaitEntry CreateWaitHandle(ServerCommand condition)
        {
            if (!_waitEntryPool.TryPop(out var entry))
            {
                entry = new WaitEntry(this);
            }

            entry.Prepare(condition);

            lock (_waitHandles)
            {
                _waitHandles.AddLast(entry);
            }

            return(entry);
        }
Esempio n. 4
0
 public void PushWaitEntry(WaitEntry newWaiterEntry)
 {
     this.RemoveWaiter(newWaiterEntry, false);
     if (null == this._headWaitEntry._nextWaiterEntry)
     {
         this._headWaitEntry._nextWaiterEntry = newWaiterEntry;
         newWaiterEntry._prevWaiterEntry      = this._headWaitEntry;
     }
     else
     {
         WaitEntry entry = this._headWaitEntry._nextWaiterEntry;
         this._headWaitEntry._nextWaiterEntry = newWaiterEntry;
         newWaiterEntry._nextWaiterEntry      = entry;
         newWaiterEntry._prevWaiterEntry      = this._headWaitEntry;
         entry._prevWaiterEntry = newWaiterEntry;
     }
     this._waitersCount++;
 }
Esempio n. 5
0
        public WorkItem DequeueWorkItem(int millisecondsTimeout, WaitHandle cancelEvent)
        {
            WaitEntry      newWaiterEntry = null;
            WorkItem       workItem       = null;
            WorkItemsQueue queue;

            lock ((queue = this))
            {
                this.CheckDisposed();
                if (this._workItems.Count > 0)
                {
                    return(this._workItems.Dequeue() as WorkItem);
                }
                newWaiterEntry = this.GetThreadWaitEntry();
                this.PushWaitEntry(newWaiterEntry);
            }
            WaitHandle[] waitHandles = new WaitHandle[] { newWaiterEntry.WaitHandle, cancelEvent };
            int          num         = WaitHandle.WaitAny(waitHandles, millisecondsTimeout, true);

            lock ((queue = this))
            {
                bool flag = 0 == num;
                if (!flag)
                {
                    bool flag2 = newWaiterEntry.Timeout();
                    if (flag2)
                    {
                        this.RemoveWaiter(newWaiterEntry, false);
                    }
                    flag = !flag2;
                }
                if (flag)
                {
                    workItem = newWaiterEntry.WorkItem;
                    if (workItem == null)
                    {
                        workItem = this._workItems.Dequeue() as WorkItem;
                    }
                }
            }
            return(workItem);
        }
        /// <summary>
        /// Enqueue a work item to the queue.
        /// </summary>
        public bool EnqueueWorkItem(WorkItem workItem)
        {
            // A work item cannot be null, since null is used in the WaitForWorkItem() method to indicate timeout or cancel
            if (workItem == null)
            {
                throw new ArgumentNullException("workItem");
            }

            bool enqueue = true;

            // First check if there is a wait entry waiting for work item. During
            // the check, timed out waiters are ignored. If there is no waiter then the work item is queued.
            lock (this)
            {
                CheckDisposed();

                if (!_isWorkItemsQueueActive)
                {
                    return(false);
                }

                while (_waitersCount > 0)
                {
                    // Dequeue a waiter.
                    WaitEntry waitEntry = PopWaiter();
                    // Signal the waiter. On success break the loop
                    if (waitEntry.Signal(workItem))
                    {
                        enqueue = false;
                        break;
                    }
                }

                if (enqueue)
                {
                    // Enqueue the work item
                    _workItems.Enqueue(workItem);
                }
            }
            return(true);
        }
        /// <summary>
        /// Pop a waiter from the waiter's stack
        /// </summary>
        /// <returns>Returns the first waiter in the stack</returns>
        private WaitEntry PopWaiter()
        {
            // Store the current stack head
            WaitEntry oldFirstWaiterEntry = _headWaitEntry._nextWaiterEntry;

            // Store the new stack head
            WaitEntry newHeadWaiterEntry = oldFirstWaiterEntry._nextWaiterEntry;

            // Update the old stack head list links and decrement the number waiters.
            RemoveWaiter(oldFirstWaiterEntry, true);

            // Update the new stack head
            _headWaitEntry._nextWaiterEntry = newHeadWaiterEntry;
            if (null != newHeadWaiterEntry)
            {
                newHeadWaiterEntry._prevWaiterEntry = _headWaitEntry;
            }

            // Return the old stack head
            return(oldFirstWaiterEntry);
        }
        /// <summary>
        /// Remove a waiter from the stack
        /// </summary>
        /// <param name="WaitEntry">A waiter entry to remove</param>
        /// <param name="popDecrement">If true the waiter count is always decremented</param>
        private void RemoveWaiter(WaitEntry WaitEntry, bool popDecrement)
        {
            // Store the prev entry in the list
            WaitEntry prevWaiterEntry = WaitEntry._prevWaiterEntry;

            // Store the next entry in the list
            WaitEntry nextWaiterEntry = WaitEntry._nextWaiterEntry;

            // A flag to indicate if we need to decrement the waiters count.
            // If we got here from PopWaiter then we must decrement.
            // If we got here from PushWaitEntry then we decrement only if
            // the waiter was already in the stack.
            bool decrementCounter = popDecrement;

            // Null the waiter's entry links
            WaitEntry._prevWaiterEntry = null;
            WaitEntry._nextWaiterEntry = null;

            // If the waiter entry had a prev link then update it.
            // It also means that the waiter is already in the list and we
            // need to decrement the waiters count.
            if (null != prevWaiterEntry)
            {
                prevWaiterEntry._nextWaiterEntry = nextWaiterEntry;
                decrementCounter = true;
            }

            // If the waiter entry had a next link then update it.
            // It also means that the waiter is already in the list and we
            // need to decrement the waiters count.
            if (null != nextWaiterEntry)
            {
                nextWaiterEntry._prevWaiterEntry = prevWaiterEntry;
                decrementCounter = true;
            }
            if (decrementCounter)
            {
                --_waitersCount;
            }
        }
Esempio n. 9
0
        private void RemoveWaiter(WaitEntry WaitEntry, bool popDecrement)
        {
            WorkItemsQueue.WaitEntry entry  = WaitEntry._prevWaiterEntry;
            WorkItemsQueue.WaitEntry entry2 = WaitEntry._nextWaiterEntry;
            bool flag = popDecrement;

            WaitEntry._prevWaiterEntry = null;
            WaitEntry._nextWaiterEntry = null;
            if (null != entry)
            {
                entry._nextWaiterEntry = entry2;
                flag = true;
            }
            if (null != entry2)
            {
                entry2._prevWaiterEntry = entry;
                flag = true;
            }
            if (flag)
            {
                this._waitersCount--;
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Cleanup the work items queue, hence no more work items are allowed to be queued.
        /// </summary>
        private void Cleanup()
        {
            lock (this) {
                // Deactivate only once
                if (!_isWorkItemsQueueActive)
                {
                    return;
                }
                // Don't queue more work items
                _isWorkItemsQueueActive = false;

                foreach (WorkItem workItem in _workItems)
                {
                    workItem.DisposeState();
                }
                // Clear the work items that are already queued
                _workItems.Clear();
                while (_waitersCount > 0)
                {
                    WaitEntry WaitEntry = PopWaiter();
                    WaitEntry.Timeout();
                }
            }
        }
Esempio n. 11
0
		/// <summary>
		/// Remove a waiter from the stack
		/// </summary>
		/// <param name="WaitEntry">A waiter entry to remove</param>
		/// <param name="popDecrement">If true the waiter count is always decremented</param>
		private void RemoveWaiter(WaitEntry WaitEntry, bool popDecrement)
		{
			// Store the prev entry in the list
			WaitEntry prevWaiterEntry = WaitEntry._prevWaiterEntry;

			// Store the next entry in the list
			WaitEntry nextWaiterEntry = WaitEntry._nextWaiterEntry;

			// A flag to indicate if we need to decrement the waiters count.
			// If we got here from PopWaiter then we must decrement.
			// If we got here from PushWaitEntry then we decrement only if
			// the waiter was already in the stack.
			bool decrementCounter = popDecrement;

			// Null the waiter's entry links
			WaitEntry._prevWaiterEntry = null;
			WaitEntry._nextWaiterEntry = null;

			// If the waiter entry had a prev link then update it.
			// It also means that the waiter is already in the list and we
			// need to decrement the waiters count.
			if (null != prevWaiterEntry)
			{
				prevWaiterEntry._nextWaiterEntry = nextWaiterEntry;
				decrementCounter = true;
			}

			// If the waiter entry had a next link then update it.
			// It also means that the waiter is already in the list and we
			// need to decrement the waiters count.
			if (null != nextWaiterEntry)
			{
				nextWaiterEntry._prevWaiterEntry = prevWaiterEntry;
				decrementCounter = true;
			}
			if (decrementCounter)
				--_waitersCount;
		}
Esempio n. 12
0
		/// <summary>
		/// Push a new waiter into the waiter's stack
		/// </summary>
		/// <param name="newWaiterEntry">A waiter to put in the stack</param>
		public void PushWaitEntry(WaitEntry newWaiterEntry)
		{
			// Remove the waiter if it is already in the stack and 
			// update waiter's count as needed
			RemoveWaiter(newWaiterEntry, false);

			// If the stack is empty then newWaiterEntry is the new head of the stack 
			if (null == _headWaitEntry._nextWaiterEntry)
			{
				_headWaitEntry._nextWaiterEntry = newWaiterEntry;
				newWaiterEntry._prevWaiterEntry = _headWaitEntry;

			}
			else
			{
                // If the stack is not empty then put newWaiterEntry as the new head of the stack.
				// Save the old first waiter entry
				WaitEntry oldFirstWaiterEntry = _headWaitEntry._nextWaiterEntry;
				// Update the links
				_headWaitEntry._nextWaiterEntry = newWaiterEntry;
				newWaiterEntry._nextWaiterEntry = oldFirstWaiterEntry;
				newWaiterEntry._prevWaiterEntry = _headWaitEntry;
				oldFirstWaiterEntry._prevWaiterEntry = newWaiterEntry;
			}
			// Increment the number of waiters
			++_waitersCount;
		}
Esempio n. 13
0
		/// <summary>
		/// Returns the WaitEntry of the current thread
		/// </summary>
		/// <returns></returns>
		/// In order to avoid creation and destuction of WaitEntry
		/// objects each thread has its own WaitEntry object.
		private WaitEntry GetThreadWaitEntry()
		{
			if (null == _waitEntry)
			{
				_waitEntry = new WaitEntry();
			}
			_waitEntry.Reset();
			return _waitEntry;
		}
Esempio n. 14
0
        private bool WaitCore(int timeoutMs)
        {
            WaitEntry wait_entry      = new WaitEntry();
            bool      mutexLocked     = false;
            bool      waitEntryLocked = false;

            try {
                Monitor.try_enter_with_atomic_var(mutex, Timeout.Infinite, false, ref mutexLocked);

                if (pending_signals > 0)
                {
                    --pending_signals;
                    return(true);
                }

                wait_entry.condition = new object();
                wait_entry.previous  = null;
                wait_entry.next      = head;
                if (head != null)
                {
                    Unsafe.AsRef <WaitEntry> (head).previous = Unsafe.AsPointer <WaitEntry> (ref wait_entry);
                }
                head = Unsafe.AsPointer <WaitEntry> (ref wait_entry);
            }
            finally {
                if (mutexLocked)
                {
                    Monitor.Exit(mutex);
                }
            }

            try {
                Monitor.try_enter_with_atomic_var(wait_entry.condition, Timeout.Infinite, false, ref waitEntryLocked);
                if (!wait_entry.signaled)
                {
                    Monitor.Monitor_wait(wait_entry.condition, timeoutMs, false);
                }
            }
            finally {
                if (waitEntryLocked)
                {
                    Monitor.Exit(wait_entry.condition);
                }
            }

            mutexLocked = false;
            try {
                Monitor.try_enter_with_atomic_var(mutex, Timeout.Infinite, false, ref mutexLocked);

                if (!wait_entry.signaled)
                {
                    if (head == Unsafe.AsPointer <WaitEntry> (ref wait_entry))
                    {
                        head = wait_entry.next;
                    }
                    if (wait_entry.next != null)
                    {
                        Unsafe.AsRef <WaitEntry> (wait_entry.next).previous = wait_entry.previous;
                    }
                    if (wait_entry.previous != null)
                    {
                        Unsafe.AsRef <WaitEntry> (wait_entry.previous).next = wait_entry.next;
                    }
                }
            }
            finally {
                if (mutexLocked)
                {
                    Monitor.Exit(mutex);
                }
            }

            return(wait_entry.signaled);
        }