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 #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