summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
8991a6f)
Before the search we setup the starting position doing all the
moves (sent by GUI) from start position to the position just
before to start searching.
To do this we use a set of StateInfo records used by each
do_move() call. These records shall be kept valid during all
the search because repetition draw detection uses them to back
track all the earlier positions keys. The problem is that, while
searching, the GUI could send another 'position' command, this
calls set_position() that clears the states! Of course a crash
follows shortly.
Before searching all the relevant parameters are copied in
start_searching() just for this reason: to fully detach data
accessed during the search from the UCI protocol handling.
So the natural solution would be to copy also the setup states.
Unfortunatly this approach does not work because StateInfo
contains a pointer to the previous record, so naively copying and
then freeing the original memory leads to a crash.
That's why we use two std::auto_ptr (one belonging to UCI and another
to Search) to safely transfer ownership of the StateInfo records to
the search, after we have setup the root position.
As a nice side-effect all the possible memory leaks are magically
sorted out for us by std::auto_ptr semantic.
No functional change.
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
+ Search::StateStackPtr st;
Time time = Time::current_time();
for (size_t i = 0; i < fens.size(); i++)
Time time = Time::current_time();
for (size_t i = 0; i < fens.size(); i++)
- Threads.start_searching(pos, limits, vector<Move>());
+ Threads.start_searching(pos, limits, vector<Move>(), st);
Threads.wait_for_search_finished();
nodes += Search::RootPosition.nodes_searched();
}
Threads.wait_for_search_finished();
nodes += Search::RootPosition.nodes_searched();
}
std::vector<RootMove> RootMoves;
Position RootPosition;
Time SearchTime;
std::vector<RootMove> RootMoves;
Position RootPosition;
Time SearchTime;
+ StateStackPtr SetupStates;
#define SEARCH_H_INCLUDED
#include <cstring>
#define SEARCH_H_INCLUDED
#include <cstring>
+#include <memory>
+#include <stack>
#include <vector>
#include "misc.h"
#include <vector>
#include "misc.h"
struct SplitPoint;
namespace Search {
struct SplitPoint;
namespace Search {
bool stopOnPonderhit, firstRootMove, stop, failedLowAtRoot;
};
bool stopOnPonderhit, firstRootMove, stop, failedLowAtRoot;
};
+typedef std::auto_ptr<std::stack<StateInfo> > StateStackPtr;
+
extern volatile SignalsType Signals;
extern LimitsType Limits;
extern std::vector<RootMove> RootMoves;
extern Position RootPosition;
extern Time SearchTime;
extern volatile SignalsType Signals;
extern LimitsType Limits;
extern std::vector<RootMove> RootMoves;
extern Position RootPosition;
extern Time SearchTime;
+extern StateStackPtr SetupStates;
extern void init();
extern size_t perft(Position& pos, Depth depth);
extern void init();
extern size_t perft(Position& pos, Depth depth);
// a new search, then returns immediately.
void ThreadPool::start_searching(const Position& pos, const LimitsType& limits,
// a new search, then returns immediately.
void ThreadPool::start_searching(const Position& pos, const LimitsType& limits,
- const std::vector<Move>& searchMoves) {
+ const std::vector<Move>& searchMoves, StateStackPtr& states) {
wait_for_search_finished();
SearchTime.restart(); // As early as possible
wait_for_search_finished();
SearchTime.restart(); // As early as possible
RootPosition = pos;
Limits = limits;
RootPosition = pos;
Limits = limits;
+ SetupStates = states; // Ownership transfer here
RootMoves.clear();
for (MoveList<LEGAL> ml(pos); !ml.end(); ++ml)
RootMoves.clear();
for (MoveList<LEGAL> ml(pos); !ml.end(); ++ml)
bool available_slave_exists(Thread* master) const;
void set_timer(int msec);
void wait_for_search_finished();
bool available_slave_exists(Thread* master) const;
void set_timer(int msec);
void wait_for_search_finished();
- void start_searching(const Position& pos, const Search::LimitsType& limits,
- const std::vector<Move>& searchMoves);
+ void start_searching(const Position&, const Search::LimitsType&,
+ const std::vector<Move>&, Search::StateStackPtr&);
template <bool Fake>
Value split(Position& pos, Search::Stack* ss, Value alpha, Value beta, Value bestValue, Move* bestMove,
template <bool Fake>
Value split(Position& pos, Search::Stack* ss, Value alpha, Value beta, Value bestValue, Move* bestMove,
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <sstream>
#include <string>
#include <iostream>
#include <sstream>
#include <string>
// FEN string of the initial position, normal chess
const char* StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
// FEN string of the initial position, normal chess
const char* StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
+ // Keep track of position keys along the setup moves (from start position to the
+ // position just before to start searching). Needed by repetition draw detection.
+ Search::StateStackPtr SetupStates;
+
void set_option(istringstream& up);
void set_position(Position& pos, istringstream& up);
void go(Position& pos, istringstream& up);
void set_option(istringstream& up);
void set_position(Position& pos, istringstream& up);
void go(Position& pos, istringstream& up);
void set_position(Position& pos, istringstream& is) {
void set_position(Position& pos, istringstream& is) {
- // Keep track of position keys along the setup moves (from start position to the
- // position just before to start searching). Needed by repetition draw detection.
- static std::deque<StateInfo> st;
-
Move m;
string token, fen;
Move m;
string token, fen;
return;
pos.from_fen(fen, Options["UCI_Chess960"], Threads.main_thread());
return;
pos.from_fen(fen, Options["UCI_Chess960"], Threads.main_thread());
+ SetupStates = Search::StateStackPtr(new std::stack<StateInfo>());
// Parse move list (if any)
while (is >> token && (m = move_from_uci(pos, token)) != MOVE_NONE)
{
// Parse move list (if any)
while (is >> token && (m = move_from_uci(pos, token)) != MOVE_NONE)
{
- st.push_back(StateInfo());
- pos.do_move(m, st.back());
+ SetupStates->push(StateInfo());
+ pos.do_move(m, SetupStates->top());
searchMoves.push_back(move_from_uci(pos, token));
}
searchMoves.push_back(move_from_uci(pos, token));
}
- Threads.start_searching(pos, limits, searchMoves);
+ Threads.start_searching(pos, limits, searchMoves, SetupStates);