mirror of
https://github.com/sockspls/badfish
synced 2025-04-29 16:23:09 +00:00
Material: protect global map access with locks
STL library is not guaranteed to be thread safe, even for read-access. So because these global maps are accessed by all the threads we need to protect them. This fixes a random crash experienced during testing. Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
parent
b2b86cfd27
commit
bd3ec6af15
1 changed files with 46 additions and 12 deletions
|
@ -25,6 +25,7 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include "lock.h"
|
||||||
#include "material.h"
|
#include "material.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,6 +49,9 @@ namespace {
|
||||||
std::map<Key, EndgameEvaluationFunction*> EEFmap;
|
std::map<Key, EndgameEvaluationFunction*> EEFmap;
|
||||||
std::map<Key, ScalingInfo> ESFmap;
|
std::map<Key, ScalingInfo> ESFmap;
|
||||||
|
|
||||||
|
Lock EEFmapLock;
|
||||||
|
Lock ESFmapLock;
|
||||||
|
|
||||||
void add(Key k, EndgameEvaluationFunction* f) {
|
void add(Key k, EndgameEvaluationFunction* f) {
|
||||||
|
|
||||||
EEFmap.insert(std::pair<Key, EndgameEvaluationFunction*>(k, f));
|
EEFmap.insert(std::pair<Key, EndgameEvaluationFunction*>(k, f));
|
||||||
|
@ -59,6 +63,34 @@ namespace {
|
||||||
ESFmap.insert(std::pair<Key, ScalingInfo>(k, s));
|
ESFmap.insert(std::pair<Key, ScalingInfo>(k, s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// STL map are not guaranteed to be thread safe even
|
||||||
|
// for read-access so we need this two helpers to access them.
|
||||||
|
EndgameEvaluationFunction* getEEF(Key key) {
|
||||||
|
|
||||||
|
EndgameEvaluationFunction* f = NULL;
|
||||||
|
|
||||||
|
lock_grab(&EEFmapLock);
|
||||||
|
|
||||||
|
if (EEFmap.find(key) != EEFmap.end())
|
||||||
|
f = EEFmap[key];
|
||||||
|
|
||||||
|
lock_release(&EEFmapLock);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScalingInfo getESF(Key key) {
|
||||||
|
|
||||||
|
ScalingInfo si = {WHITE, NULL};
|
||||||
|
|
||||||
|
lock_grab(&ESFmapLock);
|
||||||
|
|
||||||
|
if (ESFmap.find(key) != ESFmap.end())
|
||||||
|
si = ESFmap[key];
|
||||||
|
|
||||||
|
lock_release(&ESFmapLock);
|
||||||
|
return si;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,6 +104,10 @@ namespace {
|
||||||
|
|
||||||
void MaterialInfo::init() {
|
void MaterialInfo::init() {
|
||||||
|
|
||||||
|
// Initialize std::map access locks
|
||||||
|
lock_init(&EEFmapLock, NULL);
|
||||||
|
lock_init(&ESFmapLock, NULL);
|
||||||
|
|
||||||
typedef Key ZM[2][8][16];
|
typedef Key ZM[2][8][16];
|
||||||
const ZM& z = Position::zobMaterial;
|
const ZM& z = Position::zobMaterial;
|
||||||
|
|
||||||
|
@ -157,16 +193,16 @@ MaterialInfo *MaterialInfoTable::get_material_info(const Position& pos) {
|
||||||
|
|
||||||
// If mi->key matches the position's material hash key, it means that we
|
// If mi->key matches the position's material hash key, it means that we
|
||||||
// have analysed this material configuration before, and we can simply
|
// have analysed this material configuration before, and we can simply
|
||||||
// return the information we found the last time instead of recomputing it:
|
// return the information we found the last time instead of recomputing it.
|
||||||
if(mi->key == key)
|
if (mi->key == key)
|
||||||
return mi;
|
return mi;
|
||||||
|
|
||||||
// Clear the MaterialInfo object, and set its key:
|
// Clear the MaterialInfo object, and set its key
|
||||||
mi->clear();
|
mi->clear();
|
||||||
mi->key = key;
|
mi->key = key;
|
||||||
|
|
||||||
// A special case before looking for a specialized evaluation function
|
// A special case before looking for a specialized evaluation function
|
||||||
// KNN vs K is a draw
|
// KNN vs K is a draw.
|
||||||
if (key == KNNKMaterialKey || key == KKNNMaterialKey)
|
if (key == KNNKMaterialKey || key == KKNNMaterialKey)
|
||||||
{
|
{
|
||||||
mi->factor[WHITE] = mi->factor[BLACK] = 0;
|
mi->factor[WHITE] = mi->factor[BLACK] = 0;
|
||||||
|
@ -174,12 +210,10 @@ MaterialInfo *MaterialInfoTable::get_material_info(const Position& pos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's look if we have a specialized evaluation function for this
|
// Let's look if we have a specialized evaluation function for this
|
||||||
// particular material configuration
|
// particular material configuration.
|
||||||
if (EEFmap.find(key) != EEFmap.end())
|
if ((mi->evaluationFunction = getEEF(key)) != NULL)
|
||||||
{
|
|
||||||
mi->evaluationFunction = EEFmap[key];
|
|
||||||
return mi;
|
return mi;
|
||||||
}
|
|
||||||
else if ( pos.non_pawn_material(BLACK) == Value(0)
|
else if ( pos.non_pawn_material(BLACK) == Value(0)
|
||||||
&& pos.piece_count(BLACK, PAWN) == 0
|
&& pos.piece_count(BLACK, PAWN) == 0
|
||||||
&& pos.non_pawn_material(WHITE) >= RookValueEndgame)
|
&& pos.non_pawn_material(WHITE) >= RookValueEndgame)
|
||||||
|
@ -202,10 +236,10 @@ MaterialInfo *MaterialInfoTable::get_material_info(const Position& pos) {
|
||||||
// if we decide to add more special cases. We face problems when there
|
// if we decide to add more special cases. We face problems when there
|
||||||
// are several conflicting applicable scaling functions and we need to
|
// are several conflicting applicable scaling functions and we need to
|
||||||
// decide which one to use.
|
// decide which one to use.
|
||||||
|
ScalingInfo si = getESF(key);
|
||||||
if (ESFmap.find(key) != ESFmap.end())
|
if (si.fun != NULL)
|
||||||
{
|
{
|
||||||
mi->scalingFunction[ESFmap[key].col] = ESFmap[key].fun;
|
mi->scalingFunction[si.col] = si.fun;
|
||||||
return mi;
|
return mi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue