mirror of
https://github.com/sockspls/badfish
synced 2025-04-30 16:53:09 +00:00
Make DTZEntry init() thread safe
This commit is contained in:
parent
5ebd56ebd8
commit
ff3165286c
1 changed files with 19 additions and 15 deletions
|
@ -128,7 +128,7 @@ struct PairsData {
|
||||||
uint8_t groupLen[TBPIECES]; // Number of pieces in a given group: KRKN -> (3) + (1)
|
uint8_t groupLen[TBPIECES]; // Number of pieces in a given group: KRKN -> (3) + (1)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper struct to avoid to manually define WDLEntry copy c'tor as we should
|
// Helper struct to avoid to manually define entry copy c'tor as we should
|
||||||
// because default one is not compatible with std::atomic_bool.
|
// because default one is not compatible with std::atomic_bool.
|
||||||
struct Atomic {
|
struct Atomic {
|
||||||
Atomic() = default;
|
Atomic() = default;
|
||||||
|
@ -161,7 +161,7 @@ struct WDLEntry : public Atomic {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DTZEntry {
|
struct DTZEntry : public Atomic {
|
||||||
DTZEntry(const WDLEntry& wdl);
|
DTZEntry(const WDLEntry& wdl);
|
||||||
~DTZEntry();
|
~DTZEntry();
|
||||||
|
|
||||||
|
@ -442,6 +442,8 @@ DTZEntry::DTZEntry(const WDLEntry& wdl) {
|
||||||
|
|
||||||
memset(this, 0, sizeof(DTZEntry));
|
memset(this, 0, sizeof(DTZEntry));
|
||||||
|
|
||||||
|
ready = false;
|
||||||
|
|
||||||
key = wdl.key;
|
key = wdl.key;
|
||||||
key2 = wdl.key2;
|
key2 = wdl.key2;
|
||||||
pieceCount = wdl.pieceCount;
|
pieceCount = wdl.pieceCount;
|
||||||
|
@ -1108,6 +1110,16 @@ bool init(Entry& e, const Position& pos)
|
||||||
const bool IsWDL = std::is_same<Entry, WDLEntry>::value;
|
const bool IsWDL = std::is_same<Entry, WDLEntry>::value;
|
||||||
const uint8_t* MAGIC = IsWDL ? WDL_MAGIC : DTZ_MAGIC;
|
const uint8_t* MAGIC = IsWDL ? WDL_MAGIC : DTZ_MAGIC;
|
||||||
|
|
||||||
|
// Avoid a thread reads 'ready' == true while another is still in do_init(),
|
||||||
|
// this could happen due to compiler reordering.
|
||||||
|
if (e.ready.load(std::memory_order_acquire))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
std::unique_lock<Mutex> lk(TB_mutex);
|
||||||
|
|
||||||
|
if (e.ready.load(std::memory_order_relaxed)) // Recheck under lock
|
||||||
|
return true;
|
||||||
|
|
||||||
std::string fname, w, b;
|
std::string fname, w, b;
|
||||||
|
|
||||||
// Position pieces in decreasing order for each color, like ("KPP","KR")
|
// Position pieces in decreasing order for each color, like ("KPP","KR")
|
||||||
|
@ -1124,6 +1136,7 @@ bool init(Entry& e, const Position& pos)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
e.hasPawns ? do_init(e, e.pawn, data) : do_init(e, e.piece, data);
|
e.hasPawns ? do_init(e, e.pawn, data) : do_init(e, e.piece, data);
|
||||||
|
e.ready.store(true, std::memory_order_release);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1140,20 +1153,11 @@ WDLScore probe_wdl_table(Position& pos, ProbeState* result) {
|
||||||
return WDLDraw;
|
return WDLDraw;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init table at first access attempt. Special care should be taken to avoid
|
// Init table at first access attempt, init() is thread safe
|
||||||
// one thread reads ready == 1 while the other is still in init(), this could
|
|
||||||
// happen due to compiler reordering.
|
|
||||||
if (!entry->ready.load(std::memory_order_acquire)) {
|
|
||||||
std::unique_lock<Mutex> lk(TB_mutex);
|
|
||||||
if (!entry->ready.load(std::memory_order_relaxed)) {
|
|
||||||
if (!init(*entry, pos)) {
|
if (!init(*entry, pos)) {
|
||||||
// Was ptr2->key = 0ULL; Just leave !ptr->ready condition
|
|
||||||
*result = FAIL;
|
*result = FAIL;
|
||||||
return WDLDraw;
|
return WDLDraw;
|
||||||
}
|
}
|
||||||
entry->ready.store(1, std::memory_order_release);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (WDLScore)probe_table(pos, entry);
|
return (WDLScore)probe_table(pos, entry);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue