/*1Stockfish, a UCI chess playing engine derived from Glaurung 2.12Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)34Stockfish is free software: you can redistribute it and/or modify5it under the terms of the GNU General Public License as published by6the Free Software Foundation, either version 3 of the License, or7(at your option) any later version.89Stockfish is distributed in the hope that it will be useful,10but WITHOUT ANY WARRANTY; without even the implied warranty of11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12GNU General Public License for more details.1314You should have received a copy of the GNU General Public License15along with this program. If not, see <http://www.gnu.org/licenses/>.16*/1718#ifndef TT_H_INCLUDED19#define TT_H_INCLUDED2021#include <cstddef>22#include <cstdint>23#include <tuple>2425#include "memory.h"26#include "types.h"2728namespace Stockfish {2930class ThreadPool;31struct TTEntry;32struct Cluster;3334// There is only one global hash table for the engine and all its threads. For chess in particular, we even allow racy35// updates between threads to and from the TT, as taking the time to synchronize access would cost thinking time and36// thus elo. As a hash table, collisions are possible and may cause chess playing issues (bizarre blunders, faulty mate37// reports, etc). Fixing these also loses elo; however such risk decreases quickly with larger TT size.38//39// `probe` is the primary method: given a board position, we lookup its entry in the table, and return a tuple of:40// 1) whether the entry already has this position41// 2) a copy of the prior data (if any) (may be inconsistent due to read races)42// 3) a writer object to this entry43// The copied data and the writer are separated to maintain clear boundaries between local vs global objects.444546// A copy of the data already in the entry (possibly collided). `probe` may be racy, resulting in inconsistent data.47struct TTData {48Move move;49Value value, eval;50Depth depth;51Bound bound;52bool is_pv;5354TTData() = delete;5556// clang-format off57TTData(Move m, Value v, Value ev, Depth d, Bound b, bool pv) :58move(m),59value(v),60eval(ev),61depth(d),62bound(b),63is_pv(pv) {};64// clang-format on65};666768// This is used to make racy writes to the global TT.69struct TTWriter {70public:71void write(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev, uint8_t generation8);7273private:74friend class TranspositionTable;75TTEntry* entry;76TTWriter(TTEntry* tte);77};787980class TranspositionTable {8182public:83~TranspositionTable() { aligned_large_pages_free(table); }8485void resize(size_t mbSize, ThreadPool& threads); // Set TT size86void clear(ThreadPool& threads); // Re-initialize memory, multithreaded87int hashfull(int maxAge = 0)88const; // Approximate what fraction of entries (permille) have been written to during this root search8990void91new_search(); // This must be called at the beginning of each root search to track entry aging92uint8_t generation() const; // The current age, used when writing new data to the TT93std::tuple<bool, TTData, TTWriter>94probe(const Key key) const; // The main method, whose retvals separate local vs global objects95TTEntry* first_entry(const Key key)96const; // This is the hash function; its only external use is memory prefetching.9798private:99friend struct TTEntry;100101size_t clusterCount;102Cluster* table = nullptr;103104uint8_t generation8 = 0; // Size must be not bigger than TTEntry::genBound8105};106107} // namespace Stockfish108109#endif // #ifndef TT_H_INCLUDED110111112