public void ParticipateUntil (Func<bool> predicate)
		{
			SpinWait sw = new SpinWait ();
			
			while (!predicate ())
				sw.SpinOnce ();
		}
Esempio n. 2
0
        public static void Run()
        {
            var queue = new ConcurrentQueue<int>();

            // begin
            var producer = Task.Run(() =>
            {
                foreach (var value in Enumerable.Range(1, 10000))
                {
                    queue.Enqueue(value);
                }
            });

            var consumer = Task.Run(() =>
            {
                var spinWait = new SpinWait();
                var value = 0;
                while (value != 10000)
                {
                    if (!queue.TryDequeue(out value))
                    {
                        spinWait.SpinOnce();
                        continue;
                    }
                    Logger.Log("Value: {0}", value);
                }
            });

            Task.WaitAll(producer, consumer);
            // end
        }
Esempio n. 3
0
        public static void RunSpinWaitTests()
        {
            SpinWait spinner = new SpinWait();

            spinner.SpinOnce();
            Assert.Equal(spinner.Count, 1);
        }
Esempio n. 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);
		}
    public void Enter() {
        // If calling thread already owns the lock, increment recursion count and return
        Int32 threadId = Thread.CurrentThread.ManagedThreadId;
        if (threadId == m_owningThreadId) { m_recursion++; return; }

        // The calling thread doesn't own the lock, try to get it
        SpinWait spinwait = new SpinWait();
        for (Int32 spinCount = 0; spinCount < m_spincount; spinCount++) {
            // If the lock was free, this thread got it; set some state and return
            if (Interlocked.CompareExchange(ref m_waiters, 1, 0) == 0) goto GotLock;

            // Black magic: give other threads a chance to run
            // in hopes that the lock will be released
            spinwait.SpinOnce();
        }

        // Spinning is over and the lock was still not obtained, try one more time
        if (Interlocked.Increment(ref m_waiters) > 1) {
            // Still contention, this thread must wait
            m_waiterLock.WaitOne(); // Wait for the lock; performance hit
            // When this thread wakes, it owns the lock; set some state and return
        }

        GotLock:
        // When a thread gets the lock, we record its ID and
        // indicate that the thread owns the lock once
        m_owningThreadId = threadId; m_recursion = 1;
    }
		public void ParallelForTestCase ()
		{
			ParallelTestHelper.Repeat (() => {
				int[] expected = Enumerable.Range (1, 1000).Select ((e) => e * 2).ToArray ();
				int[] actual = Enumerable.Range (1, 1000).ToArray ();
				SpinWait sw = new SpinWait ();
				
				Parallel.For (0, actual.Length, (i) => { actual[i] *= 2; sw.SpinOnce (); });
				
				CollectionAssert.AreEquivalent (expected, actual, "#1, same");
				CollectionAssert.AreEqual (expected, actual, "#2, in order");
			});
		}
Esempio n. 7
0
		public static bool SpinUntil (Func<bool> condition, int millisecondsTimeout)
		{
			SpinWait sw = new SpinWait ();
			Watch watch = Watch.StartNew ();

			while (!condition ()) {
				if (watch.ElapsedMilliseconds > millisecondsTimeout)
					return false;
				sw.SpinOnce ();
			}

			return true;
		}
Esempio n. 8
0
		public void EnterReadLock()
		{
			SpinWait sw = new SpinWait();
			do
			{
				while ((rwlock & (RwWrite | RwWait)) > 0)
					sw.SpinOnce();

				if ((Interlocked.Add(ref rwlock, RwRead) & (RwWait | RwWait)) == 0)
					return;

				Interlocked.Add(ref rwlock, -RwRead);
			} while (true);
		}
Esempio n. 9
0
 /// <summary>
 /// 循环工作
 /// </summary>
 private static void LoopWork()
 {
     var spinWait = new SpinWait();
     while (true)
     {
         lock (syncRoot)
         {
             foreach (var item in actions)
             {
                 item.Invoke();
             }
         }
         spinWait.SpinOnce();
     }
 }
Esempio n. 10
0
        public override Event Dequeue()
        {
            Event result = null;
            SpinWait spinWait = new SpinWait();

            while (!closing)
            {
                if (queue.TryDequeue(out result))
                {
                    break;
                }
                spinWait.SpinOnce();
            }

            return result;
        }
Esempio n. 11
0
        public static int SendWithTimeout(this ZmqSocket socket, byte[] buffer, int length, TimeSpan timeout)
        {
            var stopwatch = Stopwatch.StartNew();
            var spinWait = new SpinWait();
            int result;
            do
            {
                result = socket.Send(buffer, length, SocketFlags.DontWait);
                if (socket.SendStatus != SendStatus.TryAgain)
                    break;

                spinWait.SpinOnce();
            }
            while (stopwatch.Elapsed <= timeout);

            return result;
        }
Esempio n. 12
0
 public static bool SpinWaitForCondition(Func<bool> predicate, int timeout)
 {
     Thread.MemoryBarrier();
     var sw = new Stopwatch();
     var spin = new SpinWait();
     sw.Start();
     while (sw.ElapsedMilliseconds < timeout)
     {
         if (predicate())
         {
             sw.Stop();
             return true;
         }
         spin.SpinOnce();
     }
     sw.Stop();
     return false;
 }
        protected override void ConsumeItems( int count )
        {
            SpinWait spinWait = new SpinWait();
            int value;

            for ( int i = 0; i < count; )
            {
                if ( this.queue.TryDequeue( out value ) )
                {
                    i++;

                    spinWait.Reset();
                }
                else
                {
                    spinWait.SpinOnce();
                }
            }
        }
Esempio n. 14
0
		public void EnterWriteLock()
		{
			SpinWait sw = new SpinWait();
			do
			{
				int state = rwlock;
				if (state < RwWrite)
				{
					if (Interlocked.CompareExchange(ref rwlock, RwWrite, state) == state)
						return;
					state = rwlock;
				}
				// We register our interest in taking the Write lock (if upgradeable it's already done)
				while ((state & RwWait) == 0 && Interlocked.CompareExchange(ref rwlock, state | RwWait, state) != state)
					state = rwlock;
				// Before falling to sleep
				while (rwlock > RwWait)
					sw.SpinOnce();
			} while (true);
		}
Esempio n. 15
0
		public void EnterReadLock (ref bool taken)
		{
			if (taken)
				throw new ArgumentException ("taken", "taken needs to be set to false");

			SpinWait sw = new SpinWait ();
			bool cont = true;

			do {
				while ((rwlock & (RwWrite | RwWait)) > 0)
					sw.SpinOnce ();

				try {}
				finally {
					if ((Interlocked.Add (ref rwlock, RwRead) & (RwWait | RwWait)) == 0) {
						taken = true;
						cont = false;
					} else {
						Interlocked.Add (ref rwlock, -RwRead);
					}
				}
			} while (cont);
		}
Esempio n. 16
0
        /// <summary>
        /// Exists the semaphore the specified number of times
        /// </summary>
        /// <param name="releaseCount">The number of times to exit the semaphore</param>
        public void Release(int releaseCount)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException(this.GetType().Name);
            }
            if (releaseCount < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(releaseCount), "releaseCount should be positive");
            }
            if (_maxCount - CurrentCount < releaseCount)
            {
                throw new SemaphoreFullException();
            }

            int waiterAndWaitCountDiff = 0;
            int releaseCountForWait    = 0;
            int releaseCountLocFree    = releaseCount;

            if (_waitCount > 0)
            {
                waiterAndWaitCountDiff = GetWaiterAndWaitCountDiffAtomic();
                releaseCountForWait    = Math.Min(releaseCount, waiterAndWaitCountDiff); // Приоритет waiter'ам
                releaseCountLocFree    = releaseCount - releaseCountForWait;
            }

            TurboContract.Assert(releaseCountForWait >= 0, conditionString: "releaseCountForWait >= 0");
            TurboContract.Assert(releaseCountLocFree >= 0, conditionString: "releaseCountLocFree >= 0");
            TurboContract.Assert(releaseCountForWait + releaseCountLocFree == releaseCount, conditionString: "releaseCountForWait + releaseCountLocFree == releaseCount");

            // Сначала возврат в lockFree
            if (releaseCountLocFree > 0)
            {
                int currentCountLocFree = Interlocked.Add(ref _currentCountLockFree, releaseCountLocFree);
                TurboContract.Assert(currentCountLocFree > 0, conditionString: "currentCountLocFree > 0");
            }

            // Теперь возврат для waiter'ов. Если число waiter'ов увеличилось, то тоже нужно зайти в lock
            if (releaseCountForWait > 0 || (_waitCount > 0 && GetWaiterAndWaitCountDiffAtomic() > waiterAndWaitCountDiff))
            {
                lock (_lockObj)
                {
                    int waitCount               = _waitCount;
                    int currentCountForWait     = _currentCountForWait;
                    int nextCurrentCountForWait = currentCountForWait + releaseCountForWait;

                    // В идеале _waitCount == _currentCountForWait. Если нет, то предпринимаем действия
                    if (nextCurrentCountForWait > waitCount && releaseCountForWait > 0)
                    {
                        // Если слотов оказывается больше, то избыток возвращаем в _currentCountLocFree
                        int countForReturnToLockFree = Math.Min(releaseCountForWait, nextCurrentCountForWait - waitCount);
                        int currentCountLocFree      = Interlocked.Add(ref _currentCountLockFree, countForReturnToLockFree);
                        TurboContract.Assert(currentCountLocFree > 0, conditionString: "currentCountLocFree > 0");
                        releaseCountForWait -= countForReturnToLockFree;
                        releaseCountLocFree += countForReturnToLockFree;
                    }
                    else if (nextCurrentCountForWait < waitCount)
                    {
                        // Если меньше, то пытаемся захватить себе обратно

                        // Не можем забрать больше, чем было добавлено этим вызовом Release
                        int maxToRequestFromLockFree = Math.Min(releaseCountLocFree, waitCount - nextCurrentCountForWait);

                        if (maxToRequestFromLockFree > 0)
                        {
                            SpinWait spin = new SpinWait();
                            int      currentCountLocFree        = _currentCountLockFree;
                            int      countToRequestFromLockFree = Math.Min(currentCountLocFree, maxToRequestFromLockFree);
                            while (countToRequestFromLockFree > 0)
                            {
                                TurboContract.Assert(currentCountLocFree - countToRequestFromLockFree >= 0, conditionString: "currentCountLocFree - countToRequestFromLockFree >= 0");
                                if (Interlocked.CompareExchange(ref _currentCountLockFree, currentCountLocFree - countToRequestFromLockFree, currentCountLocFree) == currentCountLocFree)
                                {
                                    releaseCountForWait += countToRequestFromLockFree;
                                    releaseCountLocFree -= countToRequestFromLockFree;
                                    break;
                                }

                                spin.SpinOnce();
                                currentCountLocFree        = _currentCountLockFree;
                                countToRequestFromLockFree = Math.Min(currentCountLocFree, maxToRequestFromLockFree);
                            }
                        }
                    }

                    TurboContract.Assert(releaseCountForWait >= 0, conditionString: "releaseCountForWait >= 0");
                    TurboContract.Assert(releaseCountLocFree >= 0, conditionString: "releaseCountLocFree >= 0");
                    TurboContract.Assert(releaseCountForWait + releaseCountLocFree == releaseCount, conditionString: "releaseCountForWait + releaseCountLocFree == releaseCount");

                    if (releaseCountForWait > 0)
                    {
                        TurboContract.Assert(_currentCountForWait == currentCountForWait, conditionString: "_currentCountForWait == currentCountForWait");

                        currentCountForWait += releaseCountForWait;
                        TurboContract.Assert(currentCountForWait > 0, conditionString: "currentCountForWait > 0");

                        int waitersToNotify = Math.Min(currentCountForWait, waitCount);
                        for (int i = 0; i < waitersToNotify; i++)
                        {
                            Monitor.Pulse(_lockObj);
                        }

                        _currentCountForWait = currentCountForWait;
                    }
                }
            }
        }
