khanat-opennel-code/code/nel/include/nel/misc/app_context.h

300 lines
10 KiB
C++

// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef APP_CONTEXT_H
#define APP_CONTEXT_H
#include "nel/misc/types_nl.h"
#include <map>
namespace NLMISC
{
class CLog;
class CMemDisplayer;
class CMsgBoxDisplayer;
/** Interface definition for nel context.
* Any application wide data can be accessed thru this interface.
*
* The NeL context is a mean to allow dynamic library loading in NeL.
* In order to make all NeL application safe, it is mandatory to declare
* a NeL context at startup of any application (first instruction of the
* main() or WinMain() is good practice).
* Note that for NLNET::IService oriented application, service framwork
* already provide the application context.
*
* \author Boris 'SoniX' Boucher
* \date 2005
*/
class INelContext
{
static INelContext ** _getInstance();
public:
/// Access to the context singleton
static INelContext &getInstance();
static bool isContextInitialised();
virtual ~INelContext();
//@name Singleton registry
//@{
/** Return the pointer associated to a given singleton name
* If the name is not present, return NULL.
*/
virtual void *getSingletonPointer(const std::string &singletonName) =0;
/** Register a singleton pointer.
*/
virtual void setSingletonPointer(const std::string &singletonName, void *ptr) =0;
/** Release a singleton pointer */
virtual void releaseSingletonPointer(const std::string &singletonName, void *ptr) =0;
//@}
//@name Global debugging object
//@{
virtual CLog *getErrorLog() =0;
virtual void setErrorLog(CLog *errorLog) =0;
virtual CLog *getWarningLog() =0;
virtual void setWarningLog(CLog *warningLog) =0;
virtual CLog *getInfoLog() =0;
virtual void setInfoLog(CLog *infoLog) =0;
virtual CLog *getDebugLog() =0;
virtual void setDebugLog(CLog *debugLog) =0;
virtual CLog *getAssertLog() =0;
virtual void setAssertLog(CLog *assertLog) =0;
virtual CMemDisplayer *getDefaultMemDisplayer() =0;
virtual void setDefaultMemDisplayer(CMemDisplayer *memDisplayer) =0;
virtual CMsgBoxDisplayer *getDefaultMsgBoxDisplayer() =0;
virtual void setDefaultMsgBoxDisplayer(CMsgBoxDisplayer *msgBoxDisplayer) =0;
virtual bool getDebugNeedAssert() =0;
virtual void setDebugNeedAssert(bool needAssert) =0;
virtual bool getNoAssert() =0;
virtual void setNoAssert(bool noAssert) =0;
virtual bool getAlreadyCreateSharedAmongThreads() =0;
virtual void setAlreadyCreateSharedAmongThreads(bool b) =0;
//@}
protected:
/// Called by derived class to finalize initialisation of context
void contextReady();
static INelContext *_NelContext;
};
/** This class implement the context interface for the application module
* That means that this class will really hold the data.
* \author Boris 'SoniX' Boucher
* \date 2005
*/
class CApplicationContext : public INelContext
{
public:
CApplicationContext();
virtual void *getSingletonPointer(const std::string &singletonName);
virtual void setSingletonPointer(const std::string &singletonName, void *ptr);
virtual void releaseSingletonPointer(const std::string &singletonName, void *ptr);
virtual CLog *getErrorLog();
virtual void setErrorLog(CLog *errorLog);
virtual CLog *getWarningLog();
virtual void setWarningLog(CLog *warningLog);
virtual CLog *getInfoLog();
virtual void setInfoLog(CLog *infoLog);
virtual CLog *getDebugLog();
virtual void setDebugLog(CLog *debugLog);
virtual CLog *getAssertLog();
virtual void setAssertLog(CLog *assertLog);
virtual CMemDisplayer *getDefaultMemDisplayer();
virtual void setDefaultMemDisplayer(CMemDisplayer *memDisplayer);
virtual CMsgBoxDisplayer *getDefaultMsgBoxDisplayer();
virtual void setDefaultMsgBoxDisplayer(CMsgBoxDisplayer *msgBoxDisplayer);
virtual bool getDebugNeedAssert();
virtual void setDebugNeedAssert(bool needAssert);
virtual bool getNoAssert();
virtual void setNoAssert(bool noAssert);
virtual bool getAlreadyCreateSharedAmongThreads();
virtual void setAlreadyCreateSharedAmongThreads(bool b);
private:
/// Singleton registry
typedef std::map<std::string, void*> TSingletonRegistry;
TSingletonRegistry _SingletonRegistry;
CLog *ErrorLog;
CLog *WarningLog;
CLog *InfoLog;
CLog *DebugLog;
CLog *AssertLog;
CMemDisplayer *DefaultMemDisplayer;
CMsgBoxDisplayer *DefaultMsgBoxDisplayer;
bool DebugNeedAssert;
bool NoAssert;
bool AlreadyCreateSharedAmongThreads;
};
/** This class implements the context interface for the a library module.
* All it contains is forward call to the application context instance.
* \author Boris 'SoniX' Boucher
* \date 2005
*/
class CLibraryContext : public INelContext
{
public:
CLibraryContext (INelContext &applicationContext);
virtual void *getSingletonPointer(const std::string &singletonName);
virtual void setSingletonPointer(const std::string &singletonName, void *ptr);
virtual void releaseSingletonPointer(const std::string &singletonName, void *ptr);
virtual CLog *getErrorLog();
virtual void setErrorLog(CLog *errorLog);
virtual CLog *getWarningLog();
virtual void setWarningLog(CLog *warningLog);
virtual CLog *getInfoLog();
virtual void setInfoLog(CLog *infoLog);
virtual CLog *getDebugLog();
virtual void setDebugLog(CLog *debugLog);
virtual CLog *getAssertLog();
virtual void setAssertLog(CLog *assertLog);
virtual CMemDisplayer *getDefaultMemDisplayer();
virtual void setDefaultMemDisplayer(CMemDisplayer *memDisplayer);
virtual CMsgBoxDisplayer *getDefaultMsgBoxDisplayer();
virtual void setDefaultMsgBoxDisplayer(CMsgBoxDisplayer *msgBoxDisplayer);
virtual bool getDebugNeedAssert();
virtual void setDebugNeedAssert(bool needAssert);
virtual bool getNoAssert();
virtual void setNoAssert(bool noAssert);
virtual bool getAlreadyCreateSharedAmongThreads();
virtual void setAlreadyCreateSharedAmongThreads(bool b);
private:
/// Pointer to the application context.
INelContext *_ApplicationContext;
};
//@name Singleton utility
//@{
/** Some utility macro to build singleton compatible with
* the dynamic loading of library
* This macro must be put inside the singleton class
* definition.
* Warning : this macro change the current access right, it end up with
* private access right.
*/
#define NLMISC_SAFE_SINGLETON_DECL(className) \
private:\
/* declare private constructors*/ \
/*className () {}*/\
className (const className &) {}\
/* the local static pointer to the singleton instance */ \
static className *_Instance; \
public:\
static className &getInstance() \
{ \
if (_Instance == NULL) \
{ \
/* the nel context MUST be initialised */ \
nlassertex(NLMISC::INelContext::isContextInitialised(), ("You are trying to access a safe singleton without having initialized a NeL context. The simplest correction is to add 'NLMISC::CApplicationContext myApplicationContext;' at the very beginning of your application.")); \
void *ptr = NLMISC::INelContext::getInstance().getSingletonPointer(#className); \
if (ptr == NULL) \
{ \
/* allocate the singleton and register it */ \
_Instance = new className; \
NLMISC::INelContext::getInstance().setSingletonPointer(#className, _Instance); \
} \
else \
{ \
_Instance = reinterpret_cast<className*>(ptr); \
} \
} \
return *_Instance; \
} \
private:
/** The same as above, but generate a getInstance method that
* return a pointer instead of a reference
*/
#define NLMISC_SAFE_SINGLETON_DECL_PTR(className) \
private:\
/* declare private constructors*/ \
/*className () {}*/\
className (const className &) {}\
/* the local static pointer to the singleton instance */ \
static className *_Instance; \
public:\
static className *getInstance() \
{ \
if (_Instance == NULL) \
{ \
/* the nel context MUST be initialised */ \
nlassertex(NLMISC::INelContext::isContextInitialised(), ("You are trying to access a safe singleton without having initialized a NeL context. The simplest correction is to add 'NLMISC::CApplicationContext myApplicationContext;' at the very beginning of your application.")); \
void *ptr = NLMISC::INelContext::getInstance().getSingletonPointer(#className); \
if (ptr == NULL) \
{ \
/* allocate the singleton and register it */ \
_Instance = new className; \
NLMISC::INelContext::getInstance().setSingletonPointer(#className, _Instance); \
} \
else \
{ \
_Instance = reinterpret_cast<className*>(ptr); \
} \
} \
return _Instance; \
} \
private:
/** This macro is the complement of the previous one.
* It must be put in a cpp file to implement the static
* property of the singleton.
*/
#define NLMISC_SAFE_SINGLETON_IMPL(className) className *className::_Instance = NULL;
/// Function type for library entry point
typedef void (*TInitLibraryFunc)(INelContext &applicationContext);
/** An helper macro to build the dll entry point easily.
*/
#define NLMISC_LIBRARY_ENTRY \
void libraryEntryImp(NLMISC::INelContext &applicationContext) \
{ \
nlassert(!NLMISC::INelContext::isContextInitialised() || &applicationContext == &(NLMISC::INelContext::getInstance())); \
\
if (!NLMISC::INelContext::isContextInitialised()) \
{ \
new CLibraryContext(applicationContext); \
} \
} \
extern "C" \
{ \
NLMISC_LIB_EXPORT TInitLibraryFunc libraryEntry = libraryEntryImp; \
} \
class CLibrary;
/// helper function to init newly loaded nel library
void initNelLibrary(CLibrary &lib);
} // namespace NLMISC
#endif //APP_CONTEXT_H