Example #1
0
        public void AddQueueWaitNode(QueueEntry entry, InMemoryQueueWaitNode node)
        {
            var headNext = node.Next = null;
            var spinWait = new SpinWait();

            while (true)
            {
                var newNext = Interlocked.CompareExchange(ref entry.WaitHead.Next, node, headNext);
                if (newNext == headNext)
                {
                    break;
                }

                headNext = node.Next = newNext;
                spinWait.SpinOnce();
            }
        }
        public override IFetchedJob FetchNextJob(string[] queueNames, CancellationToken cancellationToken)
        {
            using (var ready = new SemaphoreSlim(0, queueNames.Length))
            {
                var waitNode  = new InMemoryQueueWaitNode(ready);
                var waitAdded = false;

                while (!cancellationToken.IsCancellationRequested)
                {
                    // TODO: Ensure duplicate queue names do not fail everything
                    var entries = _dispatcher.GetOrAddQueues(queueNames);

                    foreach (var entry in entries)
                    {
                        if (entry.Value.Queue.TryDequeue(out var jobId))
                        {
                            _dispatcher.SignalOneQueueWaitNode(entry.Value);
                            return(new InMemoryFetchedJob(_dispatcher, entry.Key, jobId));
                        }
                    }

                    if (!waitAdded && ready.CurrentCount == 0)
                    {
                        foreach (var entry in entries)
                        {
                            _dispatcher.AddQueueWaitNode(entry.Value, waitNode);
                        }

                        waitAdded = true;
                        continue;
                    }

                    ready.Wait(cancellationToken);
                    waitAdded = false;
                }
            }

            cancellationToken.ThrowIfCancellationRequested();
            return(null);
        }