Esempio n. 17
0
		public void EnterWriteLock (ref bool taken)
		{
			if (taken)
				throw new ArgumentException ("taken", "taken needs to be set to false");

			SpinWait sw = new SpinWait ();
			int state = rwlock;

			try {
				do {
					state = rwlock;
					if (state < RwWrite) {
						try {}
						finally {
							if (Interlocked.CompareExchange (ref rwlock, RwWrite, state) == state)
								taken = true;
						}
						if (taken)
							return;

						state = rwlock;
					}

					while ((state & RwWait) == 0 && Interlocked.CompareExchange (ref rwlock, state | RwWait, state) != state)
						state = rwlock;

					while (rwlock > RwWait)
						sw.SpinOnce ();
				} while (true);
			} finally {
				state = rwlock;
				if (!taken && (state & RwWait) != 0)
					Interlocked.CompareExchange (ref rwlock, state - RwWait, state);
			}
		}
        private void RunUploadLoop(
            BlobTransferContext transferContext,
            FileStream fileStream,
            int numThreads)
        {
            SpinWait spinWait = new SpinWait();

            while (!transferContext.IsComplete && !transferContext.CancellationToken.IsCancellationRequested)
            {
                if (!transferContext.IsReadingOrWriting)
                {
                    DoSequentialRead(transferContext, fileStream);
                }

                if (!transferContext.IsComplete &&
                    transferContext.NumInProgressUploadDownloads < numThreads)
                {
                    TryUploadingBlocks(transferContext);
                }
                spinWait.SpinOnce();
            }

            while (transferContext.NumInProgressUploadDownloads > 0 || transferContext.IsReadingOrWriting)
            {
                spinWait.SpinOnce();
            }

            //Release any buffers that are still in queue to be written to file but could not because there was
            // a complete signal for this file upload due to some error in the one of the other block uploads in the same transfer context.
            //If this is not cleaned, used buffers will hit the cap of 16 and future uploads will hang for lack of memory buffers.
            for (int currentBlock = transferContext.NextFileIOBlock; currentBlock <= transferContext.BlocksForFileIO.Count(); currentBlock++)
            {
                byte[] buffer = null;

                if (transferContext.BlocksForFileIO.TryGetValue(currentBlock, out buffer) && (buffer != null))
                {
                    try
                    {
                        transferContext.MemoryManager.ReleaseBuffer(buffer);
                    }
                    catch (ArgumentException ex)
                    {
                        Debug.WriteLine("Exception occured while releasing memory buffer ", ex.Message);
                    }

                }
            }
            foreach (var memoryStream in transferContext.BufferStreams.Values)
            {
                memoryStream.Dispose();
            }

            transferContext.OnComplete();
        }
            /// <summary>Tries to dequeue an element from the queue.</summary>
            public bool TryDequeue(out T item)
            {
                // Loop in case of contention...
                var spinner = new SpinWait();

                while (true)
                {
                    // Get the head at which to try to dequeue.
                    int currentHead = Volatile.Read(ref _headAndTail.Head);
                    int slotsIndex  = currentHead & _slotsMask;

                    // Read the sequence number for the head position.
                    int sequenceNumber = Volatile.Read(ref _slots[slotsIndex].SequenceNumber);

                    // We can dequeue from this slot if it's been filled by an enqueuer, which
                    // would have left the sequence number at pos+1.
                    int diff = sequenceNumber - (currentHead + 1);
                    if (diff == 0)
                    {
                        // We may be racing with other dequeuers.  Try to reserve the slot by incrementing
                        // the head.  Once we've done that, no one else will be able to read from this slot,
                        // and no enqueuer will be able to read from this slot until we've written the new
                        // sequence number. WARNING: The next few lines are not reliable on a runtime that
                        // supports thread aborts. If a thread abort were to sneak in after the CompareExchange
                        // but before the Volatile.Write, enqueuers trying to enqueue into this slot would
                        // spin indefinitely.  If this implementation is ever used on such a platform, this
                        // if block should be wrapped in a finally / prepared region.
                        if (Interlocked.CompareExchange(ref _headAndTail.Head, currentHead + 1, currentHead) == currentHead)
                        {
                            // Successfully reserved the slot.  Note that after the above CompareExchange, other threads
                            // trying to dequeue from this slot will end up spinning until we do the subsequent Write.
                            item = _slots[slotsIndex].Item;
                            if (!Volatile.Read(ref _preservedForObservation))
                            {
                                // If we're preserving, though, we don't zero out the slot, as we need it for
                                // enumerations, peeking, ToArray, etc.  And we don't update the sequence number,
                                // so that an enqueuer will see it as full and be forced to move to a new segment.
                                _slots[slotsIndex].Item = default(T);
                                Volatile.Write(ref _slots[slotsIndex].SequenceNumber, currentHead + _slots.Length);
                            }
                            return(true);
                        }
                    }
                    else if (diff < 0)
                    {
                        // The sequence number was less than what we needed, which means this slot doesn't
                        // yet contain a value we can dequeue, i.e. the segment is empty.  Technically it's
                        // possible that multiple enqueuers could have written concurrently, with those
                        // getting later slots actually finishing first, so there could be elements after
                        // this one that are available, but we need to dequeue in order.  So before declaring
                        // failure and that the segment is empty, we check the tail to see if we're actually
                        // empty or if we're just waiting for items in flight or after this one to become available.
                        bool frozen      = _frozenForEnqueues;
                        int  currentTail = Volatile.Read(ref _headAndTail.Tail);
                        if (currentTail - currentHead <= 0 || (frozen && (currentTail - FreezeOffset - currentHead <= 0)))
                        {
                            item = default(T);
                            return(false);
                        }

                        // It's possible it could have become frozen after we checked _frozenForEnqueues
                        // and before reading the tail.  That's ok: in that rare race condition, we just
                        // loop around again.
                    }

                    // Lost a race. Spin a bit, then try again.
                    spinner.SpinOnce();
                }
            }
Esempio n. 20
0
        /// <summary>
        /// Takes a moment-in-time snapshot of the deque.
        /// </summary>
        /// <returns>A list representing a moment-in-time snapshot of the deque.</returns>
        /// <remarks>
        /// The algorithm runs in linear O(n) time.
        ///
        /// This implementation relies on the following invariant:
        /// If at time t, x was the leftmost node and y was the rightmost node,
        /// regardless of how many nodes are pushed/popped from either end thereafter, the paths
        /// (a) x->a (obtained by traversing the deque recursively using a node's right pointer starting from x), and
        /// (b) y->b (obtained by traversing the deque recursively using a node's left pointer starting from y)
        /// will always have at least 1 node in common.
        ///
        /// This means that, for a given x and y, even if the deque is mutated during the algorithm's
        /// execution, we can always rebuild the original x-y sequence by finding a node c, common to both
        /// x->a and y->b paths, and merging the paths by the common node.
        /// </remarks>
        private List <T> ToList()
        {
            //try to grab a reference to a stable anchor (fast route)
            Anchor anchor = _anchor;

            anchor.Validate();

            //try to grab a reference to a stable anchor (slow route)
            if (anchor._status != DequeStatus.Stable)
            {
                var spinner = new SpinWait();
                do
                {
                    anchor = _anchor;
                    anchor.Validate();

                    spinner.SpinOnce();
                } while (anchor._status != DequeStatus.Stable);
            }

            var x = anchor._left;
            var y = anchor._right;

            //check if deque is empty
            if (x == null)
            {
                return(new List <T>());
            }

            //check if deque has only 1 item
            if (x == y)
            {
                return new List <T> {
                           x._value
                }
            }
            ;

            var xaPath  = new List <Node>();
            var current = x;

            while (current != null && current != y)
            {
                xaPath.Add(current);

                current = current._right;
            }

            /*
             * If the 'y' node hasn't been popped from the right side of the deque,
             * then we should still be able to find the original x-y sequence
             * using a node's right pointer.
             *
             * If 'current' does not equal 'y', then the 'y' node must have been popped by
             * another thread during the while loop and the traversal wasn't successful.
             */
            if (current == y)
            {
                xaPath.Add(current);
                return(xaPath.Select(node => node._value).ToList());
            }

            /*
             * If the 'y' node has been popped from the right end, we need to find all nodes that have
             * been popped from the right end and rebuild the original sequence.
             *
             * To do this, we need to traverse the deque from right to left (using a node's left pointer)
             * until we find a node c common to both x->a and y->b paths. Such a node is either:
             * (a) currently part of the deque or
             * (b) the last node of the x->a path (i.e., node 'a') or
             * (c) the last node to be popped from the left (if all nodes between 'x' and 'y' were popped from the deque).
             *
             * -- Predicate (a) --
             * A node belongs to the deque if node.left.right == node (except for the leftmost node) if the deque has > 1 nodes.
             * If the deque has exactly one node, we know we've found that node if:
             * (1) all nodes to its right in the x-y sequence don't fall under predicates (a), (b) and (c) and
             * (2) node.left == null
             *
             * -- Predicate (b) --
             * True for a node n if n == a
             *
             * -- Predicate (c) --
             * True for a node n if:
             * (1) all nodes to its right in the x-y sequence don't fall under predicates (a), (b) and (c) and
             * (2) node.left == null
             */
            current = y;
            var a      = xaPath.Last();
            var ycPath = new Stack <Node>();

            while (current._left != null &&
                   current._left._right != current &&
                   current != a)
            {
                ycPath.Push(current);
                current = current._left;
            }

            //this node is common to the list and the stack
            var common = current;

            ycPath.Push(common);

            /*
             * Merge the x->a and the y->c paths by the common node.
             * This is done by removing the nodes in x->a that come after c,
             * and appending all nodes in the y->c path in reverse order.
             * Since we used a LIFO stack to store all nodes in the y->c path,
             * we can simply iterate over it to reverse the order in which they were inserted.
             */
            var xySequence = xaPath
                             .TakeWhile(node => node != common)
                             .Select(node => node._value)
                             .Concat(
                ycPath.Select(node => node._value));

            return(xySequence.ToList());
        }
Esempio n. 21
0
        // Flushes the changes such that they are in sync with the FileStream bits (ones obtained
        // with the win32 ReadFile and WriteFile functions).  Need to call FileStream's Flush to
        // flush to the disk.
        // NOTE: This will flush all bytes before and after the view up until an offset that is a multiple
        //       of SystemPageSize.
        public void Flush(UIntPtr capacity)
        {
            unsafe
            {
                byte *firstPagePtr = null;
                try
                {
                    _viewHandle.AcquirePointer(ref firstPagePtr);

                    if (Interop.Kernel32.FlushViewOfFile((IntPtr)firstPagePtr, capacity))
                    {
                        return;
                    }

                    // It is a known issue within the NTFS transaction log system that
                    // causes FlushViewOfFile to intermittently fail with ERROR_LOCK_VIOLATION
                    // As a workaround, we catch this particular error and retry the flush operation
                    // a few milliseconds later. If it does not work, we give it a few more tries with
                    // increasing intervals. Eventually, however, we need to give up. In ad-hoc tests
                    // this strategy successfully flushed the view after no more than 3 retries.

                    int error = Marshal.GetLastWin32Error();
                    if (error != Interop.Errors.ERROR_LOCK_VIOLATION)
                    {
                        throw Win32Marshal.GetExceptionForWin32Error(error);
                    }

                    SpinWait spinWait = default;
                    for (int w = 0; w < MaxFlushWaits; w++)
                    {
                        int pause = (1 << w);  // MaxFlushRetries should never be over 30
                        Thread.Sleep(pause);

                        for (int r = 0; r < MaxFlushRetriesPerWait; r++)
                        {
                            if (Interop.Kernel32.FlushViewOfFile((IntPtr)firstPagePtr, capacity))
                            {
                                return;
                            }

                            error = Marshal.GetLastWin32Error();
                            if (error != Interop.Errors.ERROR_LOCK_VIOLATION)
                            {
                                throw Win32Marshal.GetExceptionForWin32Error(error);
                            }

                            spinWait.SpinOnce();
                        }
                    }

                    // We got to here, so there was no success:
                    throw Win32Marshal.GetExceptionForWin32Error(error);
                }
                finally
                {
                    if (firstPagePtr != null)
                    {
                        _viewHandle.ReleasePointer();
                    }
                }
            }
        }
        internal bool AtomicLoopStateUpdate(int newState, int illegalStates, ref int oldState)
        {
            SpinWait sw = new SpinWait();

            do
            {
                oldState = m_LoopStateFlags;
                if ((oldState & illegalStates) != 0) return false;
                if (Interlocked.CompareExchange(ref m_LoopStateFlags, oldState | newState, oldState) == oldState)
                {
                    return true;
                }
                sw.SpinOnce();
            } while (true);

        }
