Esempio n. 1
0
        internal void BuildNodeList(int level, DispatcherNode[] nodeList, string[] keyParts)
        {
            // find/create subnode
            nodeList[_Level] = this;
            DispatcherNode subNode;

            _ChildIndexLock.Enter();
            try
            {
                if (!_ChildIndex.TryGetValue(keyParts[_Level], out subNode))
                {
                    subNode = new DispatcherNode(_Dispatcher, _Level + 1, this);
                    _ChildIndex.Add(keyParts[_Level], subNode);
                }
            }
            finally
            {
                _ChildIndexLock.Leave();
            }
            nodeList[_Level + 1] = subNode;
            if (level > (_Level + 1))
            {
                subNode.BuildNodeList(level, nodeList, keyParts);
            }
        }
Esempio n. 2
0
 // constructors
 internal DispatcherNode(Dispatcher Dispatcher, int level, DispatcherNode parent)
 {
     _Dispatcher = Dispatcher;
     if (level < 0)
     {
         throw new ArgumentException("Invalid", nameof(level));
     }
     _Level = level;
     if ((level == 0) && (parent != null))
     {
         throw new ArgumentException("Invalid", nameof(parent));
     }
     if ((level > 0) && (parent == null))
     {
         throw new ArgumentNullException(nameof(parent));
     }
     _Parent = parent;
 }
Esempio n. 3
0
        private void ProcessNode(DispatcherItem completedItem)
        {
            long threadsInTree = IncThreadsInTree();

            try
            {
                if (completedItem != null)
                {
                    // completed item cleanup
                    DecThreadsInTree();
                    long debugN = Interlocked.Decrement(ref _ThisNodeRunning);
                    Debug.Assert(debugN == 0);
                    _Parent?.DecChildrenRunning();
                    completedItem = null;
                }

                bool looping = true;
                while (looping)
                {
                    looping = false;
                    // ensure that at least one pass through the dequeuing logic occurs
                    _Queue.Locked((queue) =>
                    {
                        // we have the queue
                        // we can dispatch the head of the queue if:
                        // a) the item is for this level, AND this tree is not running;
                        // or b) the item is for a lower level, AND this node is not running.
                        if (queue.Count > 0)
                        {
                            DispatcherItem workItem = queue.Peek();
                            Debug.Assert(workItem.Level >= _Level);
                            if ((workItem.Level == _Level) &&
                                (Interlocked.Add(ref _ThisNodeRunning, 0) == 0) &&
                                (Interlocked.Add(ref _ChildrenRunning, 0) == 0))
                            {
                                // item is for this level
                                // dispatch it to the threadpool
                                queue.Dequeue();
                                long debugN = Interlocked.Increment(ref _ThisNodeRunning);
                                Debug.Assert(debugN == 1);
                                IncThreadsInTree();
                                ThreadPool.QueueUserWorkItem(CallbackWrapper, workItem);
                            }
                            if ((workItem.Level > _Level) &&
                                (Interlocked.Add(ref _ThisNodeRunning, 0) == 0))
                            {
                                // item is for lower level
                                // enqueue it to the child
                                queue.Dequeue();
                                Interlocked.Increment(ref _ChildrenRunning);
                                DispatcherNode childNode = workItem.NodeList[_Level + 1];
                                childNode.Enqueue(workItem);
                                // dequeue next
                                looping = true;
                            }
                        }
                    });
                } // while looping
            }
            finally
            {
                threadsInTree = DecThreadsInTree();
            }
            if ((threadsInTree == 0) && (_Parent != null))
            {
                // we are the last thread in this tree - handoff to parent
                ThreadPool.QueueUserWorkItem(_Parent.AsyncProcessNode, null);
            }
        }