OpenTTD
newgrf_storage.h
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #ifndef NEWGRF_STORAGE_H
11 #define NEWGRF_STORAGE_H
12 
13 #include "core/pool_type.hpp"
14 #include "tile_type.h"
15 
26 };
27 
33  uint32 grfid;
34  byte feature;
36 
38 
39  static void SwitchMode(PersistentStorageMode mode, bool ignore_prev_mode = false);
40 
41 protected:
45  virtual void ClearChanges() = 0;
46 
51  static bool AreChangesPersistent() { return (gameloop || command) && !testmode; }
52 
53 private:
54  static bool gameloop;
55  static bool command;
56  static bool testmode;
57 };
58 
65 template <typename TYPE, uint SIZE>
67  TYPE storage[SIZE];
68  TYPE *prev_storage;
69 
71  PersistentStorageArray() : prev_storage(nullptr)
72  {
73  memset(this->storage, 0, sizeof(this->storage));
74  }
75 
78  {
79  free(this->prev_storage);
80  }
81 
83  void ResetToZero()
84  {
85  memset(this->storage, 0, sizeof(this->storage));
86  }
87 
95  void StoreValue(uint pos, int32 value)
96  {
97  /* Out of the scope of the array */
98  if (pos >= SIZE) return;
99 
100  /* The value hasn't changed, so we pretend nothing happened.
101  * Saves a few cycles and such and it's pretty easy to check. */
102  if (this->storage[pos] == value) return;
103 
104  /* We do not have made a backup; lets do so */
105  if (AreChangesPersistent()) {
106  assert(this->prev_storage == nullptr);
107  } else if (this->prev_storage == nullptr) {
108  this->prev_storage = MallocT<TYPE>(SIZE);
109  memcpy(this->prev_storage, this->storage, sizeof(this->storage));
110 
111  /* We only need to register ourselves when we made the backup
112  * as that is the only time something will have changed */
114  }
115 
116  this->storage[pos] = value;
117  }
118 
124  TYPE GetValue(uint pos) const
125  {
126  /* Out of the scope of the array */
127  if (pos >= SIZE) return 0;
128 
129  return this->storage[pos];
130  }
131 
133  {
134  if (this->prev_storage != nullptr) {
135  memcpy(this->storage, this->prev_storage, sizeof(this->storage));
136  free(this->prev_storage);
137  this->prev_storage = nullptr;
138  }
139  }
140 };
141 
142 
149 template <typename TYPE, uint SIZE>
151  TYPE storage[SIZE];
152  uint16 init[SIZE];
153  uint16 init_key;
154 
157  {
158  memset(this->storage, 0, sizeof(this->storage)); // not exactly needed, but makes code analysers happy
159  memset(this->init, 0, sizeof(this->init));
160  this->init_key = 1;
161  }
162 
168  void StoreValue(uint pos, int32 value)
169  {
170  /* Out of the scope of the array */
171  if (pos >= SIZE) return;
172 
173  this->storage[pos] = value;
174  this->init[pos] = this->init_key;
175  }
176 
182  TYPE GetValue(uint pos) const
183  {
184  /* Out of the scope of the array */
185  if (pos >= SIZE) return 0;
186 
187  if (this->init[pos] != this->init_key) {
188  /* Unassigned since last call to ClearChanges */
189  return 0;
190  }
191 
192  return this->storage[pos];
193  }
194 
195  void ClearChanges()
196  {
197  /* Increment init_key to invalidate all storage */
198  this->init_key++;
199  if (this->init_key == 0) {
200  /* When init_key wraps around, we need to reset everything */
201  memset(this->init, 0, sizeof(this->init));
202  this->init_key = 1;
203  }
204  }
205 };
206 
208 
210 
211 typedef uint32 PersistentStorageID;
212 
213 struct PersistentStorage;
215 
216 extern PersistentStoragePool _persistent_storage_pool;
217 
221 struct PersistentStorage : PersistentStorageArray<int32, 256>, PersistentStoragePool::PoolItem<&_persistent_storage_pool> {
223  PersistentStorage(const uint32 new_grfid, byte feature, TileIndex tile)
224  {
225  this->grfid = new_grfid;
226  this->feature = feature;
227  this->tile = tile;
228  }
229 };
230 
231 assert_compile(cpp_lengthof(OldPersistentStorage, storage) <= cpp_lengthof(PersistentStorage, storage));
232 
233 #endif /* NEWGRF_STORAGE_H */
TileIndex tile
NOSAVE: Used to identify in the owner of the array in debug output.
TemporaryStorageArray()
Simply construct the array.
TYPE * prev_storage
Memory to store "old" states so we can revert them on the performance of test cases for commands etc...
Leave command test mode, revert to previous mode.
Enter command test mode, changes will be tempoary.
Class for temporary storage of data.
~PersistentStorageArray()
And free all data related to it.
byte feature
NOSAVE: Used to identify in the owner of the array in debug output.
Definition of Pool, structure used to access PoolItems, and PoolItem, base structure for Vehicle...
Class for persistent storage of data.
TYPE GetValue(uint pos) const
Gets the value from a given position.
void StoreValue(uint pos, int32 value)
Stores some value at a given position.
static void SwitchMode(PersistentStorageMode mode, bool ignore_prev_mode=false)
Clear temporary changes made since the last call to SwitchMode, and set whether subsequent changes sh...
PersistentStorageMode
Mode switches to the behaviour of persistent storage array.
Enter the gameloop, changes will be permanent.
uint32 grfid
GRFID associated to this persistent storage. A value of zero means "default".
PersistentStorage(const uint32 new_grfid, byte feature, TileIndex tile)
We don&#39;t want GCC to zero our struct! It already is zeroed and has an index!
virtual void ClearChanges()=0
Discard temporary changes.
void StoreValue(uint pos, int32 value)
Stores some value at a given position.
Class for pooled persistent storage of data.
void AddChangedPersistentStorage(BasePersistentStorageArray *storage)
Add the changed storage array to the list of changed arrays.
static bool AreChangesPersistent()
Check whether currently changes to the storage shall be persistent or temporary till the next call to...
Base class for all persistent NewGRF storage arrays.
Enter command scope, changes will be permanent.
Base class for all PoolItems.
Definition: pool_type.hpp:188
Leave command scope, revert to previous mode.
Base class for all pools.
Definition: pool_type.hpp:82
Leave the gameloop, changes will be temporary.
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:78
#define cpp_lengthof(base, variable)
Gets the length of an array variable within a class.
Definition: stdafx.h:413
void ClearChanges()
Discard temporary changes.
uint16 init_key
Magic key to &#39;init&#39;.
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:129
PersistentStorageArray()
Simply construct the array.
TYPE GetValue(uint pos) const
Gets the value from a given position.
void ResetToZero()
Resets all values to zero.
Types related to tiles.
virtual ~BasePersistentStorageArray()
Remove references to use.