Esempio n. 23
0
        public static void TestCreationOptions(String ctorType)
        {
            ConcurrentExclusiveSchedulerPair schedPair = null;
            //Need to define the default values since these values are passed to the verification methods
            TaskScheduler scheduler          = TaskScheduler.Default;
            int           maxConcurrentLevel = Environment.ProcessorCount;

            //Based on input args, use one of the ctor overloads
            switch (ctorType.ToLower())
            {
            case "default":
                schedPair = new ConcurrentExclusiveSchedulerPair();
                break;

            case "scheduler":
                schedPair = new ConcurrentExclusiveSchedulerPair(scheduler);
                break;

            case "maxconcurrent":
                maxConcurrentLevel = 2;
                schedPair          = new ConcurrentExclusiveSchedulerPair(scheduler, maxConcurrentLevel);
                break;

            case "all":
                maxConcurrentLevel = Int32.MaxValue;
                schedPair          = new ConcurrentExclusiveSchedulerPair(scheduler, -1 /*MaxConcurrentLevel*/, -1 /*MaxItemsPerTask*/); //-1 gets converted to Int32.MaxValue
                break;

            default:
                throw new NotImplementedException(String.Format("The option specified {0} to create the ConcurrentExclusiveSchedulerPair is invalid", ctorType));
            }

            //Create the factories that use the exclusive scheduler and the concurrent scheduler. We test to ensure
            //that the ConcurrentExclusiveSchedulerPair created are valid by scheduling work on them.
            TaskFactory writers = new TaskFactory(schedPair.ExclusiveScheduler);
            TaskFactory readers = new TaskFactory(schedPair.ConcurrentScheduler);

            List <Task> taskList = new List <Task>(); //Store all tasks created, to enable wait until all of them are finished

            // Schedule some dummy work that should be run with as much parallelism as possible
            for (int i = 0; i < 50; i++)
            {
                //In the current design, when there are no more tasks to execute, the Task used by concurrentexclusive scheduler dies
                //by sleeping we simulate some non trivial work that takes time and causes the concurrentexclusive scheduler Task
                //to stay around for addition work.
                taskList.Add(readers.StartNew(() => { var sw = new SpinWait(); while (!sw.NextSpinWillYield)
                                                      {
                                                          sw.SpinOnce();
                                                      }
                                              }));
            }
            // Schedule work where each item must be run when no other items are running
            for (int i = 0; i < 10; i++)
            {
                taskList.Add(writers.StartNew(() => { var sw = new SpinWait(); while (!sw.NextSpinWillYield)
                                                      {
                                                          sw.SpinOnce();
                                                      }
                                              }));
            }

            //Wait on the tasks to finish to ensure that the ConcurrentExclusiveSchedulerPair created can schedule and execute tasks without issues
            foreach (var item in taskList)
            {
                item.Wait();
            }

            //verify that maxconcurrency was respected.
            if (ctorType == "maxconcurrent")
            {
                Assert.Equal(maxConcurrentLevel, schedPair.ConcurrentScheduler.MaximumConcurrencyLevel);
            }
            Assert.Equal(1, schedPair.ExclusiveScheduler.MaximumConcurrencyLevel);

            //verify that the schedulers have not completed
            Assert.False(schedPair.Completion.IsCompleted, "The schedulers should not have completed as a completion request was not issued.");

            //complete the scheduler and make sure it shuts down successfully
            schedPair.Complete();
            schedPair.Completion.Wait();

            //make sure no additional work may be scheduled
            foreach (var schedPairScheduler in new TaskScheduler[] { schedPair.ConcurrentScheduler, schedPair.ExclusiveScheduler })
            {
                Exception caughtException = null;
                try
                {
                    Task.Factory.StartNew(() => { }, CancellationToken.None, TaskCreationOptions.None, schedPairScheduler);
                }
                catch (Exception exc)
                {
                    caughtException = exc;
                }
                Assert.True(
                    caughtException is TaskSchedulerException && caughtException.InnerException is InvalidOperationException,
                    "Queueing after completion should fail");
            }
        }
            /// <summary>
            /// Attempts to pass the gate if it is open
            /// </summary>
            public MutuallyExclusiveGuard EnterClient(int timeout, CancellationToken token)
            {
                if (_isDisposed)
                {
                    throw new ObjectDisposedException(this.GetType().Name);
                }
                if (token.IsCancellationRequested)
                {
                    throw new OperationCanceledException(token);
                }

                try
                {
                    Interlocked.Increment(ref _waiterCount);

                    if (TryEnterClient()) // Always call TryEnterClient first
                    {
                        return(new MutuallyExclusiveGuard(this));
                    }

                    uint startTime = 0;
                    if (timeout > 0)
                    {
                        startTime = TimeoutHelper.GetTimestamp();
                    }
                    else if (timeout < -1)
                    {
                        timeout = Timeout.Infinite;
                    }

                    if (timeout != 0)
                    {
                        SpinWait sw = new SpinWait();
                        while (!_isDisposed)
                        {
                            int remainingWaitMilliseconds = Timeout.Infinite;
                            if (timeout != Timeout.Infinite)
                            {
                                remainingWaitMilliseconds = TimeoutHelper.UpdateTimeout(startTime, timeout);
                                if (remainingWaitMilliseconds <= 0)
                                {
                                    return(new MutuallyExclusiveGuard());
                                }
                            }

                            if (_event.Wait(remainingWaitMilliseconds, token) && !_isDisposed)
                            {
                                if (TryEnterClient())
                                {
                                    return(new MutuallyExclusiveGuard(this));
                                }

                                sw.SpinOnce(); // State swap perfromed before manipulations on _event => Should wait some time
                            }
                        }

                        if (_isDisposed)
                        {
                            throw new ObjectDisposedException(this.GetType().Name);
                        }
                    }

                    return(new MutuallyExclusiveGuard());
                }
                finally
                {
                    Interlocked.Decrement(ref _waiterCount);
                }
            }
Esempio n. 25
0
        private static void Run161()
        {
            if (_useDelay)
            {
                Thread.Sleep(_delayCount);
            }

            int count = 0;

            Console.WriteLine("=========================");
            var result = _redisClient4.FlushDBAsync().Result;

            Console.WriteLine($"Clear DB 0 - [{(result ? "SUCCEED" : "FAILED")}]!");
            var       tasks = new Task <bool> [frequence];
            Stopwatch sw    = new Stopwatch();

            //_beforeSw?.Invoke(title);
            Console.WriteLine("Start Run:");
            //Thread.Sleep(0);
            //Thread.Sleep(1000);
            sw.Start();

            Parallel.For(0, frequence, _options, (index) =>
            {
                var key      = index.ToString();
                tasks[index] = _redisClient161.SetAsync(key, key);
            });
            //Task.WaitAll(tasks);
            int      offset = 0;
            SpinWait wait   = default;

            while (offset != frequence - 1)
            {
                for (int i = offset; i < frequence; i++)
                {
                    if (tasks[i].IsCompleted)
                    {
                        offset = i;
                    }
                    else
                    {
                        break;
                    }
                }
                wait.SpinOnce();
            }
            sw.Stop();
            //Thread.Sleep(3000);
            //var checkTasks = new Task[frequence];
            //for (var a = 0; a < frequence; a += 1)
            //{
            //    var key = a.ToString();
            //    checkTasks[a] = Task.Run(() =>
            //    {
            //        var result = _stackExnchangeClient.StringGet(key);
            //        if (result != key)
            //        {
            //            Console.WriteLine(key);
            //            Console.WriteLine(result);
            //            Interlocked.Increment(ref count);
            //        }
            //    });
            //}
            //Task.WaitAll(checkTasks);
            //Console.WriteLine($"{title} (0-{frequence / 10000}W) : {sw.ElapsedTicks} SPAN! ");
            Console.WriteLine($"161 (0-{frequence / 10000}W) : {sw.ElapsedMilliseconds}ms! ");
            //Console.WriteLine($"Errors : {count} !");
            //if (count>0)
            //{
            //    Thread.Sleep(1000);
            //    for (var a = 0; a < frequence; a += 1)
            //    {
            //        var key = a.ToString();
            //        tasks[a] = Task.Run(() =>
            //        {
            //            var result = _stackExnchangeClient.StringGet(key);
            //            if (result != key)
            //            {
            //                Interlocked.Increment(ref count);
            //            }
            //        });
            //    }
            //    Task.WaitAll(tasks);
            //    Console.WriteLine($"Rechecking Errors : {count} !");
            //}
            Console.WriteLine("=========================\r\n");
        }
Esempio n. 26
0
        /// <summary>
        /// Stops the current <see cref="ThreadSetManager"/>
        /// </summary>
        /// <param name="waitForStop">Whether the current thread should be blocked until all processing threads are be completed</param>
        private void StopThreadManager(bool waitForStop)
        {
            if (this.IsStopRequestedOrStopped)
            {
                if (waitForStop)
                {
                    this.Join();
                }
            }

            ThreadSetManagerState prevState;

            if (!ChangeStateSafe(ThreadSetManagerState.StopRequested, out prevState))
            {
                if (prevState != ThreadSetManagerState.StartRequested)
                {
                    if (waitForStop)
                    {
                        this.Join();
                    }

                    return;
                }

                SpinWait sw = new SpinWait();
                while (State == ThreadSetManagerState.StartRequested)
                {
                    sw.SpinOnce();
                }

                if (!ChangeStateSafe(ThreadSetManagerState.StopRequested, out prevState))
                {
                    if (waitForStop)
                    {
                        this.Join();
                    }

                    return;
                }
            }

            _stopRequestedCancelation.Cancel();

            if (waitForStop && prevState != ThreadSetManagerState.Created)
            {
                for (int i = 0; i < _procThreads.Length; i++)
                {
                    if (_procThreads[i] != null)
                    {
                        _procThreads[i].Join();
                    }
                }
            }

            if (ActiveThreadCount == 0)
            {
                if (ChangeStateSafe(ThreadSetManagerState.Stopped, out prevState) && prevState == ThreadSetManagerState.StopRequested)
                {
                    _threadExitedEvent.Set();
                    Profiling.Profiler.ThreadSetManagerDisposed(this.Name, false);
                }
            }

            Debug.Assert(State == ThreadSetManagerState.StopRequested || State == ThreadSetManagerState.Stopped);
            Debug.Assert(!waitForStop || State == ThreadSetManagerState.Stopped);
        }
Esempio n. 27
0
        private void ThreadProcFunc()
        {
            CancellationToken token = GetCancellationToken();

            object state = null;

            try
            {
                Interlocked.Increment(ref _activeThreadCount);
                Profiling.Profiler.ThreadSetManagerThreadStart(this.Name, this.ActiveThreadCount, this.ThreadCount);

                state = this.Prepare();

                token.ThrowIfCancellationRequested();
                this.Process(state, token);
            }
            catch (OperationCanceledException opEx)
            {
                if (!token.IsCancellationRequested)
                {
                    ProcessThreadException(opEx);
                    throw;
                }
            }
            catch (Exception ex)
            {
                if (ex.GetType() == typeof(ThreadAbortException) || ex.GetType() == typeof(ThreadInterruptedException) || ex.GetType() == typeof(StackOverflowException) || ex.GetType() == typeof(OutOfMemoryException))
                {
                    throw;
                }

                ProcessThreadException(ex);
                throw;
            }
            finally
            {
                this.Finalize(state);

                int activeThreadCount = Interlocked.Decrement(ref _activeThreadCount);
                int exitedThreadCount = Interlocked.Increment(ref _exitedThreadCount);
                Debug.Assert(activeThreadCount >= 0);
                Debug.Assert(exitedThreadCount <= this.ThreadCount);

                if (exitedThreadCount >= this.ThreadCount || (activeThreadCount == 0 && IsStopRequested))
                {
                    // Вынуждены ждать
                    SpinWait sw = new SpinWait();
                    while (State == ThreadSetManagerState.StartRequested)
                    {
                        sw.SpinOnce();
                    }

                    ThreadSetManagerState prevState;
                    if (ChangeStateSafe(ThreadSetManagerState.AllThreadsExited, out prevState))
                    {
                        Debug.Assert(prevState == ThreadSetManagerState.Running);
                        _threadExitedEvent.Set();
                    }
                    else if (ChangeStateSafe(ThreadSetManagerState.Stopped, out prevState))
                    {
                        Debug.Assert(prevState == ThreadSetManagerState.StopRequested);
                        _threadExitedEvent.Set();
                        Profiling.Profiler.ThreadSetManagerDisposed(this.Name, false);
                    }
                }

                Profiling.Profiler.ThreadSetManagerThreadStop(this.Name, this.ActiveThreadCount, this.ThreadCount);
            }
        }
Esempio n. 28
0
        private object WaitForCompletion(bool snap)
        {
            ManualResetEvent waitHandle  = null;
            bool             createdByMe = false;
            bool             complete    = snap ? IsCompleted : InternalPeekCompleted;

            if (!complete)
            {
                // Not done yet, so wait:
                waitHandle = (ManualResetEvent)_event;
                if (waitHandle == null)
                {
                    createdByMe = LazilyCreateEvent(out waitHandle);
                }
            }

            if (waitHandle != null)
            {
                try
                {
                    GlobalLog.Print("LazyAsyncResult#" + Logging.HashString(this) + "::InternalWaitForCompletion() Waiting for completion _event#" + Logging.HashString(waitHandle));
                    waitHandle.WaitOne(Timeout.Infinite);
                }
                catch (ObjectDisposedException)
                {
                    // This can occur if this method is called from two different threads.
                    // This possibility is the trade-off for not locking.
                }
                finally
                {
                    // We also want to dispose the event although we can't unless we did wait on it here.
                    if (createdByMe && !_userEvent)
                    {
                        // Does _userEvent need to be volatile (or _event set via Interlocked) in order
                        // to avoid giving a user a disposed event?
                        ManualResetEvent oldEvent = (ManualResetEvent)_event;
                        _event = null;
                        if (!_userEvent)
                        {
                            oldEvent.Dispose();
                        }
                    }
                }
            }

            // A race condition exists because InvokeCallback sets _intCompleted before _result (so that _result
            // can benefit from the synchronization of _intCompleted).  That means you can get here before _result got
            // set (although rarely - once every eight hours of stress).  Handle that case with a spin-lock.

            SpinWait sw = new SpinWait();

            while (_result == DBNull.Value)
            {
                sw.SpinOnce();
            }

            GlobalLog.Print("LazyAsyncResult#" + Logging.HashString(this) + "::InternalWaitForCompletion() done: " +
                            (_result is Exception ? ((Exception)_result).Message : _result == null ? "<null>" : _result.ToString()));

            return(_result);
        }
