示例#1
0
        internal Thread(ThreadLoopType lt, ManualResetEvent initEvent)
        {
            is_searching  = do_exit = false;
            maxPly        = splitPointsCnt = 0;
            curSplitPoint = null;
            loopType      = lt;
            idx           = Threads.size();

            do_sleep = loopType != ThreadLoopType.Main; // Avoid a race with start_searching()

            for (int j = 0; j < Constants.MAX_SPLITPOINTS_PER_THREAD; j++)
            {
                splitPoints[j] = new SplitPoint();
            }

#if WINDOWS_RT
            Windows.Foundation.IAsyncAction action = Windows.System.Threading.ThreadPool.RunAsync(delegate { StartThread(initEvent); }, WorkItemPriority.Normal);
#else
            ThreadPool.QueueUserWorkItem(this.StartThread, initEvent);
#endif
        }
示例#2
0
        /// Thread::idle_loop() is where the thread is parked when it has no work to do.
        /// The parameter 'master_sp', if non-NULL, is a pointer to an active SplitPoint
        /// object for which the thread is the master.
        internal void idle_loop(SplitPoint sp_master, ManualResetEvent initEvent)
        {
            if (initEvent != null)
            {
                // Signal done
                initEvent.Set();
            }

            bool use_sleeping_threads = Threads.useSleepingThreads;

            // If this thread is the master of a split point and all slaves have
            // finished their work at this split point, return from the idle loop.
            while ((sp_master == null) || (sp_master.slavesMask != 0))
            {
                // If we are not searching, wait for a condition to be signaled
                // instead of wasting CPU time polling for work.
                while (do_sleep ||
                       do_exit ||
                       (!is_searching && use_sleeping_threads))
                {
                    if (do_exit)
                    {
                        Debug.Assert(sp_master == null);
                        return;
                    }

                    // Grab the lock to avoid races with Thread::wake_up()
                    ThreadHelper.lock_grab(sleepLock);

                    // If we are master and all slaves have finished don't go to sleep
                    if ((sp_master != null) && (sp_master.slavesMask == 0))
                    {
                        ThreadHelper.lock_release(sleepLock);
                        break;
                    }

                    // Do sleep after retesting sleep conditions under lock protection, in
                    // particular we need to avoid a deadlock in case a master thread has,
                    // in the meanwhile, allocated us and sent the wake_up() call before we
                    // had the chance to grab the lock.
                    if (do_sleep || !is_searching)
                    {
                        ThreadHelper.cond_wait(sleepCond, sleepLock);
                    }

                    ThreadHelper.lock_release(sleepLock);
                }

                // If this thread has been assigned work, launch a search
                if (is_searching)
                {
                    Debug.Assert(!do_sleep && !do_exit);

                    ThreadHelper.lock_grab(Threads.splitLock);

                    Debug.Assert(is_searching);
                    SplitPoint sp = curSplitPoint;

                    ThreadHelper.lock_release(Threads.splitLock);

                    LoopStack ls    = LoopStackBroker.GetObject();
                    Stack[]   ss    = ls.ss;
                    int       ssPos = 0;

                    Position pos = PositionBroker.GetObject();
                    pos.copy(sp.pos, this);

                    Array.Copy(sp.ss, sp.ssPos - 1, ss, ssPos, 4);
                    ss[ssPos + 1].sp = sp;

                    ThreadHelper.lock_grab(sp.Lock);

                    if (sp.nodeType == NodeTypeC.Root)
                    {
                        Search.search(NodeTypeC.SplitPointRoot, pos, ss, ssPos + 1, sp.alpha, sp.beta, sp.depth);
                    }
                    else if (sp.nodeType == NodeTypeC.PV)
                    {
                        Search.search(NodeTypeC.SplitPointPV, pos, ss, ssPos + 1, sp.alpha, sp.beta, sp.depth);
                    }
                    else if (sp.nodeType == NodeTypeC.NonPV)
                    {
                        Search.search(NodeTypeC.SplitPointNonPV, pos, ss, ssPos + 1, sp.alpha, sp.beta, sp.depth);
                    }
                    else
                    {
                        Debug.Assert(false);
                    }

                    Debug.Assert(is_searching);

                    is_searching = false;
#if ACTIVE_REPARENT
                    sp.allSlavesRunning = false;
#endif
                    sp.slavesMask &= ~(1UL << idx);
                    sp.nodes      += pos.nodes;

                    // Wake up master thread so to allow it to return from the idle loop in
                    // case we are the last slave of the split point.
                    if (use_sleeping_threads &&
                        this != sp.master &&
                        !sp.master.is_searching)
                    {
                        sp.master.wake_up();
                    }

                    // After releasing the lock we cannot access anymore any SplitPoint
                    // related data in a safe way becuase it could have been released under
                    // our feet by the sp master. Also accessing other Thread objects is
                    // unsafe because if we are exiting there is a chance are already freed.
                    ThreadHelper.lock_release(sp.Lock);

#if ACTIVE_REPARENT
                    // Try to reparent to the first split point, with still all slaves
                    // running, where we are available as a possible slave.
                    for (int i = 0; i < Threads.size(); i++)
                    {
                        Thread     th     = Threads.threads[i];
                        int        spCnt  = th.splitPointsCnt;
                        SplitPoint latest = th.splitPoints[spCnt != 0 ? spCnt - 1 : 0];

                        if (this.is_available_to(th) &&
                            spCnt > 0 &&
                            !th.cutoff_occurred() &&
                            latest.allSlavesRunning &&
                            Utils.more_than_one(latest.slavesMask))
                        {
                            ThreadHelper.lock_grab(latest.Lock);
                            ThreadHelper.lock_grab(Threads.splitLock);

                            // Retest all under lock protection, we are in the middle
                            // of a race storm here !
                            if (this.is_available_to(th) &&
                                spCnt == th.splitPointsCnt &&
                                !th.cutoff_occurred() &&
                                latest.allSlavesRunning &&
                                Utils.more_than_one(latest.slavesMask))
                            {
                                latest.slavesMask |= 1UL << idx;
                                curSplitPoint      = latest;
                                is_searching       = true;
                            }

                            ThreadHelper.lock_release(Threads.splitLock);
                            ThreadHelper.lock_release(latest.Lock);

                            break; // Exit anyhow, only one try (enough in 99% of cases)
                        }
                    }
#endif

                    pos.startState = null;
                    pos.st         = null;
                    PositionBroker.Free();
                    LoopStackBroker.Free(ls);
                }
            }
        }