modulesystem.h

Go to the documentation of this file.
00001 /*
00002  Copyright (C) 2001-2006, William Joseph.
00003  All Rights Reserved.
00004 
00005  This file is part of GtkRadiant.
00006 
00007  GtkRadiant 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 of the License, or
00010  (at your option) any later version.
00011 
00012  GtkRadiant 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 GtkRadiant; if not, write to the Free Software
00019  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020  */
00021 
00027 #if !defined(INCLUDED_MODULESYSTEM_H)
00028 #define INCLUDED_MODULESYSTEM_H
00029 
00030 #include "generic/static.h"
00031 #include "debugging/debugging.h"
00032 
00033 #if defined(WIN32)
00034 #define RADIANT_DLLEXPORT __declspec(dllexport)
00035 #define RADIANT_DLLIMPORT __declspec(dllimport)
00036 #else
00037 #define RADIANT_DLLEXPORT
00038 #define RADIANT_DLLIMPORT
00039 #endif
00040 
00045 class Module
00046 {
00047     public:
00048         virtual ~Module ()
00049         {
00050         }
00051         virtual void capture () = 0;
00052         virtual void release () = 0;
00053         virtual void* getTable () = 0;
00054 };
00055 
00059 inline void* Module_getTable (Module& module)
00060 {
00061     return module.getTable();
00062 }
00063 
00064 class TextOutputStream;
00065 class DebugMessageHandler;
00066 
00071 class ModuleServer
00072 {
00073     public:
00074         class Visitor
00075         {
00076             public:
00077                 virtual ~Visitor ()
00078                 {
00079                 }
00080                 virtual void visit (const std::string& name, Module& module) const = 0;
00081         };
00082 
00083         virtual ~ModuleServer ()
00084         {
00085         }
00086 
00087         virtual void setError (bool error) = 0;
00088         virtual bool getError () const = 0;  
00090         virtual TextOutputStream& getOutputStream () = 0;
00091         virtual TextOutputStream& getErrorStream () = 0;
00092         virtual TextOutputStream& getWarningStream () = 0;
00093         virtual DebugMessageHandler& getDebugMessageHandler () = 0;
00094 
00095         virtual void registerModule (const char* type, int version, const char* name, Module& module) = 0;
00096         virtual Module* findModule (const char* type, int version, const char* name) const = 0;  
00097         virtual void foreachModule (const char* type, int version, const Visitor& visitor) = 0;
00098 };
00099 
00104 class ModuleServerHolder
00105 {
00106         ModuleServer* m_server;
00107     public:
00108         ModuleServerHolder () :
00109             m_server(0)
00110         {
00111         }
00112         void set (ModuleServer& server)
00113         {
00114             m_server = &server;
00115         }
00116         ModuleServer& get ()
00117         {
00118             return *m_server;
00119         }
00120 };
00121 
00126 typedef Static<ModuleServerHolder> GlobalModuleServer;
00127 
00131 inline ModuleServer& globalModuleServer ()
00132 {
00133     return GlobalModuleServer::instance().get();
00134 }
00135 
00140 inline void initialiseModule (ModuleServer& server)
00141 {
00142     GlobalErrorStream::instance().setOutputStream(server.getErrorStream());
00143     GlobalOutputStream::instance().setOutputStream(server.getOutputStream());
00144     GlobalWarningStream::instance().setOutputStream(server.getWarningStream());
00145     GlobalDebugMessageHandler::instance().setHandler(server.getDebugMessageHandler());
00146     GlobalModuleServer::instance().set(server);
00147 }
00148 
00153 template<typename Type>
00154 class Modules
00155 {
00156     public:
00157         virtual ~Modules ()
00158         {
00159         }
00160         class Visitor
00161         {
00162             public:
00163                 virtual ~Visitor ()
00164                 {
00165                 }
00166                 virtual void visit (const std::string& name, const Type& table) const = 0;
00167         };
00168 
00169         virtual Type* findModule (const std::string& name) = 0;
00170         virtual void foreachModule (const Visitor& visitor) = 0;
00171 };
00172 
00173 #include "debugging/debugging.h"
00174 
00179 template<typename Type>
00180 class ModuleRef
00181 {
00182         Module* m_module;
00183         Type* m_table;
00184     public:
00185         ModuleRef (const char* name) :
00186             m_table(0)
00187         {
00188             if (!globalModuleServer().getError()) {
00189                 m_module = globalModuleServer().findModule(typename Type::Name(), typename Type::Version(), name);
00190                 if (m_module == 0) {
00191                     globalModuleServer().setError(true);
00192                     globalErrorStream() << "ModuleRef::initialise: type=" << makeQuoted(typename Type::Name())
00193                             << " version=" << makeQuoted(typename Type::Version()) << " name=" << makeQuoted(name)
00194                             << " - not found\n";
00195                 } else {
00196                     m_module->capture();
00197                     if (!globalModuleServer().getError()) {
00198                         m_table = static_cast<Type*> (m_module->getTable());
00199                     }
00200                 }
00201             }
00202         }
00203         ~ModuleRef ()
00204         {
00205             if (m_module != 0) {
00206                 m_module->release();
00207             }
00208         }
00209         Type* getTable ()
00210         {
00211 #if defined(DEBUG)
00212             ASSERT_MESSAGE(m_table != 0, "ModuleRef::getTable: type=" << makeQuoted(typename Type::Name()) << " version=" << makeQuoted(typename Type::Version()) << " - module-reference used without being initialised");
00213 #endif
00214             return m_table;
00215         }
00216 };
00217 
00222 template<typename Type>
00223 class SingletonModuleRef
00224 {
00225         Module* m_module;
00226         Type* m_table;
00227     public:
00228 
00229         SingletonModuleRef () :
00230             m_module(0), m_table(0)
00231         {
00232         }
00233 
00234         bool initialised () const
00235         {
00236             return m_module != 0;
00237         }
00238 
00242         void initialise (const char* name)
00243         {
00244             m_module = globalModuleServer().findModule(typename Type::Name(), typename Type::Version(), name);
00245             if (m_module == 0) {
00246                 globalModuleServer().setError(true);
00247                 globalErrorStream() << "SingletonModuleRef::initialise: type=" << makeQuoted(typename Type::Name())
00248                         << " version=" << makeQuoted(typename Type::Version()) << " name=" << makeQuoted(name)
00249                         << " - not found\n";
00250             }
00251         }
00252 
00253         Type* getTable ()
00254         {
00255 #if defined(DEBUG)
00256             ASSERT_MESSAGE(m_table != 0, "SingletonModuleRef::getTable: type=" << makeQuoted(typename Type::Name()) << " version=" << makeQuoted(typename Type::Version()) << " - module-reference used without being initialised");
00257 #endif
00258             return m_table;
00259         }
00260 
00264         void capture ()
00265         {
00266             if (initialised()) {
00267                 m_module->capture();
00268                 m_table = static_cast<Type*> (m_module->getTable());
00269             }
00270         }
00271         void release ()
00272         {
00273             if (initialised()) {
00274                 m_module->release();
00275             }
00276         }
00277 };
00278 
00279 template<typename Type>
00280 class GlobalModule
00281 {
00282         static SingletonModuleRef<Type> m_instance;
00283     public:
00284         static SingletonModuleRef<Type>& instance ()
00285         {
00286             return m_instance;
00287         }
00288         static Type& getTable ()
00289         {
00290             return *m_instance.getTable();
00291         }
00292 };
00293 
00294 template<class Type>
00295 SingletonModuleRef<Type> GlobalModule<Type>::m_instance;
00296 
00297 template<typename Type>
00298 class GlobalModuleRef
00299 {
00300     public:
00301         GlobalModuleRef (const char* name = "*")
00302         {
00303             if (!globalModuleServer().getError()) {
00304                 GlobalModule<Type>::instance().initialise(name);
00305             }
00306             GlobalModule<Type>::instance().capture();
00307         }
00308         ~GlobalModuleRef ()
00309         {
00310             GlobalModule<Type>::instance().release();
00311         }
00312         Type& getTable ()
00313         {
00314             return GlobalModule<Type>::getTable();
00315         }
00316 };
00317 
00318 #endif

Generated by  doxygen 1.6.2