Esempio n. 29
0
        private async void Connection_RequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
        {
            AppServiceDeferral Deferral = args.GetDeferral();

            try
            {
                AppServiceConnection ServerConnection;

                SpinWait  Spin  = new SpinWait();
                Stopwatch Watch = new Stopwatch();

                Watch.Start();

                while (!PairedConnections.TryGetValue(sender, out ServerConnection) && Watch.ElapsedMilliseconds < 5000)
                {
                    if (Spin.NextSpinWillYield)
                    {
                        await Task.Delay(500);
                    }
                    else
                    {
                        Spin.SpinOnce();
                    }
                }

                Watch.Stop();

                if (ServerConnection != null)
                {
                    AppServiceResponse ServerRespose = await ServerConnection.SendMessageAsync(args.Request.Message);

                    if (ServerRespose.Status == AppServiceResponseStatus.Success)
                    {
                        await args.Request.SendResponseAsync(ServerRespose.Message);
                    }
                    else
                    {
                        await args.Request.SendResponseAsync(new ValueSet { { "Error", "Can't not send message to server" } });
                    }
                }
                else
                {
                    ValueSet Value = new ValueSet
                    {
                        { "Error", "Failed to wait a server connection within the specified time" }
                    };

                    await args.Request.SendResponseAsync(Value);
                }
            }
            catch
            {
                ValueSet Value = new ValueSet
                {
                    { "Error", "Some exceptions were threw while transmitting the message" }
                };

                await args.Request.SendResponseAsync(Value);
            }
            finally
            {
                Deferral.Complete();
            }
        }
Esempio n. 30
0
 public void Wait()
 {
     _spinWait.SpinOnce();
 }
            internal static void Peak(ref StatisticsState state, TimeSpan time, long value)
            {
                StatisticsState State;
                var             Wait = new SpinWait();

                for (; ;)
                {
                    State = Volatile.Read(ref state);

                    var Interval = State._Interval;

                    if (Interval == TimeSpan.Zero)
                    {
                        var OldValue = Volatile.Read(ref State._Current);

                        if (OldValue >= value || Interlocked.CompareExchange(ref State._Current, value, OldValue) >= value)
                        {
                            return;
                        }

                        continue;
                    }

                    var Finish = State._Time + Interval;

                    if (time < Finish)
                    {
                        // Still within the time interval
                        var OldValue = Volatile.Read(ref State._Current);

                        if (OldValue == -1)
                        {
                            // Expired. Wait a moment for the other thread to finish replacing the state
                            Wait.SpinOnce();
                        }
                        else
                        {
                            if (OldValue >= value || Interlocked.CompareExchange(ref State._Current, value, OldValue) >= value)
                            {
                                return;
                            }

                            // Another thread replaced our value with something greater than the previous peak, but less than our new peak
                        }
                    }
                    else if (time < Finish + Interval)
                    {
                        // We're within the next time interval, flag the state as expired so we can lock in that interval
                        var Previous = Interlocked.Exchange(ref State._Current, -1);

                        if (Previous != -1)
                        {
                            var NewState = new StatisticsState(Interval, time, value, Previous);

                            // Replace the current state with a new state
                            if (Interlocked.CompareExchange(ref state, NewState, State) == State)
                            {
                                return;
                            }
                        }
                        else
                        {
                            // Wait a moment for the other thread to finish replacing the state
                            Wait.SpinOnce();
                        }

                        // Another thread is performing a replacement, wait and try again
                    }
                    else
                    {
                        // Two intervals have passed since this state began recording, so we replace with a zero previous record
                        var NewState = new StatisticsState(Interval, time, value);

                        // Replace the current state with a new state
                        if (Interlocked.CompareExchange(ref state, NewState, State) == State)
                        {
                            return;
                        }

                        // Another thread is performing a replacement, wait and try again
                    }
                }
            }
Esempio n. 32
0
        public static void TestSchedulerNesting()
        {
            // Create a hierarchical set of scheduler pairs
            var cespParent = new ConcurrentExclusiveSchedulerPair();

            var cespChild1       = new ConcurrentExclusiveSchedulerPair(cespParent.ConcurrentScheduler);
            var cespChild1Child1 = new ConcurrentExclusiveSchedulerPair(cespChild1.ConcurrentScheduler);
            var cespChild1Child2 = new ConcurrentExclusiveSchedulerPair(cespChild1.ExclusiveScheduler);

            var cespChild2       = new ConcurrentExclusiveSchedulerPair(cespParent.ExclusiveScheduler);
            var cespChild2Child1 = new ConcurrentExclusiveSchedulerPair(cespChild2.ConcurrentScheduler);
            var cespChild2Child2 = new ConcurrentExclusiveSchedulerPair(cespChild2.ExclusiveScheduler);

            // these are ordered such that we will complete the child schedulers before we complete their parents.  That way
            // we don't complete a parent that's still in use.
            var cesps = new[] {
                cespChild1Child1,
                cespChild1Child2,
                cespChild1,
                cespChild2Child1,
                cespChild2Child2,
                cespChild2,
                cespParent,
            };

            // Get the schedulers from all of the pairs
            List <TaskScheduler> schedulers = new List <TaskScheduler>();

            foreach (var s in cesps)
            {
                schedulers.Add(s.ConcurrentScheduler);
                schedulers.Add(s.ExclusiveScheduler);
            }

            // Keep track of all created tasks
            var tasks = new List <Task>();

            // Queue lots of work to each scheduler
            foreach (var scheduler in schedulers)
            {
                // Create a function that schedules and inlines recursively queued tasks
                Action <int> recursiveWork = null;
                recursiveWork = depth =>
                {
                    if (depth > 0)
                    {
                        Action work = () =>
                        {
                            var sw = new SpinWait();
                            while (!sw.NextSpinWillYield)
                            {
                                sw.SpinOnce();
                            }
                            recursiveWork(depth - 1);
                        };

                        TaskFactory factory = new TaskFactory(scheduler);
                        Debug.WriteLine(string.Format("Start tasks in scheduler {0}", scheduler.Id));
                        Task t1 = factory.StartNew(work); Task t2 = factory.StartNew(work); Task t3 = factory.StartNew(work);
                        Task.WaitAll(t1, t2, t3);
                    }
                };

                for (int i = 0; i < 2; i++)
                {
                    tasks.Add(Task.Factory.StartNew(() => recursiveWork(2), CancellationToken.None, TaskCreationOptions.None, scheduler));
                }
            }

            // Wait for all tasks to complete, then complete the schedulers
            Task.WaitAll(tasks.ToArray());
            foreach (var cesp in cesps)
            {
                cesp.Complete();
                cesp.Completion.Wait();
            }
        }
Esempio n. 33
0
        protected virtual void Dispose(bool disposing) {
            if (!disposed.TryRelaxedSet())
                return;

            if (handle != null) {
                ManualResetEvent tmpHandle = Interlocked.Exchange(ref handle, null);
                if (used > 0) {
                    // A tiny wait (just a few cycles normally) before releasing
                    var wait = new SpinWait();
                    while (used > 0)
                        wait.SpinOnce();
                }
                tmpHandle.Close();
            }
        }
Esempio n. 34
0
        public long Allocate(int numSlots = 1)
        {
            PageOffset localTailPageOffset = default(PageOffset);

            // Determine insertion index.
            // ReSharper disable once CSharpWarnings::CS0420
#pragma warning disable 420
            localTailPageOffset.PageAndOffset = Interlocked.Add(ref TailPageOffset.PageAndOffset, numSlots);
#pragma warning restore 420

            int page   = localTailPageOffset.Page;
            int offset = localTailPageOffset.Offset - numSlots;

            #region HANDLE PAGE OVERFLOW

            /* To prove correctness of the following modifications
             * done to TailPageOffset and the allocation itself,
             * we should use the fact that only one thread will have any
             * of the following cases since it is a counter and we spin-wait
             * until the tail is folded onto next page accordingly.
             */
            if (localTailPageOffset.Offset >= PageSize)
            {
                if (offset >= PageSize)
                {
                    //The tail offset value was more than page size before atomic add
                    //We consider that a failed attempt and retry again
                    var spin = new SpinWait();
                    do
                    {
                        //Just to give some more time to the thread
                        // that is handling this overflow
                        while (TailPageOffset.Offset >= PageSize)
                        {
                            spin.SpinOnce();
                        }

                        // ReSharper disable once CSharpWarnings::CS0420
#pragma warning disable 420
                        localTailPageOffset.PageAndOffset = Interlocked.Add(ref TailPageOffset.PageAndOffset, numSlots);
#pragma warning restore 420

                        page   = localTailPageOffset.Page;
                        offset = localTailPageOffset.Offset - numSlots;
                    } while (offset >= PageSize);
                }


                if (localTailPageOffset.Offset == PageSize)
                {
                    //Folding over at page boundary
                    localTailPageOffset.Page++;
                    localTailPageOffset.Offset = 0;
                    TailPageOffset             = localTailPageOffset;
                }
                else if (localTailPageOffset.Offset >= PageSize)
                {
                    //Overflows not allowed. We allot same space in next page.
                    localTailPageOffset.Page++;
                    localTailPageOffset.Offset = numSlots;
                    TailPageOffset             = localTailPageOffset;

                    page   = localTailPageOffset.Page;
                    offset = 0;
                }
            }
            #endregion

            long address = (((long)page) << LogPageSizeBits) | ((long)offset);

            // Check if TailPageIndex is appropriate and allocated!
            int pageIndex = page % BufferSize;

            if (TailPageIndex == pageIndex)
            {
                return(address);
            }

            //Invert the address if either the previous page is not flushed or if it is null
            if ((PageStatusIndicator[pageIndex].PageFlushCloseStatus.PageFlushStatus != FlushStatus.Flushed) ||
                (PageStatusIndicator[pageIndex].PageFlushCloseStatus.PageCloseStatus != CloseStatus.Closed) ||
                (values[pageIndex] == null))
            {
                address = -address;
            }

            // Update the read-only so that we can get more space for the tail
            if (offset == 0)
            {
                if (address >= 0)
                {
                    TailPageIndex = pageIndex;
                    Interlocked.MemoryBarrier();
                }

                long newPage      = page + 1;
                int  newPageIndex = (int)((page + 1) % BufferSize);

                long tailAddress = (address < 0 ? -address : address);
                PageAlignedShiftReadOnlyAddress(tailAddress);
                PageAlignedShiftHeadAddress(tailAddress);

                if (values[newPageIndex] == null)
                {
                    AllocatePage(newPageIndex);
                }
            }

            return(address);
        }
Esempio n. 35
0
        /// <summary>
        /// Helper method of GetEnumerator to separate out yield return statement, and prevent lazy evaluation.
        /// </summary>
        private IEnumerator <T> GetEnumerator(Segment head, Segment tail, int headLow, int tailHigh)
        {
            try
            {
                SpinWait spin = new SpinWait();

                if (head == tail)
                {
                    for (int i = headLow; i <= tailHigh; i++)
                    {
                        // If the position is reserved by an Enqueue operation, but the value is not written into,
                        // spin until the value is available.
                        spin.Reset();
                        while (!head._state[i]._value)
                        {
                            spin.SpinOnce();
                        }
                        yield return(head._array[i]);
                    }
                }
                else
                {
                    //iterate on head segment
                    for (int i = headLow; i < SEGMENT_SIZE; i++)
                    {
                        // If the position is reserved by an Enqueue operation, but the value is not written into,
                        // spin until the value is available.
                        spin.Reset();
                        while (!head._state[i]._value)
                        {
                            spin.SpinOnce();
                        }
                        yield return(head._array[i]);
                    }
                    //iterate on middle segments
                    Segment curr = head.Next;
                    while (curr != tail)
                    {
                        for (int i = 0; i < SEGMENT_SIZE; i++)
                        {
                            // If the position is reserved by an Enqueue operation, but the value is not written into,
                            // spin until the value is available.
                            spin.Reset();
                            while (!curr._state[i]._value)
                            {
                                spin.SpinOnce();
                            }
                            yield return(curr._array[i]);
                        }
                        curr = curr.Next;
                    }

                    //iterate on tail segment
                    for (int i = 0; i <= tailHigh; i++)
                    {
                        // If the position is reserved by an Enqueue operation, but the value is not written into,
                        // spin until the value is available.
                        spin.Reset();
                        while (!tail._state[i]._value)
                        {
                            spin.SpinOnce();
                        }
                        yield return(tail._array[i]);
                    }
                }
            }
            finally
            {
                // This Decrement must happen after the enumeration is over.
                Interlocked.Decrement(ref _numSnapshotTakers);
            }
        }
        /// <summary>
        /// Removes the first element from the queue and returns it (or <c>null</c>).
        /// </summary>
        /// <param name="blockWhenEmpty">
        /// If <c>true</c> and the queue is empty, the calling thread is blocked until
        /// either an element is enqueued, or <see cref="Stop"/> is called.
        /// </param>
        /// <returns>
        /// <list type="bullet">
        ///   <item>
        ///     <term>If the queue not empty</term>
        ///     <description>the first element.</description>
        ///   </item>
        ///   <item>
        ///     <term>otherwise, if <paramref name="blockWhenEmpty"/>==<c>false</c>
        ///       or <see cref="Stop"/> has been called</term>
        ///     <description><c>null</c>.</description>
        ///   </item>
        /// </list>
        /// </returns>
        public Event Dequeue(bool blockWhenEmpty)
        {
            SpinWait sw = new SpinWait();

            do
            {
                int cachedRemoveId = _removeId;
                int cachedAddId    = _addId;

                // Empty case
                if (cachedRemoveId == cachedAddId)
                {
                    if (!blockWhenEmpty || _stopped != 0)
                    {
                        return(null);
                    }

                    // Spin a few times to see if something changes
                    if (sw.Count <= spinCount)
                    {
                        sw.SpinOnce();
                    }
                    else
                    {
                        // Reset to wait for an enqueue
                        _mreAdd.Reset();

                        // Recheck for an enqueue to avoid a Wait
                        if (cachedRemoveId != _removeId || cachedAddId != _addId)
                        {
                            // Queue is not empty, set the event
                            _mreAdd.Set();
                            continue;
                        }

                        // Wait for something to happen
                        _mreAdd.Wait(500);
                    }

                    continue;
                }

                // Validate that we are the current dequeuer
                if (Interlocked.CompareExchange(ref _removeId, cachedRemoveId + 1, cachedRemoveId) != cachedRemoveId)
                {
                    continue;
                }


                // Dequeue our work item
                Event e;
                while (!_queue.TryDequeue(out e))
                {
                    if (!blockWhenEmpty || _stopped != 0)
                    {
                        return(null);
                    }
                }

                return(e);
            } while (true);
        }
