/// <summary>
        /// When an entry is archived, we need to attempt scavenging to cleanup the list
        /// </summary>
        public void OnEntryArchived(QueueEntry entry)
        {
            var next    = head.Next;
            var newNext = head.GetNextValidEntry();

            if (next == newNext)
            {
                // the head of the queue has not been archived, hence the archival must have been mid queue.

                // so update unscavengedEntry if entry is further back in the queue than the current unscavengedEntry value
                var currentUnscavengedEntry = unscavengedEntry;
                while (currentUnscavengedEntry == null || currentUnscavengedEntry.CompareTo(entry) < 0)
                {
                    Interlocked.CompareExchange(ref unscavengedEntry, entry, currentUnscavengedEntry);
                    currentUnscavengedEntry = unscavengedEntry;
                }

                // only going to scavenge() after N entries have been scavenged
                if (Interlocked.Increment(ref scavenges) > 10)
                {
                    Interlocked.Exchange(ref scavenges, 0);
                    Scavenge();
                }
            }
            else
            {
                // the head has been scavenged
                var currentUnscavengedEntry = unscavengedEntry;
                if (currentUnscavengedEntry != null && (next == null || currentUnscavengedEntry.CompareTo(next) < 0))
                {
                    Interlocked.CompareExchange(ref unscavengedEntry, null, currentUnscavengedEntry);
                    currentUnscavengedEntry = unscavengedEntry;
                }
            }
        }
示例#2
0
        public void TryDelivery(QueueEntry head)
        {
            // TODO: check link credit to determine if we can deliver
            if (!HasCreditToDeliver())
            {
                return;
            }

            lock (syncRoot)
            {
                var next = head.GetNextValidEntry();
                while (next != null)
                {
                    if (next.IsAvailable)
                    {
                        // TODO: FILTER out entries we don't care about

                        if (queue.TryAcquire(next, this))
                        {
                            break; // if not acquired, we'll try again with the next one
                        }
                    }

                    // loop until we get an available entry to deliver
                    // or null
                    next = next.GetNextValidEntry();
                }

                if (next == null)
                {
                    return; // nothing to deliver
                }
                if (next != null)
                {
                    // message acquired and ready to be delivered
                    OnMessageAquired(next);
                }
            }
        }