- // ThreadsManager class is used to handle all the threads related stuff in search,
- // init, starting, parking and, the most important, launching a slave thread at a
- // split point are what this class does. All the access to shared thread data is
- // done through this class, so that we avoid using global variables instead.
-
- class ThreadsManager {
- /* As long as the single ThreadsManager object is defined as a global we don't
- need to explicitly initialize to zero its data members because variables with
- static storage duration are automatically set to zero before enter main()
- */
- public:
- void init_threads();
- void exit_threads();
-
- int active_threads() const { return ActiveThreads; }
- void set_active_threads(int newActiveThreads) { ActiveThreads = newActiveThreads; }
- void incrementNodeCounter(int threadID) { threads[threadID].nodes++; }
-
- void resetNodeCounters();
- int64_t nodes_searched() const;
- bool available_thread_exists(int master) const;
- bool thread_is_available(int slave, int master) const;
- bool thread_should_stop(int threadID) const;
- void wake_sleeping_thread(int threadID);
- void put_threads_to_sleep();
- void idle_loop(int threadID, SplitPoint* sp);
-
- template <bool Fake>
- void split(const Position& pos, SearchStack* ss, int ply, Value* alpha, const Value beta, Value* bestValue,
- Depth depth, Move threatMove, bool mateThreat, int moveCount, MovePicker* mp, bool pvNode);
-
- private:
- friend void poll();
-
- int ActiveThreads;
- volatile bool AllThreadsShouldExit;
- Thread threads[MAX_THREADS];
- Lock MPLock, WaitLock;
- WaitCondition WaitCond[MAX_THREADS];
- };
-
-
- // RootMove struct is used for moves at the root at the tree. For each
- // root move, we store a score, a node count, and a PV (really a refutation
- // in the case of moves which fail low).
-
- struct RootMove {
-
- RootMove() : mp_score(0), nodes(0) {}
-
- // RootMove::operator<() is the comparison function used when
- // sorting the moves. A move m1 is considered to be better
- // than a move m2 if it has a higher score, or if the moves
- // have equal score but m1 has the higher beta cut-off count.
- bool operator<(const RootMove& m) const {
-
- return score != m.score ? score < m.score : mp_score <= m.mp_score;
- }
-
- Move move;
- Value score;
- int mp_score;
- int64_t nodes;
- Move pv[PLY_MAX_PLUS_2];
- };
-
-
- // The RootMoveList class is essentially an array of RootMove objects, with
- // a handful of methods for accessing the data in the individual moves.
-
- class RootMoveList {
-
- public:
- RootMoveList(Position& pos, Move searchMoves[]);
-
- Move move(int moveNum) const { return moves[moveNum].move; }
- Move move_pv(int moveNum, int i) const { return moves[moveNum].pv[i]; }
- int move_count() const { return count; }
- Value move_score(int moveNum) const { return moves[moveNum].score; }
- int64_t move_nodes(int moveNum) const { return moves[moveNum].nodes; }
- void add_move_nodes(int moveNum, int64_t nodes) { moves[moveNum].nodes += nodes; }
- void set_move_score(int moveNum, Value score) { moves[moveNum].score = score; }
-
- void set_move_pv(int moveNum, const Move pv[]);
- void score_moves(const Position& pos);
- void sort();
- void sort_multipv(int n);
-
- private:
- RootMove moves[MOVES_MAX];
- int count;
- };
-
-
- // When formatting a move for std::cout we must know if we are in Chess960
- // or not. To keep using the handy operator<<() on the move the trick is to
- // embed this flag in the stream itself. Function-like named enum set960 is
- // used as a custom manipulator and the stream internal general-purpose array,
- // accessed through ios_base::iword(), is used to pass the flag to the move's
- // operator<<() that will use it to properly format castling moves.
- enum set960 {};
-
- std::ostream& operator<< (std::ostream& os, const set960& m) {
-
- os.iword(0) = int(m);
- return os;
- }
-
-
- /// Adjustments