]> git.sesse.net Git - stockfish/blob - src/thread.h
Use thread specific mutexes instead of a global one.
[stockfish] / src / thread.h
1 /*
2   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3   Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4   Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5
6   Stockfish is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10
11   Stockfish is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifndef THREAD_H_INCLUDED
21 #define THREAD_H_INCLUDED
22
23 #include <atomic>
24 #include <bitset>
25 #include <condition_variable>
26 #include <mutex>
27 #include <thread>
28 #include <vector>
29
30 #include "material.h"
31 #include "movepick.h"
32 #include "pawns.h"
33 #include "position.h"
34 #include "search.h"
35 #include "thread_win32.h"
36
37 struct Thread;
38
39 const size_t MAX_THREADS = 128;
40 const size_t MAX_SPLITPOINTS_PER_THREAD = 8;
41 const size_t MAX_SLAVES_PER_SPLITPOINT = 4;
42
43
44 /// SplitPoint struct stores information shared by the threads searching in
45 /// parallel below the same split point. It is populated at splitting time.
46
47 struct SplitPoint {
48
49   // Const data after split point has been setup
50   const Position* pos;
51   Search::Stack* ss;
52   Thread* master;
53   Depth depth;
54   Value beta;
55   int nodeType;
56   bool cutNode;
57
58   // Const pointers to shared data
59   MovePicker* movePicker;
60   SplitPoint* parentSplitPoint;
61
62   // Shared variable data
63   Mutex mutex;
64   std::bitset<MAX_THREADS> slavesMask;
65   volatile bool allSlavesSearching;
66   volatile uint64_t nodes;
67   volatile Value alpha;
68   volatile Value bestValue;
69   volatile Move bestMove;
70   volatile int moveCount;
71   volatile bool cutoff;
72 };
73
74
75 /// ThreadBase struct is the base of the hierarchy from where we derive all the
76 /// specialized thread classes.
77
78 struct ThreadBase {
79
80   virtual ~ThreadBase() = default;
81   virtual void idle_loop() = 0;
82   void notify_one();
83   void wait_for(volatile const bool& b);
84
85   std::thread nativeThread;
86   Mutex mutex;
87   ConditionVariable sleepCondition;
88   volatile bool exit = false;
89 };
90
91
92 /// Thread struct keeps together all the thread related stuff like locks, state
93 /// and especially split points. We also use per-thread pawn and material hash
94 /// tables so that once we get a pointer to an entry its life time is unlimited
95 /// and we don't have to care about someone changing the entry under our feet.
96
97 struct Thread : public ThreadBase {
98
99   Thread();
100   virtual void idle_loop();
101   bool cutoff_occurred() const;
102   bool can_join(const SplitPoint* sp) const;
103
104   void split(Position& pos, Search::Stack* ss, Value alpha, Value beta, Value* bestValue, Move* bestMove,
105              Depth depth, int moveCount, MovePicker* movePicker, int nodeType, bool cutNode);
106
107   SplitPoint splitPoints[MAX_SPLITPOINTS_PER_THREAD];
108   Pawns::Table pawnsTable;
109   Material::Table materialTable;
110   Endgames endgames;
111   Position* activePosition;
112   size_t idx;
113   int maxPly;
114   SplitPoint* volatile activeSplitPoint;
115   volatile size_t splitPointsSize;
116   volatile bool searching;
117 };
118
119
120 /// MainThread and TimerThread are derived classes used to characterize the two
121 /// special threads: the main one and the recurring timer.
122
123 struct MainThread : public Thread {
124   virtual void idle_loop();
125   volatile bool thinking = true; // Avoid a race with start_thinking()
126 };
127
128 struct TimerThread : public ThreadBase {
129
130   static const int Resolution = 5; // Millisec between two check_time() calls
131
132   virtual void idle_loop();
133
134   bool run = false;
135 };
136
137
138 /// ThreadPool struct handles all the threads related stuff like init, starting,
139 /// parking and, most importantly, launching a slave thread at a split point.
140 /// All the access to shared thread data is done through this class.
141
142 struct ThreadPool : public std::vector<Thread*> {
143
144   void init(); // No c'tor and d'tor, threads rely on globals that should be
145   void exit(); // initialized and are valid during the whole thread lifetime.
146
147   MainThread* main() { return static_cast<MainThread*>(at(0)); }
148   void read_uci_options();
149   Thread* available_slave(const SplitPoint* sp) const;
150   void wait_for_think_finished();
151   void start_thinking(const Position&, const Search::LimitsType&, Search::StateStackPtr&);
152
153   Depth minimumSplitDepth;
154   ConditionVariable sleepCondition;
155   TimerThread* timer;
156 };
157
158 extern ThreadPool Threads;
159
160 #endif // #ifndef THREAD_H_INCLUDED