1 /* 2 * Copyright (C) 2011 Gerd Lorscheid 3 * Copyright (C) 2011-2017 Fulvio Benini 4 * 5 * This file is part of Scid (Shane's Chess Information Database). 6 * 7 * Scid is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation. 10 * 11 * Scid is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with Scid. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 /** @file 21 * Defines the SortCache class, which sorts the games of an @e Index. 22 */ 23 24 #ifndef SORTCACHE_H 25 #define SORTCACHE_H 26 27 #include "common.h" 28 29 #ifndef MULTITHREADING_OFF 30 #include <atomic> 31 using std::atomic_bool; 32 #else 33 typedef bool atomic_bool; 34 #endif 35 36 class HFilter; 37 class Index; 38 class IndexEntry; 39 class NameBase; 40 41 /** 42 * This class sorts games contained into an Index. 43 * Multiple SortCache objects can be created for a single Index, allowing to 44 * simultaneously sort the games by multiple criteria in an independent way. 45 */ 46 class SortCache { 47 gamenumT nGames_; 48 atomic_bool valid_fullMap_; 49 atomic_bool th_interrupt_; 50 bool partialHash_; 51 gamenumT* fullMap_; 52 void* th_; 53 uint32_t* hash_; 54 const Index* index_; 55 const NameBase* nbase_; 56 char criteria_[32]; 57 int refCount_; 58 59 // Valid fields that can be used to sort the games. 60 enum { 61 SORTING_date = 'd', 62 SORTING_year = 'y', 63 SORTING_event = 'e', 64 SORTING_site = 's', 65 SORTING_round = 'n', 66 SORTING_white = 'w', 67 SORTING_black = 'b', 68 SORTING_eco = 'o', 69 SORTING_result = 'r', 70 SORTING_moveCount = 'm', 71 SORTING_avgElo = 'R', 72 SORTING_country = 'c', 73 SORTING_deleted = 'D', 74 SORTING_eventdate = 'E', 75 SORTING_whiteelo = 'W', 76 SORTING_blackelo = 'B', 77 SORTING_commentcount = 'C', 78 SORTING_varcount = 'V', 79 SORTING_nagcount = 'A', 80 SORTING_resultwin = '1', 81 SORTING_resultdraw = '5', 82 SORTING_resultloss = '0', 83 SORTING_rating = 'i', 84 SORTING_number = 'N', 85 SORTING_sentinel = '\0' 86 }; 87 88 public: 89 /** 90 * Create a new SortCache object, builds the hash table, and asynchronously 91 * sorts all the games. 92 * @param idx: valid pointer to an Index object, witch contains the 93 * header data of the games to be sorted. 94 * @param nb: valid pointer to the NameBase corresponding to @e idx. 95 * @param criteria: the list of fields by which games will be ordered. 96 * Each field should be followed by '+' to indicate an 97 * ascending order or by '-' for a descending order. 98 * @returns a pointer to the new object in case of success, NULL otherwise. 99 */ 100 static SortCache* create(const Index* idx, const NameBase* nb, 101 const char* criteria); 102 ~SortCache(); 103 104 /** 105 * Notify the object that a game's header data has changed. 106 * @param gameId: the id of the game whose data has been changed. 107 */ 108 void checkForChanges(gamenumT gameId); 109 110 /** 111 * Interrupt any asynchronous operation. This function must be called before 112 * modifying the Index or the NameBase associated with the SortCache. 113 */ prepareForChanges()114 void prepareForChanges() { th_interrupt(); } 115 116 /** 117 * Retrieve the sorted list of games' ids. 118 * The behavior of this function is similar to the mySQL statement: 119 * SELECT gameId FROM idx WHERE filter(gameId) != 0 ORDER BY criteria 120 * LIMIT offset, row_count 121 * @param row_offset: the offset of the first row to return. 122 * The offset of the initial row is 0. 123 * @param row_count: maximum number of rows to return. 124 * @param filter: a reference to a valid (!= NULL) HFilter object. 125 * Games not included into the filter will be ignored. 126 * @param[out] result: valid pointer to an array where the sorted list of 127 * games will be stored (should be able to contain at 128 * least @e row_count elements). 129 * @returns the number of games' ids stored into @e result. 130 */ 131 size_t select(size_t row_offset, size_t row_count, const HFilter& filter, 132 gamenumT* result) const; 133 134 /** 135 * Get the sorted position of a game. 136 * @param gameId: the id of the game. 137 * @param filter: a reference to a valid (!= NULL) HFilter object. 138 * Games not included into the filter will be ignored, 139 * and @e gameId must be included into the filter. 140 * @returns the sorted position of @e gameId. 141 */ 142 size_t sortedPosition(gamenumT gameId, const HFilter& filter) const; 143 incrRef(int incr)144 int incrRef(int incr) { return refCount_ += incr; } 145 146 private: 147 SortCache(const Index* idx, const NameBase* nbase); 148 SortCache(const SortCache&); 149 150 class CmpLess { 151 const SortCache* sc_; 152 public: CmpLess(const SortCache * sc)153 CmpLess(const SortCache* sc) : sc_(sc) {} 154 bool operator()(gamenumT g1, gamenumT g2) const; 155 }; 156 int fullCompare(gamenumT left, gamenumT right) const; 157 158 uint32_t calcHash(gamenumT gameId); 159 void generateHashCache(); 160 void sortAsynchronously(); 161 th_interrupt()162 void th_interrupt() { 163 th_interrupt_ = true; 164 th_join(); 165 th_interrupt_ = false; 166 } 167 void th_join(); 168 void th_sort(); 169 }; 170 171 #endif 172