Esempio n. 37
0
        /// <summary>
        /// Attempts to remove and return an item from the left end of the <see cref="ConcurrentDeque{T}"/>.
        /// </summary>
        /// <param name="item">When this method returns, if the operation was successful, <paramref name="item"/> contains the
        /// object removed. If no object was available to be removed, the value is unspecified.</param>
        /// <returns>true if an element was removed and returned succesfully; otherwise, false.</returns>
        public bool TryPopLeft(out T item)
        {
            Anchor anchor;
            var    spinner = new SpinWait();

            while (true)
            {
                anchor = _anchor;
                anchor.Validate();

                if (anchor._left == null)
                {
                    //return false if the deque is empty
                    item = default(T);
                    return(false);
                }
                if (anchor._right == anchor._left)
                {
                    //update both pointers if the deque has only one node
                    var newAnchor = new Anchor();
                    if (Interlocked.CompareExchange(ref _anchor, newAnchor, anchor) == anchor)
                    {
                        break;
                    }
                }
                else if (anchor._status == DequeStatus.Stable)
                {
                    //update left pointer if deque has > 1 node
                    var prev      = anchor._left._right;
                    var newAnchor = new Anchor(prev, anchor._right, anchor._status);
                    if (Interlocked.CompareExchange(ref _anchor, newAnchor, anchor) == anchor)
                    {
                        break;
                    }
                }
                else
                {
                    //if the deque is unstable,
                    //attempt to bring it to a stable state before trying to remove the node.
                    Stabilize(anchor);
                }

                spinner.SpinOnce();
            }

            var node = anchor._left;

            item = node._value;

            /*
             * Try to set the new leftmost node's left pointer to null to avoid memory leaks.
             * We try only once - if CAS fails, then another thread must have pushed a new node, in which case we simply carry on.
             */
            var leftmostNode = node._right;

            if (leftmostNode != null)
            {
                Interlocked.CompareExchange(ref leftmostNode._left, null, node);
            }

            return(true);
        }
Esempio n. 38
0
        public static int WaitAny(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken)
        {
            if (tasks == null)
            {
                throw new ArgumentNullException("tasks");
            }
            if (tasks.Length == 0)
            {
                throw new ArgumentException("tasks is empty", "tasks");
            }
            if (tasks.Length == 1)
            {
                tasks[0].Wait(millisecondsTimeout, cancellationToken);
                return(0);
            }

            int                  numFinished        = 0;
            int                  indexFirstFinished = -1;
            int                  index        = 0;
            TaskScheduler        sched        = null;
            Task                 task         = null;
            Watch                watch        = Watch.StartNew();
            ManualResetEventSlim predicateEvt = new ManualResetEventSlim(false);

            foreach (Task t in tasks)
            {
                int indexResult = index++;
                t.ContinueWith(delegate {
                    if (numFinished >= 1)
                    {
                        return;
                    }
                    int result = Interlocked.Increment(ref numFinished);

                    // Check if we are the first to have finished
                    if (result == 1)
                    {
                        indexFirstFinished = indexResult;
                    }

                    // Stop waiting
                    predicateEvt.Set();
                }, TaskContinuationOptions.ExecuteSynchronously);

                if (sched == null && t.scheduler != null)
                {
                    task  = t;
                    sched = t.scheduler;
                }
            }

            // If none of task have a scheduler we are forced to wait for at least one to start
            if (sched == null)
            {
                var handles = Array.ConvertAll(tasks, t => t.schedWait.WaitHandle);
                int shandle = -1;
                if ((shandle = WaitHandle.WaitAny(handles, millisecondsTimeout)) == WaitHandle.WaitTimeout)
                {
                    return(-1);
                }
                sched = tasks[shandle].scheduler;
                task  = tasks[shandle];
                millisecondsTimeout = ComputeTimeout(millisecondsTimeout, watch);
            }

            // One task already finished
            if (indexFirstFinished != -1)
            {
                return(indexFirstFinished);
            }

            if (cancellationToken != CancellationToken.None)
            {
                cancellationToken.Register(predicateEvt.Set);
                cancellationToken.ThrowIfCancellationRequested();
            }

            sched.ParticipateUntil(task, predicateEvt, millisecondsTimeout);

            // Index update is still not done
            if (indexFirstFinished == -1)
            {
                SpinWait wait = new SpinWait();
                while (indexFirstFinished == -1)
                {
                    wait.SpinOnce();
                }
            }

            return(indexFirstFinished);
        }
		// This is the actual method called in the Thread
		void WorkerMethodWrapper ()
		{
			int sleepTime = 0;
			SpinWait wait = new SpinWait ();
			
			// Main loop
			while (started == 1) {
				bool result = false;

				result = WorkerMethod ();
				
				// Wait a little and if the Thread has been more sleeping than working shut it down
				wait.SpinOnce ();
				if (result)
					sleepTime = 0;
				if (sleepTime++ > sleepThreshold) 
					break;
			}

			started = 0;
		}
		public void ParallelForEachTestCase ()
		{
			ParallelTestHelper.Repeat (() => {
				IEnumerable<int> e = Enumerable.Repeat(1, 500);
				ConcurrentQueue<int> queue = new ConcurrentQueue<int> ();
				SpinWait sw = new SpinWait ();
				int count = 0;
				
				Parallel.ForEach (e, (element) => { Interlocked.Increment (ref count); queue.Enqueue (element); sw.SpinOnce (); });
				
				Assert.AreEqual (500, count, "#1");
				CollectionAssert.AreEquivalent (e, queue, "#2");
			});
		}
Esempio n. 41
0
		// Almost same as above but with an added predicate and treating one item at a time. 
		// It's used by Scheduler Participate(...) method for special waiting case like
		// Task.WaitAll(someTasks) or Task.WaitAny(someTasks)
		// Predicate should be really fast and not blocking as it is called a good deal of time
		// Also, the method skip tasks that are LongRunning to avoid blocking (Task are not LongRunning by default)
		public static void WorkerMethod (Func<bool> predicate, IProducerConsumerCollection<Task> sharedWorkQueue,
		                                 ThreadWorker[] others)
		{
			SpinWait wait = new SpinWait ();

			while (!predicate ()) {
				Task value;
				
				// Dequeue only one item as we have restriction
				if (sharedWorkQueue.TryTake (out value)) {
					if (value != null) {
						if (CheckTaskFitness (value))
							value.Execute (null);
						else
							sharedWorkQueue.TryAdd (value);
					}
				}
				
				// First check to see if we comply to predicate
				if (predicate ())
					return;
				
				// Try to complete other work by stealing since our desired tasks may be in other worker
				ThreadWorker other;
				for (int i = 0; i < others.Length; i++) {
					if ((other = others [i]) == null)
						continue;
					
					if (other.dDeque.PopTop (out value) == PopResult.Succeed) {
						if (value != null) {
							if (CheckTaskFitness (value))
								value.Execute (null);
							else
								sharedWorkQueue.TryAdd (value);
						}
					}
					
					if (predicate ())
						return;
				}

				wait.SpinOnce ();
			}
		}
Esempio n. 42
0
		public static void SpinUntil (Func<bool> condition)
		{
			SpinWait sw = new SpinWait ();
			while (!condition ())
				sw.SpinOnce ();
		}
Esempio n. 43
0
        private bool TryAddWithNoTimeValidation(T item, int millisecondsTimeout, CancellationToken cancellationToken)
        {
            bool flag;

            CheckDisposed();
            if (cancellationToken.IsCancellationRequested)
            {
                throw new OperationCanceledException2("Common_OperationCanceled", cancellationToken);
            }
            if (IsAddingCompleted)
            {
                throw new InvalidOperationException("BlockingCollection_Completed");
            }
            bool flag1 = true;

            if (m_freeNodes != null)
            {
                CancellationTokenSource cancellationTokenSource = null;
                {
                    try
                    {
                        flag1 = m_freeNodes.Wait(0);
                        if (!flag1 && millisecondsTimeout != 0)
                        {
                            cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, m_ProducersCancellationTokenSource.Token);
                            flag1 = m_freeNodes.Wait(millisecondsTimeout, cancellationTokenSource.Token);
                        }
                    }
                    catch (OperationCanceledException operationCanceledException)
                    {
                        if (!cancellationToken.IsCancellationRequested)
                        {
                            throw new InvalidOperationException("BlockingCollection_Add_ConcurrentCompleteAdd", operationCanceledException);
                        }
                        throw new OperationCanceledException2("Common_OperationCanceled", cancellationToken);
                    }
                }
            }
            if (!flag1)
            {
                return(flag1);
            }
            SpinWait spinWait = new SpinWait();

            while (true)
            {
                int mCurrentAdders = m_currentAdders;
                if ((mCurrentAdders & -2147483648) != 0)
                {
                    spinWait.Reset();
                    while (m_currentAdders != -2147483648)
                    {
                        spinWait.SpinOnce();
                    }
                    throw new InvalidOperationException("BlockingCollection_Completed");
                }
                if (Interlocked.CompareExchange(ref m_currentAdders, mCurrentAdders + 1, mCurrentAdders) == mCurrentAdders)
                {
                    break;
                }
                spinWait.SpinOnce();
            }
            try
            {
                bool flag2 = false;
                try
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    flag2 = m_collection.TryAdd(item);
                }
                catch
                {
                    if (m_freeNodes != null)
                    {
                        m_freeNodes.Release();
                    }
                    throw;
                }
                if (!flag2)
                {
                    throw new InvalidOperationException("BlockingCollection_Add_Failed");
                }
                m_occupiedNodes.Release();
                flag = flag1;
            }
            finally
            {
                Interlocked.Decrement(ref m_currentAdders);
            }
            return(flag);
        }
