Line data Source code
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 : */
114 0 : 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 :
144 14559 : int incrRef(int incr) { return refCount_ += incr; }
145 :
146 : private:
147 : SortCache(const Index* idx, const NameBase* nbase);
148 : SortCache(const SortCache&);
149 : SortCache& operator=(const SortCache&);
150 :
151 : class CmpLess {
152 : const SortCache* sc_;
153 : public:
154 364 : CmpLess(const SortCache* sc) : sc_(sc) {}
155 : bool operator()(gamenumT g1, gamenumT g2) const;
156 : };
157 : int fullCompare(gamenumT left, gamenumT right) const;
158 :
159 : uint32_t calcHash(gamenumT gameId);
160 : void generateHashCache();
161 : void sortAsynchronously();
162 :
163 15133 : void th_interrupt() {
164 15133 : th_interrupt_ = true;
165 15133 : th_join();
166 15133 : th_interrupt_ = false;
167 15133 : }
168 : void th_join();
169 : void th_sort();
170 : };
171 :
172 : #endif
|