for (size_t i = 0; i < fens.size(); i++)
{
- Position pos(fens[i], false);
+ Position pos(fens[i], false, NULL);
cerr << "\nPosition: " << i + 1 << '/' << fens.size() << endl;
string fen = sides[0] + char('0' + int(8 - code.length()))
+ sides[1] + "/8/8/8/8/8/8/8 w - - 0 10";
- return Position(fen, false).material_key();
+ return Position(fen, false, NULL).material_key();
}
template<typename M>
margins[WHITE] = margins[BLACK] = VALUE_ZERO;
// Probe the material hash table
- ei.mi = this_thread->materialTable.probe(pos);
+ ei.mi = pos.this_thread()->materialTable.probe(pos);
score += ei.mi->material_value();
// If we have a specialized evaluation function for the current material
}
// Probe the pawn hash table
- ei.pi = this_thread->pawnTable.probe(pos);
+ ei.pi = pos.this_thread()->pawnTable.probe(pos);
score += ei.pi->pawns_value();
// Initialize attack and king safety bitboards
}
-/// Position::operator=() creates a copy of 'pos'. We want the new born Position
+/// Position::copy() creates a copy of 'pos'. We want the new born Position
/// object do not depend on any external data so we detach state pointer from
/// the source one.
-Position& Position::operator=(const Position& pos) {
+void Position::copy(const Position& pos, Thread* th) {
memcpy(this, &pos, sizeof(Position));
startState = *st;
st = &startState;
+ thisThread = th;
nodes = 0;
- return *this;
+
+ assert(pos_is_ok());
}
/// string. This function is not very robust - make sure that input FENs are
/// correct (this is assumed to be the responsibility of the GUI).
-void Position::from_fen(const string& fenStr, bool isChess960) {
+void Position::from_fen(const string& fenStr, bool isChess960, Thread* th) {
/*
A FEN string defines a particular position using only the ASCII character set.
st->npMaterial[BLACK] = compute_non_pawn_material(BLACK);
st->checkersBB = attackers_to(king_square(sideToMove)) & pieces(~sideToMove);
chess960 = isChess960;
+ thisThread = th;
assert(pos_is_ok());
}
if (move)
{
- Position p(*this);
+ Position p(*this, thisThread);
cout << "\nMove is: " << (sideToMove == BLACK ? ".." : "") << move_to_san(p, move);
}
}
// Prefetch pawn and material hash tables
- prefetch((char*)this_thread->pawnTable.entries[st->pawnKey]);
- prefetch((char*)this_thread->materialTable.entries[st->materialKey]);
+ prefetch((char*)thisThread->pawnTable.entries[st->pawnKey]);
+ prefetch((char*)thisThread->materialTable.entries[st->materialKey]);
// Update incremental scores
st->psqScore += psq_delta(piece, from, to);
void Position::flip() {
// Make a copy of current position before to start changing
- const Position pos(*this);
+ const Position pos(*this, thisThread);
clear();
+ thisThread = pos.this_thread();
// Board
for (Square s = SQ_A1; s <= SQ_H8; s++)
/// * A counter for detecting 50 move rule draws.
class Position {
+
+ // No copy c'tor or assignment operator allowed
+ Position(const Position&);
+ Position& operator=(const Position&);
+
public:
Position() {}
- Position(const Position& p) { *this = p; }
- Position(const std::string& f, bool c960) { from_fen(f, c960); }
- Position& operator=(const Position&);
+ Position(const Position& p, Thread* t) { copy(p, t); }
+ Position(const std::string& f, bool c960, Thread* t) { from_fen(f, c960, t); }
// Text input/output
- void from_fen(const std::string& fen, bool isChess960);
+ void copy(const Position& pos, Thread* th);
+ void from_fen(const std::string& fen, bool isChess960, Thread* th);
const std::string to_fen() const;
void print(Move m = MOVE_NONE) const;
Color side_to_move() const;
int startpos_ply_counter() const;
bool is_chess960() const;
+ Thread* this_thread() const;
int64_t nodes_searched() const;
void set_nodes_searched(int64_t n);
template<bool SkipRepetition> bool is_draw() const;
int64_t nodes;
int startPosPly;
Color sideToMove;
+ Thread* thisThread;
StateInfo* st;
int chess960;
return st->capturedType;
}
+inline Thread* Position::this_thread() const {
+ return thisThread;
+}
+
#endif // !defined(POSITION_H_INCLUDED)
// but if we are pondering or in infinite search, we shouldn't print the best
// move before we are told to do so.
if (!Signals.stop && (Limits.ponder || Limits.infinite))
- this_thread->wait_for_stop_or_ponderhit();
+ pos.this_thread()->wait_for_stop_or_ponderhit();
// Best move could be MOVE_NONE when searching on a stalemate position
cout << "bestmove " << move_to_uci(RootMoves[0].pv[0], Chess960)
bool isPvMove, inCheck, singularExtensionNode, givesCheck;
bool captureOrPromotion, dangerous, doFullDepthSearch;
int moveCount = 0, playedMoveCount = 0;
- Thread* thisThread = this_thread;
+ Thread* thisThread = pos.this_thread();
SplitPoint* sp = NULL;
refinedValue = bestValue = value = -VALUE_INFINITE;
lock_release(Threads.splitLock);
Stack ss[MAX_PLY_PLUS_2];
- Position pos(*sp->pos);
+ Position pos(*sp->pos, this);
memcpy(ss, sp->ss - 1, 4 * sizeof(Stack));
(ss+1)->sp = sp;
using namespace Search;
ThreadsManager Threads; // Global object
-THREAD_LOCAL Thread* this_thread; // Thread local variable
namespace { extern "C" {
// start_routine() is the C function which is called when a new thread
// is launched. It is a wrapper to member function pointed by start_fn.
- long start_routine(Thread* th) {
-
- this_thread = th; // Save pointer into thread local storage
- (th->*(th->start_fn))();
- return 0;
- }
+ long start_routine(Thread* th) { (th->*(th->start_fn))(); return 0; }
} }
+
// Thread c'tor starts a newly-created thread of execution that will call
// the idle loop function pointed by start_fn going immediately to sleep.
lock_init(splitLock);
timer = new Thread(&Thread::timer_loop);
threads.push_back(new Thread(&Thread::main_loop));
- this_thread = main_thread(); // Use main thread's resources
read_uci_options();
}
assert(beta <= VALUE_INFINITE);
assert(depth > DEPTH_ZERO);
- Thread* master = this_thread;
+ Thread* master = pos.this_thread();
if (master->splitPointsCnt >= MAX_SPLITPOINTS_PER_THREAD)
return bestValue;
Signals.stopOnPonderhit = Signals.firstRootMove = false;
Signals.stop = Signals.failedLowAtRoot = false;
- RootPosition = pos;
+ RootPosition.copy(pos, main_thread());
Limits = limits;
RootMoves.clear();
bool use_sleeping_threads() const { return useSleepingThreads; }
int min_split_depth() const { return minimumSplitDepth; }
int size() const { return (int)threads.size(); }
- Thread* main_thread() const { return threads[0]; }
+ Thread* main_thread() { return threads[0]; }
void wake_up() const;
void sleep() const;
};
extern ThreadsManager Threads;
-extern THREAD_LOCAL Thread* this_thread;
#endif // !defined(THREAD_H_INCLUDED)
# define FORCE_INLINE inline
#endif
-#if defined(__GNUC__)
-# define THREAD_LOCAL __thread
-#else
-# define THREAD_LOCAL __declspec(thread)
-#endif
-
#if defined(USE_POPCNT)
const bool HasPopCnt = true;
#else
void uci_loop(const string& args) {
- Position pos(StartFEN, false); // The root position
+ Position pos(StartFEN, false, Threads.main_thread()); // The root position
string cmd, token;
while (token != "quit")
else
return;
- pos.from_fen(fen, Options["UCI_Chess960"]);
+ pos.from_fen(fen, Options["UCI_Chess960"], Threads.main_thread());
// Parse move list (if any)
while (is >> token && (m = move_from_uci(pos, token)) != MOVE_NONE)