1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-05-01 01:03:09 +00:00

Correctly handle shared 'ready' flag

Avoid ' double-checked locking' issue.
This commit is contained in:
Marco Costalba 2016-05-08 12:50:26 +02:00
parent 79051949ca
commit f68df60fe5

View file

@ -8,6 +8,7 @@
*/ */
#include <algorithm> #include <algorithm>
#include <atomic>
#include <cstdint> #include <cstdint>
#include <cstring> // For std::memset #include <cstring> // For std::memset
#include <deque> #include <deque>
@ -71,7 +72,15 @@ struct PairsData {
uint8_t norm[TBPIECES]; uint8_t norm[TBPIECES];
}; };
struct WDLEntry { // Helper struct to avoid manually define WDLEntry copy c'tor as we should
// because default one is not compatible with std::atomic_bool.
struct Atomic {
Atomic() = default;
Atomic(const Atomic& e) : ready(e.ready.load()) {}
std::atomic_bool ready;
};
struct WDLEntry : Atomic {
WDLEntry(const Position& pos, Key keys[]); WDLEntry(const Position& pos, Key keys[]);
~WDLEntry(); ~WDLEntry();
bool init(const std::string& fname); bool init(const std::string& fname);
@ -81,7 +90,6 @@ struct WDLEntry {
uint64_t mapping; uint64_t mapping;
Key key; Key key;
int pieceCount; int pieceCount;
bool ready;
bool symmetric; bool symmetric;
bool hasPawns; bool hasPawns;
union { union {
@ -1255,17 +1263,19 @@ WDLScore probe_wdl_table(Position& pos, int* success)
return WDLDraw; return WDLDraw;
} }
// Init table at first access attempt // Init table at first access attempt. Special care to avoid
if (!entry->ready) { // 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); std::unique_lock<Mutex> lk(TB_mutex);
if (!entry->ready) { if (!entry->ready.load(std::memory_order_relaxed)) {
std::string fname = file_name(pos, entry->key != key) + ".rtbw"; std::string fname = file_name(pos, entry->key != key) + ".rtbw";
if (!entry->init(fname)) { if (!entry->init(fname)) {
// Was ptr2->key = 0ULL; Just leave !ptr->ready condition // Was ptr2->key = 0ULL; Just leave !ptr->ready condition
*success = 0; *success = 0;
return WDLDraw; return WDLDraw;
} }
entry->ready = 1; entry->ready.store(1, std::memory_order_release);
} }
} }