The Battle for Wesnoth  1.17.0-dev
config_cache.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2021
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * this file implements game config caching
17  * to speed up startup
18  ***/
19 
20 #pragma once
21 
22 #include <cassert>
23 #include <list>
24 #include <memory>
25 
27 
28 class config;
29 class abstract_validator;
30 
31 namespace game_config
32 {
33 
34 /**
35  * Used to set and unset scoped defines to preproc_map
36  *
37  * This is preferred form to set defines that aren't global
38  **/
39 template<typename T>
41 {
42 public:
45 
46  /**
47  * Adds normal preproc define.
48  *
49  * @param name name of preproc define to add.
50  * @param add true if we should add this.
51  */
52  scoped_preproc_define_internal(const std::string& name, bool add = true) : name_(name), add_(add)
53  {
54  if(add_) {
55  T::instance().add_define(name_);
56  }
57  }
58 
59  /**
60  * This removes preproc define from cacher
61  */
63  {
64  if(add_) {
65  T::instance().remove_define(name_);
66  }
67  }
68 
69 protected:
70  //
71  // Protected to let test code access
72  //
73 
74  std::string name_;
75  bool add_;
76 
77 };
78 
80 
82 
83 /**
84  * Singleton class to manage game config file caching.
85  * It uses paths to config files as key to find correct cache
86  * @todo Make smarter filetree checksum caching so only required parts
87  * of tree are checked at startup. Trees are overlapping so have
88  * to split trees to subtrees to only do check once per file.
89  * @todo Make cache system easily allow validation of in memory cache objects
90  * using hash checksum of preproc_map.
91  **/
93 {
94 public:
95  /**
96  * Get reference to the singleton object
97  */
98  static config_cache& instance();
99 
100  config_cache(const config_cache&) = delete;
101  config_cache& operator=(const config_cache&) = delete;
102 
103  const preproc_map& get_preproc_map() const;
104 
105  /**
106  * Gets a config object from given @a path.
107  * @param path file to load. Should be _main.cfg.
108  * @param cfg config object that is written to. Should be empty on entry.
109  * @param validator the WML schema validator, if provided.
110  */
111  void get_config(const std::string& path, config& cfg, abstract_validator* validator = nullptr);
112 
113  /**
114  * Clear stored defines map to default values
115  */
116  void clear_defines();
117 
118  /**
119  * Add a entry to preproc defines map
120  */
121  void add_define(const std::string& define);
122 
123  /**
124  * Remove a entry to preproc defines map
125  */
126  void remove_define(const std::string& define);
127 
128  /**
129  * Enable/disable caching
130  */
131  void set_use_cache(bool use);
132 
133  /**
134  * Enable/disable cache validation
135  */
136  void set_force_valid_cache(bool force);
137 
138  /**
139  * Force cache checksum validation.
140  */
141  void recheck_filetree_checksum();
142 
143  /**
144  * Deletes stale cache files not in use by the game.
145  */
146  bool clean_cache();
147 
148  /**
149  * Deletes all cache files.
150  */
151  bool purge_cache();
152 
153 private:
157 
159 
160  std::string cache_file_prefix_;
161 
162  void read_file(const std::string& file, config& cfg);
163  void write_file(std::string file, const config& cfg);
164  void write_file(std::string file, const preproc_map& defines);
165 
166  void read_cache(const std::string& path, config& cfg, abstract_validator* validator = nullptr);
167 
168  void read_configs(const std::string& path, config& cfg, preproc_map& defines, abstract_validator* validator = nullptr);
169  void load_configs(const std::string& path, config& cfg, abstract_validator* validator = nullptr);
170  void read_defines_queue();
171  void read_defines_file(const std::string& path);
172 
173  preproc_map& make_copy_map();
174  void add_defines_map_diff(preproc_map&);
175 
176  bool delete_cache_files(const std::vector<std::string>& paths,
177  const std::string& exclude_pattern = "");
178 
179 protected:
180  //
181  // Protected to let test code access
182  //
183 
184  config_cache();
185 
186  void set_force_invalid_cache(bool);
187 };
188 
189 class fake_transaction;
190 
191 /**
192  * Used to share macros between cache objects
193  * You have to create transaction object to load all
194  * macros to memory and share them subsequent cache loads.
195  * If transaction is locked all stored macros are still
196  * available but new macros aren't added.
197  **/
199 {
200 public:
203 
206 
207  /**
208  * Lock the transaction so no more macros are added
209  */
210  void lock();
211 
212  /**
213  * Used to let std::for_each insert new defines to active_map
214  * map to active
215  */
216  void insert_to_active(const preproc_map::value_type& def);
217 
218  enum state
219  {
223  LOCKED
224  };
225 
226 private:
227  friend class config_cache;
228  friend class fake_transaction;
229 
230  static state state_;
232 
233  std::vector<std::string> define_filenames_;
235 
236  static state get_state()
237  {
238  return state_;
239  }
240 
241  static bool is_active()
242  {
243  return active_ != 0;
244  }
245 
247  {
248  assert(active_);
249  return *active_;
250  }
251 
252  const std::vector<std::string>& get_define_files() const;
253 
254  void add_define_file(const std::string& file);
255 
256  preproc_map& get_active_map(const preproc_map& defines_map);
257 
258  void add_defines_map_diff(preproc_map& defines_map);
259 };
260 
261 /**
262  * Holds a fake cache transaction if no real one is used
263  **/
265 {
266  fake_transaction(const fake_transaction&) = delete;
267  fake_transaction& operator=(const fake_transaction&) = delete;
268 
269  friend class config_cache;
270 
271  typedef std::unique_ptr<config_cache_transaction> value_type;
272  value_type trans_;
273 
274  fake_transaction() : trans_()
275  {
277  trans_.reset(new config_cache_transaction());
278  }
279  }
280 };
281 
282 }
static config_cache_transaction * active_
Holds a fake cache transaction if no real one is used.
std::vector< std::string > define_filenames_
static config_cache_transaction & instance()
scoped_preproc_define_internal(const scoped_preproc_define_internal &)=delete
Used to set and unset scoped defines to preproc_map.
Used in parsing config file.
Definition: validator.hpp:36
void write_file(const std::string &fname, const std::string &data)
Throws io_exception if an error occurs.
std::string path
Definition: game_config.cpp:38
std::string read_file(const std::string &fname)
Basic disk I/O - read file.
Definition: filesystem.cpp:997
Game configuration data as global variables.
Definition: build_info.cpp:58
scoped_preproc_define_internal< config_cache > scoped_preproc_define
scoped_preproc_define_internal & operator=(const scoped_preproc_define_internal &)=delete
std::unique_ptr< config_cache_transaction > value_type
Used to share macros between cache objects You have to create transaction object to load all macros t...
scoped_preproc_define_internal(const std::string &name, bool add=true)
Adds normal preproc define.
std::map< std::string, struct preproc_define > preproc_map
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:59
~scoped_preproc_define_internal()
This removes preproc define from cacher.
Singleton class to manage game config file caching.