Back to index

lightning-sunbird  0.9+nobinonly
GUSIFactory.h
Go to the documentation of this file.
00001 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  
00002 // % Project  :      GUSI                        -      Grand Unified Socket Interface                    
00003 // % File            :      GUSIFactory.nw              -      Socket factories                            
00004 // % Author   :      Matthias Neeracher                                           
00005 // % Language :      C++                                                        
00006 // %                                                                       
00007 // % $Log: GUSIFactory.h,v $
00008 // % Revision 1.1  2001/03/11 22:35:04  sgehani%netscape.com
00009 // % First Checked In.
00010 // %                                              
00011 // % Revision 1.10  2000/05/23 07:00:00  neeri                             
00012 // % Improve formatting                                                    
00013 // %                                                                       
00014 // % Revision 1.9  2000/03/15 07:22:07  neeri                              
00015 // % Enforce alignment choices                                             
00016 // %                                                                       
00017 // % Revision 1.8  1999/11/15 07:27:18  neeri                              
00018 // % Getting ready for GUSI 2.0.1                                          
00019 // %                                                                       
00020 // % Revision 1.7  1999/08/26 05:45:02  neeri                              
00021 // % Fixes for literate edition of source code                             
00022 // %                                                                       
00023 // % Revision 1.6  1999/05/29 06:26:43  neeri                              
00024 // % Fixed header guards                                                   
00025 // %                                                                       
00026 // % Revision 1.5  1998/11/22 23:06:53  neeri                              
00027 // % Releasing 2.0a4 in a hurry                                            
00028 // %                                                                       
00029 // % Revision 1.4  1998/10/25 11:37:37  neeri                              
00030 // % More configuration hooks                                              
00031 // %                                                                       
00032 // % Revision 1.3  1998/08/02 11:20:08  neeri                              
00033 // % Fixed some typos                                                      
00034 // %                                                                       
00035 // % Revision 1.2  1998/01/25 20:53:54  neeri                              
00036 // % Engine implemented, except for signals & scheduling                   
00037 // %                                                                       
00038 // % Revision 1.1  1996/12/16 02:12:40  neeri                              
00039 // % TCP Sockets sort of work                                              
00040 // %                                                                       
00041 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  
00042 //                                                                         
00043 // \chapter{Socket Factories}                                              
00044 //                                                                         
00045 // Instead of creating sockets of some specific subtype of [[GUSISocket]], 
00046 // directly, we choose the more flexible approach of creating them in      
00047 // some instance of a subtype of the abstract factory class [[GUSISocketFactory]].
00048 // For even more flexibility and a direct mapping to BSD socket domains,   
00049 // [[GUSISocketFactory]] instances are collected in a [[GUSISocketDomainRegistry]].
00050 // If several types and or protocols in a domain are implemented, they are collected 
00051 // in a [[GUSISocketTypeRegistry]].                                        
00052 //                                                                         
00053 // <GUSIFactory.h>=                                                        
00054 #ifndef _GUSIFactory_
00055 #define _GUSIFactory_
00056 
00057 #ifdef GUSI_SOURCE
00058 
00059 #include "GUSISocket.h"
00060 
00061 #include <ConditionalMacros.h>
00062 
00063 #if PRAGMA_STRUCT_ALIGN
00064 #pragma options align=native
00065 #endif
00066 
00067 // \section{Definition of [[GUSISocketFactory]]}                           
00068 //                                                                         
00069 // [[GUSISocketFactory]] consists of a few maintenance functions and the socket 
00070 // operations.                                                             
00071 //                                                                         
00072 // <Definition of class [[GUSISocketFactory]]>=                            
00073 class GUSISocketFactory {
00074 public:
00075        virtual int socketpair(int domain, int type, int protocol, GUSISocket * s[2]);
00076        virtual GUSISocket * socket(int domain, int type, int protocol) = 0;
00077 protected:
00078        GUSISocketFactory()                       {}
00079        virtual ~GUSISocketFactory()       {}
00080 };
00081 // \section{Definition of [[GUSISocketDomainRegistry]]}                    
00082 //                                                                         
00083 // The [[GUSISocketDomainRegistry]] is a singleton class registering all socket 
00084 // domains.                                                                
00085 //                                                                         
00086 // <Definition of class [[GUSISocketDomainRegistry]]>=                     
00087 class GUSISocketDomainRegistry : public GUSISocketFactory {
00088 public:
00089        // The only instance of [[GUSISocketDomainRegistry]] is, as usual, obtained by calling
00090  // [[Instance]]. Calling [[socket]] on this instance will then create a socket.
00091  //                                                                         
00092  // <Socket creation interface of [[GUSISocketDomainRegistry]]>=            
00093  virtual GUSISocket * socket(int domain, int type, int protocol);
00094  virtual int  socketpair(int domain, int type, int protocol, GUSISocket * s[2]);
00095  static  GUSISocketDomainRegistry *       Instance();
00096        // [[AddFactory]] and [[RemoveFactory]] add and remove a [[GUSISocketFactory]] 
00097  // for a given domain number. Both return the previous registrant.         
00098  //                                                                         
00099  // <Registration interface of [[GUSISocketDomainRegistry]]>=               
00100  GUSISocketFactory * AddFactory(int domain, GUSISocketFactory * factory);
00101  GUSISocketFactory * RemoveFactory(int domain);
00102 private:
00103        // <Privatissima of [[GUSISocketDomainRegistry]]>=                         
00104  static GUSISocketDomainRegistry * sInstance;
00105  // We store domain factories in a table that is quite comfortably sized.   
00106  //                                                                         
00107  // <Privatissima of [[GUSISocketDomainRegistry]]>=                         
00108  GUSISocketFactory * factory[AF_MAX];
00109  GUSISocketDomainRegistry();
00110 };
00111 // \section{Definition of [[GUSISocketTypeRegistry]]}                      
00112 //                                                                         
00113 // A [[GUSISocketTypeRegistry]] registers factories for some domain by type and
00114 // protocol.                                                               
00115 //                                                                         
00116 // <Definition of class [[GUSISocketTypeRegistry]]>=                       
00117 class GUSISocketTypeRegistry : public GUSISocketFactory {
00118 public:
00119        // [[GUSISocketTypeRegistry]] is not a singleton, but each instance is somewhat
00120  // singletonish in that it does some delayed initialization only when it's used
00121  // and at that point registers itself with the [[GUSISocketDomainRegistry]].
00122  // Calling [[socket]] on these instances will then create a socket.        
00123  //                                                                         
00124  // <Socket creation interface of [[GUSISocketTypeRegistry]]>=              
00125  GUSISocketTypeRegistry(int domain, int maxfactory);
00126  virtual GUSISocket * socket(int domain, int type, int protocol);
00127  virtual int socketpair(int domain, int type, int protocol, GUSISocket * s[2]);
00128        // [[AddFactory]] and [[RemoveFactory]] add and remove a [[GUSISocketFactory]] 
00129  // for a given type and protocol (both of which can be specified as 0 to match any
00130  // value). Both return the previous registrant.                            
00131  //                                                                         
00132  // <Registration interface of [[GUSISocketTypeRegistry]]>=                 
00133  GUSISocketFactory * AddFactory(int type, int protocol, GUSISocketFactory * factory);
00134  GUSISocketFactory * RemoveFactory(int type, int protocol);
00135 private:
00136        // \section{Implementation of [[GUSISocketTypeRegistry]]}                  
00137  //                                                                         
00138  // We store type factories in a fixed size table. This table is only       
00139  // initialized when any non-constructor public member is called.           
00140  //                                                                         
00141  // <Privatissima of [[GUSISocketTypeRegistry]]>=                           
00142  struct Entry {
00143        int                                type;
00144        int                                protocol;
00145        GUSISocketFactory * factory;
00146        Entry()       : type(0), protocol(0), factory(nil) {}
00147  };
00148  Entry        *      factory;
00149  int                 domain;
00150  int                 maxfactory;
00151  // [[Initialize]] initializes the table and registers the object with the  
00152  // [[GUSISocketDomainRegistry]] the first time it's called.                
00153  //                                                                         
00154  // <Privatissima of [[GUSISocketTypeRegistry]]>=                           
00155  void                Initialize();
00156  // Unlike for a [[GUSISocketDomainRegistry]], match identification for a   
00157  // [[GUSISocketTypeRegistry]] takes a linear search. [[Find]] stops        
00158  // when it has found either a match or an empty slot.                      
00159  //                                                                         
00160  // <Privatissima of [[GUSISocketTypeRegistry]]>=                           
00161  bool Find(int type, int protocol, bool exact, Entry *&found);
00162 };
00163 
00164 #if PRAGMA_STRUCT_ALIGN
00165 #pragma options align=reset
00166 #endif
00167 
00168 // \section{Implementation of [[GUSISocketDomainRegistry]]}                
00169 //                                                                         
00170 // By now, you should know how singletons are created. Could it be that the
00171 // combination of Design Patterns and Literate Programming leads to a      
00172 // proliferation of cliches?                                               
00173 //                                                                         
00174 // <Definition of [[GUSISetupFactories]] hook>=                            
00175 extern "C" void GUSISetupFactories();
00176 
00177 // <Inline member functions for class [[GUSISocketDomainRegistry]]>=       
00178 inline GUSISocketDomainRegistry * GUSISocketDomainRegistry::Instance()
00179 {
00180        if (!sInstance) {
00181               sInstance = new GUSISocketDomainRegistry();
00182               GUSISetupFactories();
00183        }
00184        
00185        return sInstance;
00186 }
00187 // [[RemoveFactory]] can actually be implemented in terms of [[AddFactory]] but
00188 // that might confuse readers.                                             
00189 //                                                                         
00190 // <Inline member functions for class [[GUSISocketDomainRegistry]]>=       
00191 inline GUSISocketFactory * GUSISocketDomainRegistry::RemoveFactory(int domain)
00192 {
00193        return AddFactory(domain, nil);
00194 }
00195 // <Inline member functions for class [[GUSISocketTypeRegistry]]>=         
00196 inline GUSISocketTypeRegistry::GUSISocketTypeRegistry(int domain, int maxfactory)
00197  : domain(domain), maxfactory(maxfactory), factory(nil)
00198 {
00199 }
00200 
00201 #endif /* GUSI_SOURCE */
00202 
00203 #endif /* _GUSIFactory_ */