-#else
-
- DWORD WINAPI init_thread(LPVOID threadID) {
-
- ThreadsMgr.idle_loop(*(int*)threadID, NULL);
- return 0;
- }
-
-#endif
-
-
- /// The ThreadsManager class
-
- // resetNodeCounters(), resetBetaCounters(), searched_nodes() and
- // get_beta_counters() are getters/setters for the per thread
- // counters used to sort the moves at root.
-
- void ThreadsManager::resetNodeCounters() {
-
- for (int i = 0; i < MAX_THREADS; i++)
- threads[i].nodes = 0ULL;
- }
-
- int64_t ThreadsManager::nodes_searched() const {
-
- int64_t result = 0ULL;
- for (int i = 0; i < ActiveThreads; i++)
- result += threads[i].nodes;
-
- return result;
- }
-
-
- // idle_loop() is where the threads are parked when they have no work to do.
- // The parameter 'sp', if non-NULL, is a pointer to an active SplitPoint
- // object for which the current thread is the master.
-
- void ThreadsManager::idle_loop(int threadID, SplitPoint* sp) {
-
- assert(threadID >= 0 && threadID < MAX_THREADS);
-
- while (true)
- {
- // Slave threads can exit as soon as AllThreadsShouldExit raises,
- // master should exit as last one.
- if (AllThreadsShouldExit)
- {
- assert(!sp);
- threads[threadID].state = THREAD_TERMINATED;
- return;
- }
-
- // If we are not thinking, wait for a condition to be signaled
- // instead of wasting CPU time polling for work.
- while (AllThreadsShouldSleep || threadID >= ActiveThreads)
- {
- assert(!sp);
- assert(threadID != 0);
- threads[threadID].state = THREAD_SLEEPING;
-
-#if !defined(_MSC_VER)
- lock_grab(&WaitLock);
- if (AllThreadsShouldSleep || threadID >= ActiveThreads)
- pthread_cond_wait(&WaitCond, &WaitLock);
- lock_release(&WaitLock);
-#else
- WaitForSingleObject(SitIdleEvent[threadID], INFINITE);
-#endif
- }
-
- // If thread has just woken up, mark it as available
- if (threads[threadID].state == THREAD_SLEEPING)
- threads[threadID].state = THREAD_AVAILABLE;
-
- // If this thread has been assigned work, launch a search
- if (threads[threadID].state == THREAD_WORKISWAITING)
- {
- assert(!AllThreadsShouldExit && !AllThreadsShouldSleep);
-
- threads[threadID].state = THREAD_SEARCHING;
-
- if (threads[threadID].splitPoint->pvNode)
- do_sp_search<PV>(threads[threadID].splitPoint, threadID);
- else
- do_sp_search<NonPV>(threads[threadID].splitPoint, threadID);
-
- assert(threads[threadID].state == THREAD_SEARCHING);
-
- threads[threadID].state = THREAD_AVAILABLE;
- }
-
- // 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.
- int i = 0;
- for ( ; sp && i < ActiveThreads && !sp->slaves[i]; i++) {}
-
- if (i == ActiveThreads)
- {
- // Because sp->slaves[] is reset under lock protection,
- // be sure sp->lock has been released before to return.
- lock_grab(&(sp->lock));
- lock_release(&(sp->lock));
-
- // In helpful master concept a master can help only a sub-tree, and
- // because here is all finished is not possible master is booked.
- assert(threads[threadID].state == THREAD_AVAILABLE);
-
- threads[threadID].state = THREAD_SEARCHING;
- return;
- }
- }
- }
-
-
- // init_threads() is called during startup. It launches all helper threads,
- // and initializes the split point stack and the global locks and condition
- // objects.
-
- void ThreadsManager::init_threads() {
-
- volatile int i;
- bool ok;
-
-#if !defined(_MSC_VER)
- pthread_t pthread[1];
-#endif
-
- // Initialize global locks
- lock_init(&MPLock);
- lock_init(&WaitLock);
-
-#if !defined(_MSC_VER)
- pthread_cond_init(&WaitCond, NULL);
-#else
- for (i = 0; i < MAX_THREADS; i++)
- SitIdleEvent[i] = CreateEvent(0, FALSE, FALSE, 0);
-#endif