Esempio n. 44
0
        private void ProcessNetwork()
        {
            Stopwatch time         = Stopwatch.StartNew();
            int       lastPacketId = 0;

            try
            {
                NetworkStream ns = new NetworkStream(Socket);

                using (ns)
                {
                    using (MinecraftStream mc = new MinecraftStream(ns))
                    {
                        SpinWait sw = new SpinWait();
                        _readerStream = mc;
                        while (!CancellationToken.IsCancellationRequested)
                        {
                            if (time.ElapsedMilliseconds > 5000)
                            {
                                Log.Info($"No messages received. Stopping?");
                                time.Restart();
                            }
                            /*SpinWait.SpinUntil(() => ns.DataAvailable || CancellationToken.IsCancellationRequested);*/

                            if (CancellationToken.IsCancellationRequested)
                            {
                                break;
                            }

                            if (!ns.DataAvailable)
                            {
                                sw.SpinOnce();
                                continue;
                            }

                            if (TryReadPacket(mc, out lastPacketId))
                            {
                                time.Restart();
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                //  if (ex is OperationCanceledException) return;
                //   if (ex is EndOfStreamException) return;
                //   if (ex is IOException) return;

                if (LogExceptions)
                {
                    Log.Warn(
                        $"Failed to process network (Last packet: 0x{lastPacketId:X2} State: {ConnectionState}): " +
                        ex);
                }
            }
            finally
            {
                Disconnected(false);
            }
        }
Esempio n. 45
0
        /// <summary>
        /// Removes the first element from the queue and returns it (or <c>null</c>).
        /// </summary>
        /// <param name="blockWhenEmpty">
        /// If <c>true</c> and the queue is empty, the calling thread is blocked until
        /// either an element is enqueued, or <see cref="Stop"/> is called.
        /// </param>
        /// <returns>
        /// <list type="bullet">
        ///   <item>
        ///     <term>If the queue not empty</term>
        ///     <description>the first element.</description>
        ///   </item>
        ///   <item>
        ///     <term>otherwise, if <paramref name="blockWhenEmpty"/>==<c>false</c>
        ///       or <see cref="Stop"/> has been called</term>
        ///     <description><c>null</c>.</description>
        ///   </item>
        /// </list>
        /// </returns>
        public Event Dequeue(bool blockWhenEmpty)
        {
            SpinWait sw = new SpinWait();

            do
            {
                int cachedRemoveId = _removeId;
                int cachedAddId = _addId;

                // Empty case
                if (cachedRemoveId == cachedAddId)
                {
                    if (!blockWhenEmpty || _stopped != 0)
                        return null;

                    // Spin a few times to see if something changes
                    if (sw.Count <= spinCount)
                    {
                        sw.SpinOnce();
                    }
                    else
                    {
                        // Reset to wait for an enqueue
                        _mreAdd.Reset();

                        // Recheck for an enqueue to avoid a Wait
                        if (cachedRemoveId != _removeId || cachedAddId != _addId)
                        {
                            // Queue is not empty, set the event
                            _mreAdd.Set();
                            continue;
                        }

                        // Wait for something to happen
                        _mreAdd.Wait(500);
                    }

                    continue;
                }

                // Validate that we are the current dequeuer
                if (Interlocked.CompareExchange(ref _removeId, cachedRemoveId + 1, cachedRemoveId) != cachedRemoveId)
                    continue;


                // Dequeue our work item
                Event e;
                while (!_queue.TryDequeue (out e))
                {
                    if (!blockWhenEmpty || _stopped != 0)
                        return null;
                }

                return e;
            } while (true);
        }
Esempio n. 46
0
        /// <summary>
        /// The auto receiver action handler.
        /// </summary>
        /// <param name="data">The data from the server.</param>
        private void ReceiveAction(byte[] data)
        {
            // Make sure only one thread at a time is adding to the buffer.
            lock (_lockReceiver)
            {
                // Make sure data has arrived.
                if (data.Length > 0)
                {
                    // If the upper capacity of the buffer
                    // has been reached then stop writting
                    // until the request buffer gets to the
                    // lower capacity threshold.
                    if (_responseBuffer.IsUpperCapacityPercentage())
                    {
                        // Create the tasks.
                        Task[] tasks = new Task[1];
                        Interlocked.Exchange(ref _exitWaitReceiveIndicator, 0);

                        try
                        {
                            // Write to the request stream task.
                            Task readFromStream = Task.Factory.StartNew(() =>
                            {
                                // Create a new spin wait.
                                SpinWait sw = new SpinWait();

                                // Action to perform.
                                while (Interlocked.CompareExchange(ref _exitWaitReceiveIndicator, 0, 1) == 0)
                                {
                                    // The NextSpinWillYield property returns true if
                                    // calling sw.SpinOnce() will result in yielding the
                                    // processor instead of simply spinning.
                                    if (sw.NextSpinWillYield)
                                    {
                                        // If the buffer is below the lower capacity
                                        // threshold then exist the spin wait.
                                        if (!_responseBuffer.IsLowerCapacityPercentage())
                                        {
                                            Interlocked.Exchange(ref _exitWaitReceiveIndicator, 1);
                                        }
                                    }

                                    // Performs a single spin.
                                    sw.SpinOnce();
                                }
                            });

                            // Assign the listener task.
                            tasks[0] = readFromStream;

                            // Wait for all tasks to complete.
                            Task.WaitAll(tasks);
                        }
                        catch { }

                        // For each task.
                        foreach (Task item in tasks)
                        {
                            try
                            {
                                // Release the resources.
                                item.Dispose();
                            }
                            catch { }
                        }
                        tasks = null;
                    }

                    // Write to the response stream.
                    _responseStream.WriteToStream(data, 0, data.Length);
                }
            }

            // Make sure data has arrived.
            if (data.Length > 0)
            {
                // Make sure the context exists.
                if (_context != null)
                {
                    // If the data available handler has been set
                    // then send a trigger indicating that
                    // data is available.
                    if (_context.OnReceivedHandler != null)
                    {
                        // If not in async mode.
                        if (!_context.IsAsyncMode)
                        {
                            // Allow an active context.
                            if (Interlocked.CompareExchange(ref _isContextActive, 1, 0) == 0)
                            {
                                // Set the active context indicator to true
                                // no other context can start.
                                Interlocked.Exchange(ref _isContextActive, 1);

                                // Received the request from the client.
                                // Send the message context.
                                Receiver();
                            }
                        }
                    }
                }
            }
        }
        internal void RemoveCallback(CancellationTokenRegistration tokenReg)
        {
            if (!canceled) {
                lock (syncRoot) {
                    if (!canceled) {
                        callbacks.Remove (tokenReg);
                        return;
                    }
                }
            }

            SpinWait sw = new SpinWait ();
            while (!processed)
                sw.SpinOnce ();
        }
Esempio n. 48
0
        /// <summary>
        ///     Spins until the specified condition is satisfied or until the specified timeout is expired.
        /// </summary>
        /// <param name="condition">A delegate to be executed over and over until it returns true.</param>
        /// <param name="millisecondsTimeout">
        ///     The number of milliseconds to wait, or
        ///     <see
        ///         cref="System.Threading.Timeout.Infinite" />
        ///     (-1) to wait indefinitely.
        /// </param>
        /// <returns>True if the condition is satisfied within the timeout; otherwise, false</returns>
        /// <exception cref="ArgumentNullException">The <paramref name="condition" /> argument is null.</exception>
        /// <exception cref="T:System.ArgumentOutOfRangeException">
        ///     <paramref name="millisecondsTimeout" /> is a
        ///     negative number other than -1, which represents an infinite time-out.
        /// </exception>
        public static bool SpinUntil(Func<bool> condition, int millisecondsTimeout) {
            if (millisecondsTimeout < Timeout.Infinite) {
                throw new ArgumentOutOfRangeException("millisecondsTimeout", millisecondsTimeout, "SpinWait_SpinUntil_TimeoutWrong");
            }
            if (condition == null) {
                throw new ArgumentNullException("condition", "SpinWait_SpinUntil_ArgumentNull");
            }
            long startTicks = 0;
            ;
            if (millisecondsTimeout != 0 && millisecondsTimeout != Timeout.Infinite) {
                startTicks = DateTime.UtcNow.Ticks;
            }
            var spinner = new SpinWait();
            while (!condition()) {
                if (millisecondsTimeout == 0) {
                    return false;
                }

                spinner.SpinOnce();

                if (millisecondsTimeout != Timeout.Infinite && spinner.NextSpinWillYield) {
                    if (millisecondsTimeout <= (DateTime.UtcNow.Ticks - startTicks)/TimeSpan.TicksPerMillisecond) {
                        return false;
                    }
                }
            }
            return true;
        }
        /// <summary>
        /// This method is the meat of the lock-free aggregation logic.
        /// </summary>
        /// <param name="metricValue">Already filtered and conveted value to be tracked.
        ///     We know that the value is not Double.NaN and not null and it passed trought any filters.</param>
        private void TrackFilteredConvertedValue(TBufferedValue metricValue)
        {
            // Get reference to the current buffer:
            MetricValuesBufferBase <TBufferedValue> buffer = _metricValuesBuffer;

            // Get the index at which to store metricValue into the buffer:
            int index = buffer.IncWriteIndex();

            // Check to see whether we are past the end of the buffer.
            // If we are, it means that some *other* thread hit exactly the end (wrote the last value that fits into the buffer) and is currently flushing.
            // If we are, we will spin and wait.
            if (index >= buffer.Capacity)
            {
#if DEBUG
                int startMillis = Environment.TickCount;
#endif
#pragma warning disable SA1129 // Do not use default value type constructor
                var spinWait = new SpinWait();
#pragma warning restore SA1129 // Do not use default value type constructor

                // It could be that the thread that was flushing is done and has updated the buffer pointer.
                // We refresh our local reference and see if we now have a valid index into the buffer.
                buffer = _metricValuesBuffer;
                index  = buffer.IncWriteIndex();

                while (index >= buffer.Capacity)
                {
                    // Still not valid index into the buffer. Spin and try again.
                    spinWait.SpinOnce();
#if DEBUG
                    unchecked
                    {
                        Interlocked.Increment(ref s_countBufferWaitSpinCycles);
                    }
#endif
                    if (spinWait.Count % 100 == 0)
                    {
                        // In tests (including stress tests) we always finished wating before 100 cycles.
                        // However, this is a protection against en extreme case on a slow machine.
                        // We will back off and sleep for a few millisecs to give the machine a chance to finish current tasks.

                        Task.Delay(10).ConfigureAwait(continueOnCapturedContext: false).GetAwaiter().GetResult();
                    }

                    // Check to see whether the thread that was flushing is done and has updated the buffer pointer.
                    // We refresh our local reference and see if we now have a valid index into the buffer.
                    buffer = _metricValuesBuffer;
                    index  = buffer.IncWriteIndex();
                }
#if DEBUG
                unchecked
                {
                    int periodMillis      = Environment.TickCount - startMillis;
                    int currentSpinMillis = s_timeBufferWaitSpinMillis;
                    int prevSpinMillis    = Interlocked.CompareExchange(ref s_timeBufferWaitSpinMillis, currentSpinMillis + periodMillis, currentSpinMillis);
                    while (prevSpinMillis != currentSpinMillis)
                    {
                        currentSpinMillis = s_timeBufferWaitSpinMillis;
                        prevSpinMillis    = Interlocked.CompareExchange(ref s_timeBufferWaitSpinMillis, currentSpinMillis + periodMillis, currentSpinMillis);
                    }

                    Interlocked.Increment(ref s_countBufferWaitSpinEvents);
                }
#endif
            }

            // Ok, so now we know that (0 <= index = buffer.Capacity). Write the value to the buffer:
            buffer.WriteValue(index, metricValue);

            // If this was the last value that fits into the buffer, we must flush the buffer:
            if (index == buffer.Capacity - 1)
            {
                // Before we begin flushing (which is can take time), we update the _metricValuesBuffer to a fresh buffer that is ready to take values.
                // That way threads do notneed to spin and wait until we flush and can begin writing values.

                // We try to recycle a previous buffer to lower stress on GC and to lower Gen-2 heap fragmentation.
                // The lifetime of an buffer can easily be a minute or so and then it can get into Gen-2 GC heap.
                // If we then, keep throwing such buffers away we can fragment the Gen-2 heap. To avoid this we employ
                // a simple form of best-effort object pooling.

                // Get buffer from pool and reset the pool:
                MetricValuesBufferBase <TBufferedValue> newBufer = Interlocked.Exchange(ref _metricValuesBufferRecycle, null);

                if (newBufer != null)
                {
                    // If we were succesful in getting a recycled buffer from the pool, we will try to use it as the new buffer.
                    // If we successfully the the recycled buffer to be the new buffer, we will reset it to prepare for data.
                    // Otherwise we will just throw it away.

                    MetricValuesBufferBase <TBufferedValue> prevBuffer = Interlocked.CompareExchange(ref _metricValuesBuffer, newBufer, buffer);
                    if (prevBuffer == buffer)
                    {
                        newBufer.ResetIndices();
                    }
                }
                else
                {
                    // If we were succesful in getting a recycled buffer from the pool, we will create a new one.

                    newBufer = InvokeMetricValuesBufferFactory();
                    Interlocked.CompareExchange(ref _metricValuesBuffer, newBufer, buffer);
                }

                // Ok, now we have either set a new buffer that is ready to be used, or we have determined using CompareExchange
                // that another thread set a new buffer and we do not need to do it here.

                // Now we can actually flush the buffer:

                UpdateAggregate(buffer);

                // The buffer is now flushed. If the slot for the best-effor object pooling is free, use it:
                Interlocked.CompareExchange(ref _metricValuesBufferRecycle, buffer, null);
            }
        }
Esempio n. 50
0
        /// <summary>
        /// Processes all synchronous events that must take place before the next time loop for the algorithm
        /// </summary>
        public virtual void ProcessSynchronousEvents()
        {
            // how to do synchronous market orders for real brokerages?

            // in backtesting we need to wait for orders to be removed from the queue and finished processing
            if (!_algorithm.LiveMode)
            {
                var spinWait = new SpinWait();
                while (!_orderRequestQueue.IsEmpty)
                {
                    // spin wait until the queue is empty
                    spinWait.SpinOnce();
                }
                // now wait for completed processing to signal
                _processingCompletedEvent.Wait();
                return;
            }

            Log.Debug("BrokerageTransactionHandler.ProcessSynchronousEvents(): Enter");

            // every morning flip this switch back
            if (_syncedLiveBrokerageCashToday && DateTime.Now.Date != LastSyncDate)
            {
                _syncedLiveBrokerageCashToday = false;
            }

            // we want to sync up our cash balance before market open
            if (_algorithm.LiveMode && !_syncedLiveBrokerageCashToday && DateTime.Now.TimeOfDay >= _liveBrokerageCashSyncTime)
            {
                try
                {
                    // only perform cash syncs if we haven't had a fill for at least 10 seconds
                    if (TimeSinceLastFill > TimeSpan.FromSeconds(10))
                    {
                        PerformCashSync();
                    }
                }
                catch (Exception err)
                {
                    Log.Error(err, "Updating cash balances");
                }
            }

            // we want to remove orders older than 10k records, but only in live mode
            const int maxOrdersToKeep = 10000;

            if (_orders.Count < maxOrdersToKeep + 1)
            {
                Log.Debug("BrokerageTransactionHandler.ProcessSynchronousEvents(): Exit");
                return;
            }

            int max = _orders.Max(x => x.Key);
            int lowestOrderIdToKeep = max - maxOrdersToKeep;

            foreach (var item in _orders.Where(x => x.Key <= lowestOrderIdToKeep))
            {
                Order       value;
                OrderTicket ticket;
                _orders.TryRemove(item.Key, out value);
                _orderTickets.TryRemove(item.Key, out ticket);
            }

            Log.Debug("BrokerageTransactionHandler.ProcessSynchronousEvents(): Exit");
        }
        /// <summary>
        /// Processes all synchronous events that must take place before the next time loop for the algorithm
        /// </summary>
        public virtual void ProcessSynchronousEvents()
        {
            // how to do synchronous market orders for real brokerages?

            // in backtesting we need to wait for orders to be removed from the queue and finished processing
            if (!_algorithm.LiveMode)
            {
                var spinWait = new SpinWait();
                while (!_orderRequestQueue.IsEmpty)
                {
                    // spin wait until the queue is empty
                    spinWait.SpinOnce();
                }
                // now wait for completed processing to signal
                _processingCompletedEvent.Wait();
                return;
            }

            Log.Debug("BrokerageTransactionHandler.ProcessSynchronousEvents(): Enter");

            // every morning flip this switch back
            if (_syncedLiveBrokerageCashToday && DateTime.Now.Date != LastSyncDate)
            {
                _syncedLiveBrokerageCashToday = false;
            }

            // we want to sync up our cash balance before market open
            if (_algorithm.LiveMode && !_syncedLiveBrokerageCashToday && DateTime.Now.TimeOfDay >= _liveBrokerageCashSyncTime)
            {
                try
                {
                    // only perform cash syncs if we haven't had a fill for at least 10 seconds
                    if (TimeSinceLastFill > TimeSpan.FromSeconds(10))
                    {
                        PerformCashSync();
                    }
                }
                catch (Exception err)
                {
                    Log.Error(err, "Updating cash balances");
                }
            }

            // we want to remove orders older than 10k records, but only in live mode
            const int maxOrdersToKeep = 10000;
            if (_orders.Count < maxOrdersToKeep + 1)
            {
                Log.Debug("BrokerageTransactionHandler.ProcessSynchronousEvents(): Exit");
                return;
            }

            int max = _orders.Max(x => x.Key);
            int lowestOrderIdToKeep = max - maxOrdersToKeep;
            foreach (var item in _orders.Where(x => x.Key <= lowestOrderIdToKeep))
            {
                Order value;
                OrderTicket ticket;
                _orders.TryRemove(item.Key, out value);
                _orderTickets.TryRemove(item.Key, out ticket);
            }

            Log.Debug("BrokerageTransactionHandler.ProcessSynchronousEvents(): Exit");
        }
Esempio n. 52
0
        /// <summary>
        /// Dequeue a WorkItem for processing
        /// </summary>
        /// <returns>A WorkItem or null if the queue has stopped</returns>
        public WorkItem Dequeue()
        {
            SpinWait sw = new SpinWait();

            do
            {
                WorkItemQueueState cachedState = State;

                if (cachedState == WorkItemQueueState.Stopped)
                {
                    return(null); // Tell worker to terminate
                }
                int cachedRemoveId = _removeId;
                int cachedAddId    = _addId;

                // Empty case (or paused)
                if (cachedRemoveId == cachedAddId || cachedState == WorkItemQueueState.Paused)
                {
                    // Spin a few times to see if something changes
                    if (sw.Count <= spinCount)
                    {
                        sw.SpinOnce();
                    }
                    else
                    {
                        // Reset to wait for an enqueue
                        _mreAdd.Reset();

                        // Recheck for an enqueue to avoid a Wait
                        if ((cachedRemoveId != _removeId || cachedAddId != _addId) && cachedState != WorkItemQueueState.Paused)
                        {
                            // Queue is not empty, set the event
                            _mreAdd.Set();
                            continue;
                        }

                        // Wait for something to happen
                        _mreAdd.Wait(500);
                    }

                    continue;
                }

                // Validate that we are the current dequeuer
                if (Interlocked.CompareExchange(ref _removeId, cachedRemoveId + 1, cachedRemoveId) != cachedRemoveId)
                {
                    continue;
                }


                // Dequeue our work item
                WorkItem work;
                while (!_innerQueue.TryDequeue(out work))
                {
                }
                ;

                // Add to items processed using CAS
                Interlocked.Increment(ref _itemsProcessed);

                return(work);
            } while (true);
        }
        // Helper method to avoid repeating Break() logic between ParallelState64 and ParallelState64<TLocal>
        internal static void Break(long iteration, ParallelLoopStateFlags64 pflags)
        {
            int oldValue = ParallelLoopStateFlags.PLS_NONE;

            // Attempt to change state from "not stopped or broken or canceled or exceptional" to "broken".
            if (!pflags.AtomicLoopStateUpdate(ParallelLoopStateFlags.PLS_BROKEN,
                                             ParallelLoopStateFlags.PLS_STOPPED | ParallelLoopStateFlags.PLS_EXCEPTIONAL | ParallelLoopStateFlags.PLS_CANCELED,
                                             ref oldValue))
            {

                // If we were already stopped, we have a problem
                if ((oldValue & ParallelLoopStateFlags.PLS_STOPPED) != 0)
                {
                    throw new InvalidOperationException(
                        Environment.GetResourceString("ParallelState_Break_InvalidOperationException_BreakAfterStop"));
                }
                else
                {
                    // Apparently we previously got cancelled or became exceptional. No action necessary
                    return;
                }
            }

            // replace shared LowestBreakIteration with CurrentIteration, but only if CurrentIteration
            // is less than LowestBreakIteration.
            long oldLBI = pflags.LowestBreakIteration;
            if (iteration < oldLBI)
            {
                SpinWait wait = new SpinWait();
                while (Interlocked.CompareExchange(
                    ref pflags.m_lowestBreakIteration,
                        iteration,
                        oldLBI) != oldLBI)
                {
                    wait.SpinOnce();
                    oldLBI = pflags.LowestBreakIteration;
                    if (iteration > oldLBI) break;
                }
            }

        }
Esempio n. 54
0
        /// <summary>
        /// Locks the file specified at location <see cref="FilePath"/>.
        /// </summary>
        /// <returns>The file lock use that can be revoked by disposing it.</returns>
        public FileLockUse WaitUntilAcquired()
        {
            var lockId = getLockId();

            Trace.WriteLine($"{CurrentThreadWithLockIdPrefix(lockId)} Begin locking file {FilePath}.", TraceCategory);
            SpinWait spinWait = new SpinWait();

            while (true)
            {
                var currentLocksInUse      = locksInUse;
                var desiredLocksInUse      = currentLocksInUse + 1;
                var currentFileLockerState = fileLockerState;

                if (currentFileLockerState.IsErroneous())
                {
                    if (EnableConcurrentRethrow)
                    {
                        Trace.WriteLine($"{CurrentThreadWithLockIdPrefix(lockId)} Error from previous lock will be rethrown.", TraceCategory);
                        throw currentFileLockerState !.Error !;
                    }

                    // Imagine stair steps where each stair step is Lock():
                    // Thread #0 Lock #0 -> Incremented to 1 -> Exception occured.
                    //  Thread #1 Lock #1 -> Incremented to 2. Recognozes exception in #0 because #0 not yet entered Unlock().
                    //   Thread #2 Lock #2 -> Incremented to 3. Recognizes excetion in #1 because #0 not yet entered Unlock().
                    // Thread #3 Lock #3 -> Incremented to 1. Lock was successful.
                    // We want Lock #1 and Lock #2 to retry their Lock():
                    //  Thread #1 Lock #1 -> Incremented to 2. Lock was successful.
                    //   Thread #2 Lock #2 -> Incremented to 3. Lock was successful.
                    currentFileLockerState !.ErrorUnlockDone !.WaitOne();
                    Trace.WriteLine($"{CurrentThreadWithLockIdPrefix(lockId)} Retry lock due to previously failed lock.", TraceCategory);
                    continue;
                }
                // If it is the initial lock, then we expect file stream being null.
                // If it is not the initial lock, we expect the stream being not null.
                else if ((currentLocksInUse == 0 && currentFileLockerState != null) ||
                         (currentLocksInUse != 0 && currentFileLockerState == null))
                {
                    spinWait.SpinOnce();
                    continue;
                }
                else
                {
                    if (currentLocksInUse != Interlocked.CompareExchange(ref locksInUse, desiredLocksInUse, currentLocksInUse))
                    {
                        continue;
                    }

                    // The above conditions met, so if it is the initial lock, then we want
                    // to acquire the lock.
                    if (desiredLocksInUse == 1)
                    {
                        try {
                            var fileStream = LockFileApi.Default.WaitUntilAcquired(FilePath, TimeoutInMilliseconds, fileMode: FileMode,
                                                                                   fileAccess: FileAccess, fileShare: FileShare) !;

                            currentFileLockerState = new FileLockContext(this, decreaseLockUseLocker, fileStream);

                            fileLockerState = currentFileLockerState;
                            Trace.WriteLine($"{CurrentThreadWithLockIdPrefix(lockId)} File {FilePath} locked by file locker.", TraceCategory);
                        } catch (Exception error) {
                            var errorUnlockDone = new ManualResetEvent(false);
                            currentFileLockerState = new FileLockContext(this, decreaseLockUseLocker, error, errorUnlockDone);
                            fileLockerState        = currentFileLockerState;
                            Unlock(lockId);
                            // After we processed Unlock(), we can surpass these locks
                            // who could be dependent on state assigment of this Lock().
                            currentFileLockerState.ErrorUnlockDone !.Set();
                            throw;
                        }
                    }
                    else
                    {
                        Trace.WriteLine($"{CurrentThreadWithLockIdPrefix(lockId)} File {FilePath} locked {desiredLocksInUse} time(s) concurrently by file locker. {fileStreamHasBeenLockedString(currentFileLockerState!.FileStream!)}", TraceCategory);
                    }
                }

                var fileLockContract = new FileLockUse(currentFileLockerState, lockId);
                return(fileLockContract);
            }
        }
Esempio n. 55
0
        public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken) {
            if (millisecondsTimeout < -1)
                throw new ArgumentOutOfRangeException("millisecondsTimeout");

            ThrowIfDisposed();

            if (!IsSet) {
                var wait = new SpinWait();

                while (!IsSet) {
                    if (wait.Count < spinCount) {
                        wait.SpinOnce();
                        continue;
                    }

                    break;
                }

                cancellationToken.ThrowIfCancellationRequested();

                if (IsSet)
                    return true;

                WaitHandle handle = WaitHandle;

                if (cancellationToken.CanBeCanceled) {
                    int result = WaitHandle.WaitAny(new[] {handle, cancellationToken.WaitHandle}, millisecondsTimeout, false);
                    if (result == 1)
                        throw new OperationCanceledException(cancellationToken.ToString());
                    if (result == WaitHandle.WaitTimeout)
                        return false;
                } else {
                    if (!handle.WaitOne(millisecondsTimeout, false))
                        return false;
                }
            }

            return true;
        }
Esempio n. 56
0
        /// <summary>
        /// Decreases the number of locks in use. If becoming zero, file gets unlocked.
        /// </summary>
        internal int DecreaseLockUse(bool decreaseToZero, string?lockId)
        {
            lockId = lockId ?? "none";
            SpinWait spinWait = new SpinWait();
            int      desiredLocksInUse;

            do
            {
                var currentLocksInUse = locksInUse;

                if (0 >= currentLocksInUse)
                {
                    Trace.WriteLine($"{CurrentThreadWithLockIdPrefix(lockId)} Number of lock remains at 0 because file has been unlocked before. {unlockSourceString(decreaseToZero)}", TraceCategory);
                    return(0);
                }

                if (decreaseToZero)
                {
                    desiredLocksInUse = 0;
                }
                else
                {
                    desiredLocksInUse = currentLocksInUse - 1;
                }

                var actualLocksInUse = Interlocked.CompareExchange(ref locksInUse, desiredLocksInUse, currentLocksInUse);

                if (currentLocksInUse == actualLocksInUse)
                {
                    break;
                }

                spinWait.SpinOnce();
            } while (true);

            string decreasedNumberOfLocksInUseMessage() =>
            $"{CurrentThreadWithLockIdPrefix(lockId)} Number of lock uses is decreased to {desiredLocksInUse}. {unlockSourceString(decreaseToZero)}";

            // When no locks are registered, we have to ..
            if (0 == desiredLocksInUse)
            {
                // 1. wait for file stream assignment,
                FileLockContext?nullState    = null;
                FileLockContext nonNullState = null !;

                while (true)
                {
                    nullState = Interlocked.CompareExchange(ref fileLockerState, null, nullState);

                    /* When class scoped file stream is null local file stream will be null too.
                     * => If so, spin once and continue loop.
                     *
                     * When class scoped file stream is not null the local file stream will become
                     * not null too.
                     * => If so, assigned class scoped file streama to to local non null file stream
                     *    and continue loop.
                     *
                     * When class scoped file stream is null and local non null file stream is not null
                     * => If so, break loop.
                     */
                    if (nullState == null && nonNullState is null)
                    {
                        spinWait.SpinOnce();
                    }
                    else if (nullState == null && !(nonNullState is null))
                    {
                        break;
                    }
                    else
                    {
                        nonNullState = nullState !;
                    }
                }

                // 2. invalidate the file stream.
                nonNullState.FileStream?.Close();
                nonNullState.FileStream?.Dispose();
                Trace.WriteLine($"{decreasedNumberOfLocksInUseMessage()}{Environment.NewLine}{CurrentThreadWithLockIdPrefix(lockId)} File {FilePath} unlocked by file locker. {unlockSourceString(decreaseToZero)}", TraceCategory);
            }
            else
            {
                Trace.WriteLine($"{decreasedNumberOfLocksInUseMessage()}");
            }

            return(desiredLocksInUse);
        }
Esempio n. 57
0
        /// <summary>
        /// Send the response data to the client.
        /// </summary>
        private void Sender()
        {
            // Make sure only one thread at a time is removing from the buffer.
            lock (_lockSender)
            {
                try
                {
                    // If the upper capacity of the buffer
                    // has been reached then stop writting
                    // until the response buffer gets to the
                    // lower capacity threshold.
                    if (_requestBuffer.IsUpperCapacityPercentage())
                    {
                        // Create the tasks.
                        Task[] tasks = new Task[1];
                        Interlocked.Exchange(ref _exitWaitSendIndicator, 0);

                        try
                        {
                            // Write to the response stream task.
                            Task writeToStream = Task.Factory.StartNew(() =>
                            {
                                // Create a new spin wait.
                                SpinWait sw = new SpinWait();

                                // Action to perform.
                                while (Interlocked.CompareExchange(ref _exitWaitSendIndicator, 0, 1) == 0)
                                {
                                    // The NextSpinWillYield property returns true if
                                    // calling sw.SpinOnce() will result in yielding the
                                    // processor instead of simply spinning.
                                    if (sw.NextSpinWillYield)
                                    {
                                        // Send the data to the client until
                                        // the lower capacity buffer has been
                                        // reached.
                                        SendData();

                                        // If the buffer is below the lower capacity
                                        // threshold then exist the spin wait.
                                        if (!_requestBuffer.IsLowerCapacityPercentage())
                                        {
                                            Interlocked.Exchange(ref _exitWaitSendIndicator, 1);
                                        }
                                    }

                                    // Performs a single spin.
                                    sw.SpinOnce();
                                }
                            });

                            // Assign the listener task.
                            tasks[0] = writeToStream;

                            // Wait for all tasks to complete.
                            Task.WaitAll(tasks);
                        }
                        catch { }

                        // For each task.
                        foreach (Task item in tasks)
                        {
                            try
                            {
                                // Release the resources.
                                item.Dispose();
                            }
                            catch { }
                        }
                        tasks = null;
                    }

                    // Send the data to the client.
                    SendData();
                }
                catch { }
            }
        }
Esempio n. 58
0
            // **** BACKGROUND THREAD ****
            private void WorkerLoop()
            {
                long?elapsedMs    = null;
                var  fileNameOnly = Path.GetFileName(_fileName);

#if EDITOR_TRACING
                var sw = new Stopwatch();
#endif

                try
                {
                    RazorEditorTrace.TraceLine(RazorResources.FormatTrace_BackgroundThreadStart(fileNameOnly));
                    EnsureOnThread();

#if DNXCORE50
                    var spinWait = new SpinWait();
#endif

                    while (!_shutdownToken.IsCancellationRequested)
                    {
                        // Grab the parcel of work to do
                        var parcel = _main.GetParcel();
                        if (parcel.Changes.Any())
                        {
                            RazorEditorTrace.TraceLine(RazorResources.FormatTrace_ChangesArrived(fileNameOnly, parcel.Changes.Count));
                            try
                            {
                                DocumentParseCompleteEventArgs args = null;
                                using (var linkedCancel = CancellationTokenSource.CreateLinkedTokenSource(_shutdownToken, parcel.CancelToken))
                                {
                                    if (!linkedCancel.IsCancellationRequested)
                                    {
                                        // Collect ALL changes
#if EDITOR_TRACING
                                        if (_previouslyDiscarded != null && _previouslyDiscarded.Any())
                                        {
                                            RazorEditorTrace.TraceLine(RazorResources.Trace_CollectedDiscardedChanges, fileNameOnly, _previouslyDiscarded.Count);
                                        }
#endif
                                        List <TextChange> allChanges;

                                        if (_previouslyDiscarded != null)
                                        {
                                            allChanges = Enumerable.Concat(_previouslyDiscarded, parcel.Changes).ToList();
                                        }
                                        else
                                        {
                                            allChanges = parcel.Changes.ToList();
                                        }

                                        var finalChange = allChanges.Last();
#if EDITOR_TRACING
                                        sw.Start();
#endif
                                        var results = ParseChange(finalChange.NewBuffer, linkedCancel.Token);
#if EDITOR_TRACING
                                        sw.Stop();
                                        elapsedMs = sw.ElapsedMilliseconds;
                                        sw.Reset();
#endif
                                        RazorEditorTrace.TraceLine(
                                            RazorResources.FormatTrace_ParseComplete(
                                                fileNameOnly,
                                                elapsedMs.HasValue ? elapsedMs.Value.ToString(CultureInfo.InvariantCulture) : "?"));

                                        if (results != null && !linkedCancel.IsCancellationRequested)
                                        {
                                            // Clear discarded changes list
                                            _previouslyDiscarded = null;

                                            // Take the current tree and check for differences
#if EDITOR_TRACING
                                            sw.Start();
#endif
                                            var treeStructureChanged = _currentParseTree == null || TreesAreDifferent(_currentParseTree, results.Document, allChanges, parcel.CancelToken);
#if EDITOR_TRACING
                                            sw.Stop();
                                            elapsedMs = sw.ElapsedMilliseconds;
                                            sw.Reset();
#endif
                                            _currentParseTree = results.Document;
                                            RazorEditorTrace.TraceLine(RazorResources.FormatTrace_TreesCompared(
                                                                           fileNameOnly,
                                                                           elapsedMs.HasValue ? elapsedMs.Value.ToString(CultureInfo.InvariantCulture) : "?",
                                                                           treeStructureChanged));

                                            // Build Arguments
                                            args = new DocumentParseCompleteEventArgs()
                                            {
                                                GeneratorResults     = results,
                                                SourceChange         = finalChange,
                                                TreeStructureChanged = treeStructureChanged
                                            };
                                        }
                                        else
                                        {
                                            // Parse completed but we were cancelled in the mean time. Add these to the discarded changes set
                                            RazorEditorTrace.TraceLine(RazorResources.FormatTrace_ChangesDiscarded(fileNameOnly, allChanges.Count));
                                            _previouslyDiscarded = allChanges;
                                        }

#if CHECK_TREE
                                        if (args != null)
                                        {
                                            // Rewind the buffer and sanity check the line mappings
                                            finalChange.NewBuffer.Position = 0;
                                            var lineCount = finalChange.NewBuffer.ReadToEnd().Split(new string[] { Environment.NewLine, "\r", "\n" }, StringSplitOptions.None).Count();
                                            Debug.Assert(
                                                !args.GeneratorResults.DesignTimeLineMappings.Any(pair => pair.Value.StartLine > lineCount),
                                                "Found a design-time line mapping referring to a line outside the source file!");
                                            Debug.Assert(
                                                !args.GeneratorResults.Document.Flatten().Any(span => span.Start.LineIndex > lineCount),
                                                "Found a span with a line number outside the source file");
                                            Debug.Assert(
                                                !args.GeneratorResults.Document.Flatten().Any(span => span.Start.AbsoluteIndex > parcel.NewBuffer.Length),
                                                "Found a span with an absolute offset outside the source file");
                                        }
#endif
                                    }
                                }
                                if (args != null)
                                {
                                    _main.ReturnParcel(args);
                                }
                            }
                            catch (OperationCanceledException)
                            {
                            }
                        }
                        else
                        {
                            RazorEditorTrace.TraceLine(RazorResources.FormatTrace_NoChangesArrived(fileNameOnly));
#if DNXCORE50
                            // This does the equivalent of thread.yield under the covers.
                            spinWait.SpinOnce();
#else
                            // No Yield in CoreCLR

                            Thread.Yield();
#endif
                        }
                    }
                }
                catch (OperationCanceledException)
                {
                    // Do nothing. Just shut down.
                }
                finally
                {
                    RazorEditorTrace.TraceLine(RazorResources.FormatTrace_BackgroundThreadShutdown(fileNameOnly));

                    // Clean up main thread resources
                    _main.Dispose();
                }
            }
Esempio n. 59
0
		private void Test(Func<long> generate, int threadCount, int generatedIdCount)
		{
			var waitingThreadCount = 0;
			var starterGun = new ManualResetEvent(false);

			var results = new long[generatedIdCount];
			var threads = Enumerable.Range(0, threadCount).Select(threadNumber => new Thread(() =>
			{
				// Wait for all threads to be ready
				Interlocked.Increment(ref waitingThreadCount);
				starterGun.WaitOne();

				for (int i = threadNumber; i < generatedIdCount; i += threadCount)
					results[i] = generate();
			})).ToArray();

			foreach (var t in threads)
				t.Start();

			// Wait for all tasks to reach the waiting stage
			var wait = new SpinWait();
			while (waitingThreadCount < threadCount)
				wait.SpinOnce();

			// Start all the threads at the same time
			starterGun.Set();
			foreach (var t in threads)
				t.Join();

			var ids = new HashSet<long>();
			foreach (var value in results)
			{
				if (!ids.Add(value))
				{
					throw new AssertException("Id " + value + " was generated more than once, in indices "
						+ string.Join(", ", results.Select(Tuple.Create<long, int>).Where(x => x.Item1 == value).Select(x => x.Item2)));
				}
			}

			for (long i = 1; i <= GeneratedIdCount; i++)
				Assert.True(ids.Contains(i), "Id " + i + " was not generated.");
		}
Esempio n. 60
0
        private void ProcessMeasurements()
        {
            List <IMeasurement> measurements = new List <IMeasurement>((int)(Ticks.ToSeconds(GapThreshold) * m_sampleRate * m_channels * 1.1D));

            LittleBinaryValue[] sample;

            while (Enabled)
            {
                try
                {
                    SpinWait spinner = new SpinWait();

                    // Determine what time it is now
                    long now = DateTime.UtcNow.Ticks;

                    // Assign a timestamp to the next sample based on its location
                    // in the file relative to the other samples in the file
                    long timestamp = m_startTime + (m_dataIndex * Ticks.PerSecond / m_sampleRate);

                    if (now - timestamp > GapThreshold)
                    {
                        // Reset the start time and delay next transmission in an attempt to catch up
                        m_startTime = now - (m_dataIndex * Ticks.PerSecond / m_sampleRate) + Ticks.FromSeconds(RecoveryDelay);
                        timestamp   = now;
                        OnStatusMessage(MessageLevel.Info, "Start time reset.");
                    }

                    // Keep generating measurements until
                    // we catch up to the current time.
                    while (timestamp < now)
                    {
                        sample = m_dataReader.GetNextSample();

                        // If the sample is null, we've reached the end of the file - close and reopen,
                        // resetting the data index and start time
                        if (sample == null)
                        {
                            m_dataReader.Close();
                            m_dataReader.Dispose();

                            m_dataReader = OpenWaveDataReader();
                            m_dataIndex  = 0;

                            m_startTime = timestamp;
                            sample      = m_dataReader.GetNextSample();
                        }

                        // Create new measurements, one for each channel, and add them to the measurements list
                        for (int i = 0; i < m_channels; i++)
                        {
                            measurements.Add(Measurement.Clone(OutputMeasurements[i], sample[i].ConvertToType(TypeCode.Double), timestamp));
                        }

                        // Update the data index and recalculate the assigned timestamp for the next sample
                        m_dataIndex++;
                        timestamp = m_startTime + (m_dataIndex * Ticks.PerSecond / m_sampleRate);
                    }

                    OnNewMeasurements(measurements);
                    measurements.Clear();

                    while (DateTime.UtcNow.Ticks - timestamp <= GapThreshold / 100)
                    {
                        // Ahead of schedule -- pause for a moment
                        spinner.SpinOnce();
                    }
                }
                catch (Exception ex)
                {
                    OnProcessException(MessageLevel.Warning, ex);
                }
            }
        }