# newgrf_storage.h

Go to the documentation of this file.

    00001 /* $Id: newgrf_storage.h 26371 2014-02-23 22:03:08Z frosch $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * 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.
    00006  * 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.
    00007  * 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/>.
    00008  */
    00009
    00012 #ifndef NEWGRF_STORAGE_H
    00013 #define NEWGRF_STORAGE_H
    00014
    00015 #include "core/pool_type.hpp"
    00016 #include "tile_type.h"
    00017
    00021 enum PersistentStorageMode {
    00022   PSM_ENTER_GAMELOOP,
    00023   PSM_LEAVE_GAMELOOP,
    00024   PSM_ENTER_COMMAND,
    00025   PSM_LEAVE_COMMAND,
    00026   PSM_ENTER_TESTMODE,
    00027   PSM_LEAVE_TESTMODE,
    00028 };
    00029
    00034 struct BasePersistentStorageArray {
    00035   uint32 grfid;
    00036   byte feature;
    00037   TileIndex tile;
    00038
    00039   virtual ~BasePersistentStorageArray();
    00040
    00041   static void SwitchMode(PersistentStorageMode mode, bool ignore_prev_mode = false);
    00042
    00043 protected:
    00047   virtual void ClearChanges() = 0;
    00048
    00053   static bool AreChangesPersistent() { return (gameloop || command) && !testmode; }
    00054
    00055 private:
    00056   static bool gameloop;
    00057   static bool command;
    00058   static bool testmode;
    00059 };
    00060
    00067 template <typename TYPE, uint SIZE>
    00068 struct PersistentStorageArray : BasePersistentStorageArray {
    00069   TYPE storage[SIZE];
    00070   TYPE *prev_storage;
    00071
    00073   PersistentStorageArray() : prev_storage(NULL)
    00074   {
    00075     memset(this->storage, 0, sizeof(this->storage));
    00076   }
    00077
    00079   ~PersistentStorageArray()
    00080   {
    00081     free(this->prev_storage);
    00082   }
    00083
    00085   void ResetToZero()
    00086   {
    00087     memset(this->storage, 0, sizeof(this->storage));
    00088   }
    00089
    00097   void StoreValue(uint pos, int32 value)
    00098   {
    00099     /* Out of the scope of the array */
    00100     if (pos >= SIZE) return;
    00101
    00102     /* The value hasn't changed, so we pretend nothing happened.
    00103      * Saves a few cycles and such and it's pretty easy to check. */
    00104     if (this->storage[pos] == value) return;
    00105
    00106     /* We do not have made a backup; lets do so */
    00107     if (AreChangesPersistent()) {
    00108       assert(this->prev_storage == NULL);
    00109     } else if (this->prev_storage == NULL) {
    00110       this->prev_storage = MallocT<TYPE>(SIZE);
    00111       memcpy(this->prev_storage, this->storage, sizeof(this->storage));
    00112
    00113       /* We only need to register ourselves when we made the backup
    00114        * as that is the only time something will have changed */
    00115       AddChangedPersistentStorage(this);
    00116     }
    00117
    00118     this->storage[pos] = value;
    00119   }
    00120
    00126   TYPE GetValue(uint pos) const
    00127   {
    00128     /* Out of the scope of the array */
    00129     if (pos >= SIZE) return 0;
    00130
    00131     return this->storage[pos];
    00132   }
    00133
    00134   void ClearChanges()
    00135   {
    00136     if (this->prev_storage != NULL) {
    00137       memcpy(this->storage, this->prev_storage, sizeof(this->storage));
    00138       free(this->prev_storage);
    00139       this->prev_storage = NULL;
    00140     }
    00141   }
    00142 };
    00143
    00144
    00151 template <typename TYPE, uint SIZE>
    00152 struct TemporaryStorageArray {
    00153   TYPE storage[SIZE];
    00154   uint16 init[SIZE];
    00155   uint16 init_key;
    00156
    00158   TemporaryStorageArray()
    00159   {
    00160     memset(this->storage, 0, sizeof(this->storage)); // not exactly needed, but makes code analysers happy
    00161     memset(this->init, 0, sizeof(this->init));
    00162     this->init_key = 1;
    00163   }
    00164
    00170   void StoreValue(uint pos, int32 value)
    00171   {
    00172     /* Out of the scope of the array */
    00173     if (pos >= SIZE) return;
    00174
    00175     this->storage[pos] = value;
    00176     this->init[pos] = this->init_key;
    00177   }
    00178
    00184   TYPE GetValue(uint pos) const
    00185   {
    00186     /* Out of the scope of the array */
    00187     if (pos >= SIZE) return 0;
    00188
    00189     if (this->init[pos] != this->init_key) {
    00190       /* Unassigned since last call to ClearChanges */
    00191       return 0;
    00192     }
    00193
    00194     return this->storage[pos];
    00195   }
    00196
    00197   void ClearChanges()
    00198   {
    00199     /* Increment init_key to invalidate all storage */
    00200     this->init_key++;
    00201     if (this->init_key == 0) {
    00202       /* When init_key wraps around, we need to reset everything */
    00203       memset(this->init, 0, sizeof(this->init));
    00204       this->init_key = 1;
    00205     }
    00206   }
    00207 };
    00208
    00209 void AddChangedPersistentStorage(BasePersistentStorageArray *storage);
    00210
    00211 typedef PersistentStorageArray<int32, 16> OldPersistentStorage;
    00212
    00213 typedef uint32 PersistentStorageID;
    00214
    00215 struct PersistentStorage;
    00216 typedef Pool<PersistentStorage, PersistentStorageID, 1, 0xFF000> PersistentStoragePool;
    00217
    00218 extern PersistentStoragePool _persistent_storage_pool;
    00219
    00223 struct PersistentStorage : PersistentStorageArray<int32, 16>, PersistentStoragePool::PoolItem<&_persistent_storage_pool> {
    00225   PersistentStorage(const uint32 new_grfid, byte feature, TileIndex tile)
    00226   {
    00227     this->grfid = new_grfid;
    00228     this->feature = feature;
    00229     this->tile = tile;
    00230   }
    00231 };
    00232
    00233 assert_compile(cpp_lengthof(OldPersistentStorage, storage) == cpp_lengthof(PersistentStorage, storage));
    00234
    00235 #define FOR_ALL_STORAGES_FROM(var, start) FOR_ALL_ITEMS_FROM(PersistentStorage, storage_index, var, start)
    00236 #define FOR_ALL_STORAGES(var) FOR_ALL_STORAGES_FROM(var, 0)
    00237
    00238 #endif /* NEWGRF_STORAGE_H */