Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

PickleRegistry.d

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003         @file PickleRegistry.d
00004         
00005         Copyright (C) 2004 Kris Bell
00006         
00007         This software is provided 'as-is', without any express or implied
00008         warranty. In no event will the authors be held liable for damages
00009         of any kind arising from the use of this software.
00010         
00011         Permission is hereby granted to anyone to use this software for any 
00012         purpose, including commercial applications, and to alter it and/or 
00013         redistribute it freely, subject to the following restrictions:
00014         
00015         1. The origin of this software must not be misrepresented; you must 
00016            not claim that you wrote the original software. If you use this 
00017            software in a product, an acknowledgment within documentation of 
00018            said product would be appreciated but is not required.
00019 
00020         2. Altered source versions must be plainly marked as such, and must 
00021            not be misrepresented as being the original software.
00022 
00023         3. This notice may not be removed or altered from any distribution
00024            of the source.
00025 
00026 
00027                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00028 
00029 
00030         @version        Initial version, April 2004      
00031         @author         Kris
00032 
00033 
00034 *******************************************************************************/
00035 
00036 module mango.io.PickleRegistry;
00037 
00038 private import  mango.io.Exception;
00039         
00040 public  import  mango.io.model.IReader,
00041                 mango.io.model.IPickle;
00042 
00043 /*******************************************************************************
00044 
00045         Bare framework for registering and creating serializable objects.
00046         Such objects are intended to be transported across a local network
00047         and re-instantiated at some destination node. 
00048 
00049         Each IPickle exposes the means to write, or freeze, its content. An
00050         IPickleFactory provides the means to create a new instance of itself
00051         populated with thawed data. Frozen objects are uniquely identified 
00052         by a guid exposed via the interface. Responsibility of maintaining
00053         uniqueness across said identifiers lies in the hands of the developer.
00054 
00055         See PickleReader for an example of how this is expected to operate.
00056 
00057 *******************************************************************************/
00058 
00059 class PickleRegistry
00060 {
00061         private static Object           lock;
00062         private static Proxy[char[]]    registry;
00063 
00064         /***********************************************************************
00065         
00066         ***********************************************************************/
00067 
00068         alias Object function (IReader reader) SimpleProxyFnc;
00069         alias Object function (IReader reader, char[] guid) GuidProxyFnc;
00070 
00071         /***********************************************************************
00072         
00073                 Base registrar entry
00074 
00075         ***********************************************************************/
00076 
00077         private class Proxy
00078         {
00079                 abstract Object create (IReader reader);
00080         }
00081 
00082         /***********************************************************************
00083         
00084                 Simple registrar entry
00085 
00086         ***********************************************************************/
00087 
00088         private class SimpleProxy : Proxy
00089         {
00090                 SimpleProxyFnc  fnc;
00091 
00092                 /***************************************************************
00093         
00094                 ***************************************************************/
00095               
00096                 this (SimpleProxyFnc fnc)
00097                 {
00098                         this.fnc = fnc;
00099                 }
00100 
00101                 /***************************************************************
00102         
00103                 ***************************************************************/
00104               
00105                 Object create (IReader reader)
00106                 {       
00107                         return fnc (reader);
00108                 }
00109         }
00110 
00111         /***********************************************************************
00112         
00113                 Guid registrar entry
00114 
00115         ***********************************************************************/
00116 
00117         private class GuidProxy : Proxy
00118         {
00119                 GuidProxyFnc    fnc;
00120                 char[]          guid;
00121 
00122                 /***************************************************************
00123         
00124                 ***************************************************************/
00125               
00126                 this (GuidProxyFnc fnc, char[] guid)
00127                 {
00128                         this.fnc = fnc;
00129                         this.guid = guid;
00130                 }
00131 
00132                 /***************************************************************
00133         
00134                 ***************************************************************/
00135               
00136                 Object create (IReader reader)
00137                 {       
00138                         return fnc (reader, guid);
00139                 }
00140         }
00141 
00142         /***********************************************************************
00143         
00144                 IPickleFactory registrar entry
00145 
00146         ***********************************************************************/
00147 
00148         private class PickleProxy : Proxy
00149         {
00150                 IPickleFactory  factory;
00151 
00152                 /***************************************************************
00153         
00154                 ***************************************************************/
00155               
00156                 this (IPickleFactory factory)
00157                 {
00158                         this.factory = factory;
00159                 }
00160 
00161                 /***************************************************************
00162         
00163                 ***************************************************************/
00164               
00165                 Object create (IReader reader)
00166                 {       
00167                         return factory.create (reader);
00168                 }
00169         }
00170 
00171         /***********************************************************************
00172         
00173                 This is a singleton: the constructor should not be exposed
00174 
00175         ***********************************************************************/
00176 
00177         private this ()
00178         {
00179         }
00180 
00181         /***********************************************************************
00182         
00183                 Initialize the environment
00184 
00185         ***********************************************************************/
00186 
00187         private static this()
00188         {
00189                 // have to do this to work around static syncronization bug
00190                 lock = new Object();
00191         }
00192 
00193         /***********************************************************************
00194         
00195                 Add the provided class to the registry. Note that one
00196                 cannot change a registration once it is placed. Neither
00197                 can one remove registered item. This is done to avoid 
00198                 major issues when trying to synchronize servers across
00199                 a farm, which may still have live instances of "old"
00200                 objects waiting to be passed around the cluster. New
00201                 versions of an object should be given a distinct guid
00202                 from the prior version; appending an incremental number 
00203                 may well be sufficient for your needs.
00204 
00205         ***********************************************************************/
00206 
00207         private static synchronized void enroll (Proxy proxy, char[] guid)
00208         {
00209                 if (guid in registry)
00210                     throw new PickleException ("Invalid attempt to re-register a guid");
00211         
00212                 registry[guid] = proxy;
00213         }
00214 
00215         /***********************************************************************
00216         
00217                 do a synchronized Proxy lookup of the guid
00218 
00219         ***********************************************************************/
00220 
00221         private final static synchronized Proxy lookup (char[] guid)
00222         {
00223                 if (guid in registry)
00224                     return registry [guid];
00225                 return null;
00226         }
00227 
00228         /***********************************************************************
00229         
00230                 Add the provided object to the registry. Note that one
00231                 cannot change a registration once it is placed. Neither
00232                 can one remove registered item. This is done to avoid 
00233                 major issues when trying to synchronize servers across
00234                 a farm, which may still have live instances of "old"
00235                 objects waiting to be passed around the cluster. New
00236                 versions of an object should be given a distinct guid
00237                 from the prior version; appending an incremental number 
00238                 may well be sufficient for your needs.
00239 
00240         ***********************************************************************/
00241 
00242         static void enroll (IPickleFactory object)
00243         {
00244                 enroll (new PickleProxy(object), object.getGuid);
00245         }
00246 
00247         /***********************************************************************
00248         
00249                 Add the provided function to the registry. Note that one
00250                 cannot change a registration once it is placed. Neither
00251                 can one remove registered item. This is done to avoid 
00252                 major issues when trying to synchronize servers across
00253                 a farm, which may still have live instances of "old"
00254                 objects waiting to be passed around the cluster. New
00255                 versions of an object should be given a distinct guid
00256                 from the prior version; appending an incremental number 
00257                 may well be sufficient for your needs.
00258 
00259         ***********************************************************************/
00260 
00261         static void enroll (SimpleProxyFnc sp, char[] guid)
00262         {
00263                 enroll (new SimpleProxy(sp), guid);
00264         }
00265 
00266         /***********************************************************************
00267         
00268                 Add the provided function to the registry. Note that one
00269                 cannot change a registration once it is placed. Neither
00270                 can one remove registered item. This is done to avoid 
00271                 major issues when trying to synchronize servers across
00272                 a farm, which may still have live instances of "old"
00273                 objects waiting to be passed around the cluster. New
00274                 versions of an object should be given a distinct guid
00275                 from the prior version; appending an incremental number 
00276                 may well be sufficient for your needs.
00277 
00278         ***********************************************************************/
00279 
00280         static void enroll (GuidProxyFnc gp, char[] guid)
00281         {
00282                 enroll (new GuidProxy(gp, guid), guid);
00283         }
00284 
00285         /***********************************************************************
00286         
00287                 Create a new instance of a registered class from the content
00288                 made available via the given reader. The factory is located
00289                 using the provided guid, which must match an enrolled class.
00290 
00291                 Note that only the factory lookup is synchronized, and not 
00292                 the instance construction itself.
00293 
00294         ***********************************************************************/
00295 
00296         static Object create (IReader reader, char[] guid)
00297         {
00298                 // locate the appropriate Proxy. 
00299                 Proxy p = lookup (guid);
00300                 if (p)
00301                     return p.create (reader);
00302 
00303                 throw new PickleException ("Attempt to unpickle via unregistered guid '"~guid~"'");
00304         }
00305 }
00306 

Generated on Sun Nov 7 19:06:52 2004 for Mango by doxygen 1.3.6