persist.h

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 
00028 #define PERSIST_INVALID_ID (persist_id_t) (0xffff)
00029 #define PERSIST_FREE_SLOT  (persist_id_t) (0x7fff)
00030 
00031 typedef unsigned short persist_id_t;
00032 
00045 class persistent_store
00046 {
00047 protected:
00048 
00050   //
00051   // The persistent area starts with a persistent store id and the size
00052   // of that store.  The store id is used to retrieve the store when
00053   // we start.  The size is used to be able to walk the persistent areas,
00054   // manage their allocation/deallocation.  */
00055   typedef struct
00056   {
00057     persist_id_t id;
00058     unsigned char size;
00059     unsigned char data[0];
00060   } persistent_area_t;
00061 
00063   //
00064   // Returns a pointer to the persistent area or NULL if not found.
00065   static persistent_area_t *find_store (persist_id_t id);
00066 
00068   //
00069   // Returns a pointer to the persistent area allocated for the new store.
00070   static persistent_area_t *allocate_store (persist_id_t id, size_t len);
00071 
00072   // Start in Eprom of the persistent memory.
00073   static persistent_area_t start_area asm ("0xb000");
00074 
00075   // End of the persistent memory.
00076   static persistent_area_t end_area asm ("0xb200");
00077 
00078   // The persistent area used by that store (saved copy).
00079   persistent_area_t *area;
00080 
00082   //
00083   // If the runtime copy of the object is modified, update its
00084   // copy in persistent memory.
00085   void
00086   save (const unsigned char *object);
00087 
00089   //
00090   // Retrieve the persistent store identified by `id', initialize
00091   // the runtime copy `object' with it.  If the persistent storage
00092   // does not exist for that store, allocate one.
00093   //
00094   // Returns 1 when the persistent store was created, 0 otherwise.
00095   int
00096   create (persist_id_t id, void *object, size_t len);
00097 
00098   inline
00099   persistent_store ()
00100     {}
00101 
00102 private:
00103   // Copy constructor is forbidden.
00104   inline
00105   persistent_store (const persistent_store&)
00106     {
00107       ;
00108     }
00109 
00110   // Copy of persistent store objects is forbidden.
00111   inline persistent_store&
00112   operator = (const persistent_store&)
00113     {
00114       return *this;
00115     }
00116 
00117 protected:
00119   inline
00120   persistent_store (persist_id_t id, void *object, size_t len)
00121     {
00122       create (id, object, len);
00123     }
00124 
00125 public:
00127   //
00128   // The persistent store is freed and is no longer used to save
00129   // the object.
00130   void
00131   revoke ();
00132 };
00133 
00134 
00139 class persistent_object : private persistent_store
00140 {
00141 protected:
00142 
00143   // First persistent object in the list.
00144   static persistent_object *first;
00145 
00146   // Next persistent object in the list.
00147   persistent_object *next;
00148 
00149   // Pointer to the object in memory (runtime copy).
00150   unsigned char *object;
00151 
00152   inline
00153   persistent_object ()
00154     {}
00155 
00156 private:
00157   // Copy constructor is forbidden.
00158   inline
00159   persistent_object (const persistent_object&)
00160     {
00161       ;
00162     }
00163 
00164   // Copy of persistent object is forbidden.
00165   inline persistent_object&
00166   operator = (const persistent_object&)
00167     {
00168       return *this;
00169     }
00170 public:
00171 
00173   inline
00174   persistent_object (persist_id_t id, void *object, size_t len)
00175     : persistent_store (id, object, len)
00176     {
00177       next = first;
00178       first = this;
00179     }
00180 
00182   //
00183   // Persistent objects with external storage are not managed completely
00184   // by `persistent_object' class.  We are not aware of when the object
00185   // is modified.  For these objects, it is necessary to call `save_all'
00186   // to synchronize the runtime value with the persistent storage.
00187   // Only the bytes that have changed are updated.
00188   static void
00189   save_all ();
00190 };
00191 
00192 
00193 
00195 //
00196 // This class is suitable for a transparent persistent object.
00197 // When the object is modified, the persistent storage is also updated.
00198 // This is implemented by overriding the `=' operator and the `(type)'
00199 // type conversion.
00200 //
00201 template <class type>
00202 class persistent : private persistent_store
00203 {
00204   type obj;
00205 
00207   inline void
00208   sync ()
00209     {
00210       save ((const unsigned char*) &obj);
00211     }
00212 public:
00214   inline
00215   persistent (persist_id_t id)
00216     : persistent_store (id, &obj, sizeof (obj))
00217     {
00218     }
00219 
00221   //
00222   // If it's the first time the object is created, initialize it
00223   // with <b>init</b>.
00224   inline
00225   persistent (persist_id_t id, const type& init)
00226     : persistent_store ()
00227     {
00228       if (create (id, &obj, sizeof (type)))
00229         {
00230           obj = init;
00231           sync ();
00232         }
00233     }
00234 
00236   //
00237   // If it's the first time the object is created, initialize it
00238   // with <b>init</b>.
00239   inline
00240   persistent (persist_id_t id, type& init)
00241     : persistent_store ()
00242     {
00243       if (create (id, &obj, sizeof (type)))
00244         {
00245           obj = init;
00246           sync ();
00247         }
00248     }
00249 
00251   //
00252   // The object can still be retrieve from persistent storage.
00253   inline
00254   ~persistent ()
00255     {
00256       ;
00257     }
00258 
00260   //
00261   // Modify the object and update its persistent storage.
00262   inline persistent<type>&
00263   operator = (const type& value)
00264     {
00265       obj = value;
00266       sync ();
00267       return *this;
00268     }
00269 
00271   //
00272   // Modify the object and update its persistent storage.
00273   inline persistent<type>&
00274   operator = (type& value)
00275     {
00276       obj = value;
00277       sync ();
00278       return *this;
00279     }
00280 
00282   inline
00283   operator const type& ()
00284     {
00285       return obj;
00286     }
00287 
00288   inline persistent<type>&
00289   operator ++ (int)
00290     {
00291       obj++;
00292       sync ();
00293       return *this;
00294     }
00295 
00296   inline persistent<type>&
00297   operator -- (int)
00298     {
00299       obj--;
00300       sync ();
00301       return *this;
00302     }
00303 };
00304 
00305   
00306 #endif