mirror of
https://github.com/sockspls/badfish
synced 2025-05-01 09:13:08 +00:00
Refactor Thread class
Associate platform OS thread to the Thread class instead of creating it from ThreadsManager. No functional change. Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
parent
f01b53c374
commit
553655eb07
6 changed files with 82 additions and 83 deletions
|
@ -84,12 +84,6 @@ namespace {
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
/// MaterialInfoTable c'tor and d'tor allocate and free the space for Endgames
|
|
||||||
|
|
||||||
void MaterialInfoTable::init() { Base::init(); if (!funcs) funcs = new Endgames(); }
|
|
||||||
MaterialInfoTable::~MaterialInfoTable() { delete funcs; }
|
|
||||||
|
|
||||||
|
|
||||||
/// MaterialInfoTable::material_info() takes a position object as input,
|
/// MaterialInfoTable::material_info() takes a position object as input,
|
||||||
/// computes or looks up a MaterialInfo object, and returns a pointer to it.
|
/// computes or looks up a MaterialInfo object, and returns a pointer to it.
|
||||||
/// If the material configuration is not already present in the table, it
|
/// If the material configuration is not already present in the table, it
|
||||||
|
|
|
@ -72,8 +72,9 @@ private:
|
||||||
|
|
||||||
class MaterialInfoTable : public SimpleHash<MaterialInfo, MaterialTableSize> {
|
class MaterialInfoTable : public SimpleHash<MaterialInfo, MaterialTableSize> {
|
||||||
public:
|
public:
|
||||||
~MaterialInfoTable();
|
MaterialInfoTable() : funcs(new Endgames()) {}
|
||||||
void init();
|
~MaterialInfoTable() { delete funcs; }
|
||||||
|
|
||||||
MaterialInfo* material_info(const Position& pos) const;
|
MaterialInfo* material_info(const Position& pos) const;
|
||||||
static Phase game_phase(const Position& pos);
|
static Phase game_phase(const Position& pos);
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ typedef void*(*start_fn)(void*);
|
||||||
# define cond_signal(x) pthread_cond_signal(&(x))
|
# define cond_signal(x) pthread_cond_signal(&(x))
|
||||||
# define cond_wait(x,y) pthread_cond_wait(&(x),&(y))
|
# define cond_wait(x,y) pthread_cond_wait(&(x),&(y))
|
||||||
# define cond_timedwait(x,y,z) pthread_cond_timedwait(&(x),&(y),z)
|
# define cond_timedwait(x,y,z) pthread_cond_timedwait(&(x),&(y),z)
|
||||||
# define thread_create(x,f,id) !pthread_create(&(x),NULL,(start_fn)f,&(id))
|
# define thread_create(x,f,t) !pthread_create(&(x),NULL,(start_fn)f,t)
|
||||||
# define thread_join(x) pthread_join(x, NULL)
|
# define thread_join(x) pthread_join(x, NULL)
|
||||||
|
|
||||||
#else // Windows and MinGW
|
#else // Windows and MinGW
|
||||||
|
@ -101,7 +101,7 @@ typedef HANDLE ThreadHandle;
|
||||||
# define cond_signal(x) SetEvent(x)
|
# define cond_signal(x) SetEvent(x)
|
||||||
# define cond_wait(x,y) { lock_release(y); WaitForSingleObject(x, INFINITE); lock_grab(y); }
|
# define cond_wait(x,y) { lock_release(y); WaitForSingleObject(x, INFINITE); lock_grab(y); }
|
||||||
# define cond_timedwait(x,y,z) { lock_release(y); WaitForSingleObject(x,z); lock_grab(y); }
|
# define cond_timedwait(x,y,z) { lock_release(y); WaitForSingleObject(x,z); lock_grab(y); }
|
||||||
# define thread_create(x,f,id) (x = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)f,&(id),0,NULL), x != NULL)
|
# define thread_create(x,f,t) (x = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)f,t,0,NULL), x != NULL)
|
||||||
# define thread_join(x) { WaitForSingleObject(x, INFINITE); CloseHandle(x); }
|
# define thread_join(x) { WaitForSingleObject(x, INFINITE); CloseHandle(x); }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
133
src/thread.cpp
133
src/thread.cpp
|
@ -53,6 +53,45 @@ namespace { extern "C" {
|
||||||
} }
|
} }
|
||||||
|
|
||||||
|
|
||||||
|
Thread::Thread(int id) {
|
||||||
|
|
||||||
|
threadID = id;
|
||||||
|
do_sleep = (id != 0); // Avoid a race with start_thinking()
|
||||||
|
is_searching = do_exit = false;
|
||||||
|
maxPly = splitPointsCnt = 0;
|
||||||
|
curSplitPoint = NULL;
|
||||||
|
|
||||||
|
lock_init(sleepLock);
|
||||||
|
cond_init(sleepCond);
|
||||||
|
|
||||||
|
for (int j = 0; j < MAX_SPLITPOINTS_PER_THREAD; j++)
|
||||||
|
lock_init(splitPoints[j].lock);
|
||||||
|
|
||||||
|
if (!thread_create(handle, start_routine, this))
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to create thread number " << id << std::endl;
|
||||||
|
::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Thread::~Thread() {
|
||||||
|
|
||||||
|
assert(do_sleep);
|
||||||
|
|
||||||
|
do_exit = true; // Search must be already finished
|
||||||
|
wake_up();
|
||||||
|
|
||||||
|
thread_join(handle); // Wait for thread termination
|
||||||
|
|
||||||
|
lock_destroy(sleepLock);
|
||||||
|
cond_destroy(sleepCond);
|
||||||
|
|
||||||
|
for (int j = 0; j < MAX_SPLITPOINTS_PER_THREAD; j++)
|
||||||
|
lock_destroy(splitPoints[j].lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Thread::timer_loop() is where the timer thread waits maxPly milliseconds and
|
// Thread::timer_loop() is where the timer thread waits maxPly milliseconds and
|
||||||
// then calls do_timer_event(). If maxPly is 0 thread sleeps until is woken up.
|
// then calls do_timer_event(). If maxPly is 0 thread sleeps until is woken up.
|
||||||
extern void check_time();
|
extern void check_time();
|
||||||
|
@ -175,15 +214,16 @@ void ThreadsManager::read_uci_options() {
|
||||||
useSleepingThreads = Options["Use Sleeping Threads"];
|
useSleepingThreads = Options["Use Sleeping Threads"];
|
||||||
activeThreads = Options["Threads"];
|
activeThreads = Options["Threads"];
|
||||||
|
|
||||||
// Dynamically allocate pawn and material hash tables according to the
|
// Dynamically allocate Thread object according to the number of
|
||||||
// number of active threads. This avoids preallocating memory for all
|
// active threads. This avoids preallocating memory for all possible
|
||||||
// possible threads if only few are used.
|
// threads if only few are used.
|
||||||
for (int i = 0; i < MAX_THREADS; i++)
|
for (int i = 0; i < MAX_THREADS; i++)
|
||||||
if (i < activeThreads)
|
if (i < activeThreads && !threads[i])
|
||||||
|
threads[i] = new Thread(i);
|
||||||
|
else if (i >= activeThreads && threads[i])
|
||||||
{
|
{
|
||||||
threads[i].pawnTable.init();
|
delete threads[i];
|
||||||
threads[i].materialTable.init();
|
threads[i] = NULL;
|
||||||
threads[i].maxPly = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,8 +232,8 @@ void ThreadsManager::wake_up() {
|
||||||
|
|
||||||
for (int i = 0; i < activeThreads; i++)
|
for (int i = 0; i < activeThreads; i++)
|
||||||
{
|
{
|
||||||
threads[i].do_sleep = false;
|
threads[i]->do_sleep = false;
|
||||||
threads[i].wake_up();
|
threads[i]->wake_up();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +241,7 @@ void ThreadsManager::wake_up() {
|
||||||
void ThreadsManager::sleep() {
|
void ThreadsManager::sleep() {
|
||||||
|
|
||||||
for (int i = 0; i < activeThreads; i++)
|
for (int i = 0; i < activeThreads; i++)
|
||||||
threads[i].do_sleep = true;
|
threads[i]->do_sleep = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -210,34 +250,10 @@ void ThreadsManager::sleep() {
|
||||||
|
|
||||||
void ThreadsManager::init() {
|
void ThreadsManager::init() {
|
||||||
|
|
||||||
read_uci_options();
|
|
||||||
|
|
||||||
cond_init(sleepCond);
|
cond_init(sleepCond);
|
||||||
lock_init(splitLock);
|
lock_init(splitLock);
|
||||||
|
timer = new Thread(MAX_THREADS);
|
||||||
// Allocate main thread tables to call evaluate() also when not searching
|
read_uci_options(); // Creates at least main thread
|
||||||
threads[0].pawnTable.init();
|
|
||||||
threads[0].materialTable.init();
|
|
||||||
|
|
||||||
// Create and launch all the threads, threads will go immediately to sleep
|
|
||||||
for (int i = 0; i <= MAX_THREADS; i++)
|
|
||||||
{
|
|
||||||
threads[i].is_searching = false;
|
|
||||||
threads[i].do_sleep = (i != 0); // Avoid a race with start_thinking()
|
|
||||||
threads[i].threadID = i;
|
|
||||||
|
|
||||||
lock_init(threads[i].sleepLock);
|
|
||||||
cond_init(threads[i].sleepCond);
|
|
||||||
|
|
||||||
for (int j = 0; j < MAX_SPLITPOINTS_PER_THREAD; j++)
|
|
||||||
lock_init(threads[i].splitPoints[j].lock);
|
|
||||||
|
|
||||||
if (!thread_create(threads[i].handle, start_routine, threads[i]))
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to create thread number " << i << std::endl;
|
|
||||||
::exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -245,22 +261,11 @@ void ThreadsManager::init() {
|
||||||
|
|
||||||
void ThreadsManager::exit() {
|
void ThreadsManager::exit() {
|
||||||
|
|
||||||
for (int i = 0; i <= MAX_THREADS; i++)
|
for (int i = 0; i < MAX_THREADS; i++)
|
||||||
{
|
if (threads[i])
|
||||||
assert(threads[i].do_sleep);
|
delete threads[i];
|
||||||
|
|
||||||
threads[i].do_exit = true; // Search must be already finished
|
|
||||||
threads[i].wake_up();
|
|
||||||
|
|
||||||
thread_join(threads[i].handle); // Wait for thread termination
|
|
||||||
|
|
||||||
lock_destroy(threads[i].sleepLock);
|
|
||||||
cond_destroy(threads[i].sleepCond);
|
|
||||||
|
|
||||||
for (int j = 0; j < MAX_SPLITPOINTS_PER_THREAD; j++)
|
|
||||||
lock_destroy(threads[i].splitPoints[j].lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
delete timer;
|
||||||
lock_destroy(splitLock);
|
lock_destroy(splitLock);
|
||||||
cond_destroy(sleepCond);
|
cond_destroy(sleepCond);
|
||||||
}
|
}
|
||||||
|
@ -274,7 +279,7 @@ bool ThreadsManager::available_slave_exists(int master) const {
|
||||||
assert(master >= 0 && master < activeThreads);
|
assert(master >= 0 && master < activeThreads);
|
||||||
|
|
||||||
for (int i = 0; i < activeThreads; i++)
|
for (int i = 0; i < activeThreads; i++)
|
||||||
if (threads[i].is_available_to(master))
|
if (threads[i]->is_available_to(master))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -304,7 +309,7 @@ Value ThreadsManager::split(Position& pos, Stack* ss, Value alpha, Value beta,
|
||||||
assert(activeThreads > 1);
|
assert(activeThreads > 1);
|
||||||
|
|
||||||
int master = pos.thread();
|
int master = pos.thread();
|
||||||
Thread& masterThread = threads[master];
|
Thread& masterThread = *threads[master];
|
||||||
|
|
||||||
if (masterThread.splitPointsCnt >= MAX_SPLITPOINTS_PER_THREAD)
|
if (masterThread.splitPointsCnt >= MAX_SPLITPOINTS_PER_THREAD)
|
||||||
return bestValue;
|
return bestValue;
|
||||||
|
@ -341,14 +346,14 @@ Value ThreadsManager::split(Position& pos, Stack* ss, Value alpha, Value beta,
|
||||||
lock_grab(splitLock);
|
lock_grab(splitLock);
|
||||||
|
|
||||||
for (int i = 0; i < activeThreads && !Fake; i++)
|
for (int i = 0; i < activeThreads && !Fake; i++)
|
||||||
if (threads[i].is_available_to(master))
|
if (threads[i]->is_available_to(master))
|
||||||
{
|
{
|
||||||
sp->slavesMask |= 1ULL << i;
|
sp->slavesMask |= 1ULL << i;
|
||||||
threads[i].curSplitPoint = sp;
|
threads[i]->curSplitPoint = sp;
|
||||||
threads[i].is_searching = true; // Slave leaves idle_loop()
|
threads[i]->is_searching = true; // Slave leaves idle_loop()
|
||||||
|
|
||||||
if (useSleepingThreads)
|
if (useSleepingThreads)
|
||||||
threads[i].wake_up();
|
threads[i]->wake_up();
|
||||||
|
|
||||||
if (++slavesCnt + 1 >= maxThreadsPerSplitPoint) // Master is always included
|
if (++slavesCnt + 1 >= maxThreadsPerSplitPoint) // Master is always included
|
||||||
break;
|
break;
|
||||||
|
@ -399,12 +404,10 @@ template Value ThreadsManager::split<true>(Position&, Stack*, Value, Value, Valu
|
||||||
|
|
||||||
void ThreadsManager::set_timer(int msec) {
|
void ThreadsManager::set_timer(int msec) {
|
||||||
|
|
||||||
Thread& timer = threads[MAX_THREADS];
|
lock_grab(timer->sleepLock);
|
||||||
|
timer->maxPly = msec;
|
||||||
lock_grab(timer.sleepLock);
|
cond_signal(timer->sleepCond); // Wake up and restart the timer
|
||||||
timer.maxPly = msec;
|
lock_release(timer->sleepLock);
|
||||||
cond_signal(timer.sleepCond); // Wake up and restart the timer
|
|
||||||
lock_release(timer.sleepLock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -415,7 +418,7 @@ void ThreadsManager::set_timer(int msec) {
|
||||||
|
|
||||||
void ThreadsManager::start_thinking(const Position& pos, const LimitsType& limits,
|
void ThreadsManager::start_thinking(const Position& pos, const LimitsType& limits,
|
||||||
const std::set<Move>& searchMoves, bool async) {
|
const std::set<Move>& searchMoves, bool async) {
|
||||||
Thread& main = threads[0];
|
Thread& main = *threads[0];
|
||||||
|
|
||||||
lock_grab(main.sleepLock);
|
lock_grab(main.sleepLock);
|
||||||
|
|
||||||
|
@ -455,7 +458,7 @@ void ThreadsManager::start_thinking(const Position& pos, const LimitsType& limit
|
||||||
|
|
||||||
void ThreadsManager::stop_thinking() {
|
void ThreadsManager::stop_thinking() {
|
||||||
|
|
||||||
Thread& main = threads[0];
|
Thread& main = *threads[0];
|
||||||
|
|
||||||
Search::Signals.stop = true;
|
Search::Signals.stop = true;
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,9 @@ struct SplitPoint {
|
||||||
|
|
||||||
struct Thread {
|
struct Thread {
|
||||||
|
|
||||||
|
Thread(int id);
|
||||||
|
~Thread();
|
||||||
|
|
||||||
void wake_up();
|
void wake_up();
|
||||||
bool cutoff_occurred() const;
|
bool cutoff_occurred() const;
|
||||||
bool is_available_to(int master) const;
|
bool is_available_to(int master) const;
|
||||||
|
@ -100,7 +103,7 @@ class ThreadsManager {
|
||||||
static storage duration are automatically set to zero before enter main()
|
static storage duration are automatically set to zero before enter main()
|
||||||
*/
|
*/
|
||||||
public:
|
public:
|
||||||
Thread& operator[](int threadID) { return threads[threadID]; }
|
Thread& operator[](int threadID) { return *threads[threadID]; }
|
||||||
void init();
|
void init();
|
||||||
void exit();
|
void exit();
|
||||||
|
|
||||||
|
@ -123,7 +126,8 @@ public:
|
||||||
private:
|
private:
|
||||||
friend struct Thread;
|
friend struct Thread;
|
||||||
|
|
||||||
Thread threads[MAX_THREADS + 1]; // Last one is used as a timer
|
Thread* timer;
|
||||||
|
Thread* threads[MAX_THREADS];
|
||||||
Lock splitLock;
|
Lock splitLock;
|
||||||
WaitCondition sleepCond;
|
WaitCondition sleepCond;
|
||||||
Depth minimumSplitDepth;
|
Depth minimumSplitDepth;
|
||||||
|
|
5
src/tt.h
5
src/tt.h
|
@ -146,10 +146,7 @@ struct SimpleHash {
|
||||||
|
|
||||||
typedef SimpleHash<Entry, HashSize> Base;
|
typedef SimpleHash<Entry, HashSize> Base;
|
||||||
|
|
||||||
void init() {
|
SimpleHash() {
|
||||||
|
|
||||||
if (entries)
|
|
||||||
return;
|
|
||||||
|
|
||||||
entries = new (std::nothrow) Entry[HashSize];
|
entries = new (std::nothrow) Entry[HashSize];
|
||||||
if (!entries)
|
if (!entries)
|
||||||
|
|
Loading…
Add table
Reference in a new issue