modulesystem.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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