00001 /* persist.h -- Persistent Object Management 00002 Copyright 2001 Free Software Foundation, Inc. 00003 Written by Stephane Carrez (stcarrez@worldnet.fr) 00004 00005 This file is part of GEL. 00006 00007 GEL is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 2, or (at your option) 00010 any later version. 00011 00012 GEL is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with GEL; see the file COPYING. If not, write to 00019 the Free Software Foundation, 59 Temple Place - Suite 330, 00020 Boston, MA 02111-1307, USA. */ 00021 00022 #ifndef _GEL_PERSIST_H 00023 #define _GEL_PERSIST_H 00024 00025 #include <sys/param.h> 00026 #include <stddef.h> 00027 #include <string.h> 00028 00029 #define PERSIST_INVALID_ID (persist_id_t) (0xffff) 00030 #define PERSIST_FREE_SLOT (persist_id_t) (0x7fff) 00031 00032 typedef unsigned short persist_id_t; 00033 00046 class persistent_store 00047 { 00048 protected: 00049 00051 // 00052 // The persistent area starts with a persistent store id and the size 00053 // of that store. The store id is used to retrieve the store when 00054 // we start. The size is used to be able to walk the persistent areas, 00055 // manage their allocation/deallocation. */ 00056 typedef struct 00057 { 00058 persist_id_t id; 00059 unsigned char size; 00060 unsigned char data[0]; 00061 } persistent_area_t; 00062 00064 // 00065 // Returns a pointer to the persistent area or NULL if not found. 00066 static persistent_area_t *find_store (persist_id_t id); 00067 00069 // 00070 // Returns a pointer to the persistent area allocated for the new store. 00071 static persistent_area_t *allocate_store (persist_id_t id, size_t len); 00072 00073 // Start in Eprom of the persistent memory. 00074 static persistent_area_t start_area asm ("0xb000"); 00075 00076 // End of the persistent memory. 00077 static persistent_area_t end_area asm ("0xb200"); 00078 00079 // The persistent area used by that store (saved copy). 00080 persistent_area_t *area; 00081 00083 // 00084 // If the runtime copy of the object is modified, update its 00085 // copy in persistent memory. 00086 void 00087 save (const unsigned char *object); 00088 00090 // 00091 // Retrieve the persistent store identified by `id', initialize 00092 // the runtime copy `object' with it. If the persistent storage 00093 // does not exist for that store, allocate one. 00094 // 00095 // Returns 1 when the persistent store was created, 0 otherwise. 00096 int 00097 create (persist_id_t id, void *object, size_t len); 00098 00099 inline 00100 persistent_store () 00101 {} 00102 00103 private: 00104 // Copy constructor is forbidden. 00105 inline 00106 persistent_store (const persistent_store&) 00107 { 00108 ; 00109 } 00110 00111 // Copy of persistent store objects is forbidden. 00112 inline persistent_store& 00113 operator = (const persistent_store&) 00114 { 00115 return *this; 00116 } 00117 00118 protected: 00120 inline 00121 persistent_store (persist_id_t id, void *object, size_t len) 00122 { 00123 create (id, object, len); 00124 } 00125 00126 public: 00128 // 00129 // The persistent store is freed and is no longer used to save 00130 // the object. 00131 void 00132 revoke (); 00133 }; 00134 00135 00140 class persistent_object : private persistent_store 00141 { 00142 protected: 00143 00144 // First persistent object in the list. 00145 static persistent_object *first; 00146 00147 // Next persistent object in the list. 00148 persistent_object *next; 00149 00150 // Pointer to the object in memory (runtime copy). 00151 unsigned char *object; 00152 00153 inline 00154 persistent_object () 00155 {} 00156 00157 private: 00158 // Copy constructor is forbidden. 00159 inline 00160 persistent_object (const persistent_object&) 00161 { 00162 ; 00163 } 00164 00165 // Copy of persistent object is forbidden. 00166 inline persistent_object& 00167 operator = (const persistent_object&) 00168 { 00169 return *this; 00170 } 00171 public: 00172 00174 inline 00175 persistent_object (persist_id_t id, void *object, size_t len) 00176 : persistent_store (id, object, len) 00177 { 00178 next = first; 00179 first = this; 00180 } 00181 00183 // 00184 // Persistent objects with external storage are not managed completely 00185 // by `persistent_object' class. We are not aware of when the object 00186 // is modified. For these objects, it is necessary to call `save_all' 00187 // to synchronize the runtime value with the persistent storage. 00188 // Only the bytes that have changed are updated. 00189 static void 00190 save_all (); 00191 }; 00192 00193 00194 00196 // 00197 // This class is suitable for a transparent persistent object. 00198 // When the object is modified, the persistent storage is also updated. 00199 // This is implemented by overriding the `=' operator and the `(type)' 00200 // type conversion. 00201 // 00202 template <class type> 00203 class persistent : private persistent_store 00204 { 00205 type obj; 00206 00208 inline void 00209 sync () 00210 { 00211 save ((const unsigned char*) &obj); 00212 } 00213 public: 00215 inline 00216 persistent (persist_id_t id) 00217 : persistent_store (id, &obj, sizeof (obj)) 00218 { 00219 } 00220 00222 // 00223 // If it's the first time the object is created, initialize it 00224 // with <b>init</b>. 00225 inline 00226 persistent (persist_id_t id, const type& init) 00227 : persistent_store () 00228 { 00229 if (create (id, &obj, sizeof (type))) 00230 { 00231 obj = init; 00232 sync (); 00233 } 00234 } 00235 00237 // 00238 // If it's the first time the object is created, initialize it 00239 // with <b>init</b>. 00240 inline 00241 persistent (persist_id_t id, type& init) 00242 : persistent_store () 00243 { 00244 if (create (id, &obj, sizeof (type))) 00245 { 00246 memcpy (&obj, &init, sizeof (type)); 00247 sync (); 00248 } 00249 } 00250 00252 // 00253 // The object can still be retrieve from persistent storage. 00254 inline 00255 ~persistent () 00256 { 00257 ; 00258 } 00259 00261 // 00262 // Modify the object and update its persistent storage. 00263 inline persistent<type>& 00264 operator = (const type& value) 00265 { 00266 memcpy (&obj, value, sizeof (value)); 00267 sync (); 00268 return *this; 00269 } 00270 00272 // 00273 // Modify the object and update its persistent storage. 00274 inline persistent<type>& 00275 operator = (type& value) 00276 { 00277 memcpy (&obj, &value, sizeof (value)); 00278 sync (); 00279 return *this; 00280 } 00281 00283 inline 00284 operator const type& () 00285 { 00286 return obj; 00287 } 00288 00289 inline persistent<type>& 00290 operator ++ (int) 00291 { 00292 obj++; 00293 sync (); 00294 return *this; 00295 } 00296 00297 inline persistent<type>& 00298 operator -- (int) 00299 { 00300 obj--; 00301 sync (); 00302 return *this; 00303 } 00304 }; 00305 00306 00307 #endif