396 lines
9.9 KiB
C++
396 lines
9.9 KiB
C++
//
|
|
// Copyright (c) 2010-2011 Matthew Jack and Doug Binks
|
|
//
|
|
// This software is provided 'as-is', without any express or implied
|
|
// warranty. In no event will the authors be held liable for any damages
|
|
// arising from the use of this software.
|
|
// Permission is granted to anyone to use this software for any purpose,
|
|
// including commercial applications, and to alter it and redistribute it
|
|
// freely, subject to the following restrictions:
|
|
// 1. The origin of this software must not be misrepresented; you must not
|
|
// claim that you wrote the original software. If you use this software
|
|
// in a product, an acknowledgment in the product documentation would be
|
|
// appreciated but is not required.
|
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
|
// misrepresented as being the original software.
|
|
// 3. This notice may not be removed or altered from any source distribution.
|
|
|
|
#pragma once
|
|
|
|
#ifndef OBJECTINTERFACEPERMODULE_INCLUDED
|
|
#define OBJECTINTERFACEPERMODULE_INCLUDED
|
|
|
|
#include "ObjectInterface.h"
|
|
#include "RuntimeInclude.h"
|
|
#include "RuntimeLinkLibrary.h"
|
|
#include "RuntimeSourceDependency.h"
|
|
#include <string>
|
|
#include <vector>
|
|
#include <assert.h>
|
|
|
|
#ifndef RCCPPOFF
|
|
#define AU_ASSERT( statement ) do { if (!(statement)) { volatile int* p = 0; int a = *p; if(a) {} } } while(0)
|
|
#else
|
|
#define AU_ASSERT( statement ) assert( statement )
|
|
#endif //RCCPPOFF
|
|
|
|
class PerModuleInterface : public IPerModuleInterface
|
|
{
|
|
public:
|
|
static PerModuleInterface* GetInstance();
|
|
static SystemTable* g_pSystemTable;
|
|
|
|
void AddConstructor( IObjectConstructor* pConstructor );
|
|
|
|
virtual std::vector<IObjectConstructor*>& GetConstructors();
|
|
virtual void SetProjectIdForAllConstructors( unsigned short projectId_ );
|
|
virtual void SetSystemTable( SystemTable* pSystemTable );
|
|
|
|
SystemTable* GetSystemTable()
|
|
{
|
|
return g_pSystemTable;
|
|
}
|
|
|
|
virtual const std::vector<const char*>& GetRequiredSourceFiles() const;
|
|
virtual void AddRequiredSourceFiles( const char* file_ );
|
|
virtual void SetModuleFileName( const char* name )
|
|
{
|
|
m_ModuleFilename = name;
|
|
}
|
|
const char* GetCompiledPath() const
|
|
{
|
|
#ifdef COMPILE_PATH
|
|
return COMPILE_PATH;
|
|
#else
|
|
return "";
|
|
#endif
|
|
}
|
|
|
|
private:
|
|
PerModuleInterface();
|
|
|
|
~PerModuleInterface()
|
|
{
|
|
}
|
|
|
|
|
|
static PerModuleInterface* ms_pObjectManager;
|
|
std::vector<IObjectConstructor*> m_ObjectConstructors;
|
|
std::vector<const char*> m_RequiredSourceFiles;
|
|
std::string m_ModuleFilename;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T> class TObjectConstructorConcrete: public IObjectConstructor
|
|
{
|
|
public:
|
|
TObjectConstructorConcrete(
|
|
#ifndef RCCPPOFF
|
|
const char* Filename,
|
|
IRuntimeIncludeFileList* pIncludeFileList_,
|
|
IRuntimeSourceDependencyList* pSourceDependencyList_,
|
|
IRuntimeLinkLibraryList* pLinkLibraryList,
|
|
#endif
|
|
bool bIsSingleton,
|
|
bool bIsAutoConstructSingleton)
|
|
: m_bIsSingleton( bIsSingleton )
|
|
, m_bIsAutoConstructSingleton( bIsAutoConstructSingleton )
|
|
, m_pModuleInterface(0)
|
|
, m_Project(0)
|
|
#ifndef RCCPPOFF
|
|
, m_FileName( Filename )
|
|
, m_pIncludeFileList(pIncludeFileList_)
|
|
, m_pSourceDependencyList(pSourceDependencyList_)
|
|
, m_pLinkLibraryList(pLinkLibraryList)
|
|
#endif
|
|
{
|
|
#ifndef RCCPPOFF
|
|
// add path to filename
|
|
#ifdef COMPILE_PATH
|
|
m_FileName = COMPILE_PATH + m_FileName;
|
|
#endif
|
|
#endif
|
|
PerModuleInterface::GetInstance()->AddConstructor( this );
|
|
m_pModuleInterface = PerModuleInterface::GetInstance();
|
|
m_Id = InvalidId;
|
|
}
|
|
|
|
virtual IObject* Construct()
|
|
{
|
|
T* pT = 0;
|
|
if( m_bIsSingleton && m_ConstructedObjects.size() && m_ConstructedObjects[0] )
|
|
{
|
|
return m_ConstructedObjects[0];
|
|
}
|
|
|
|
if( m_FreeIds.empty() )
|
|
{
|
|
PerTypeObjectId id = m_ConstructedObjects.size();
|
|
|
|
pT = new T();
|
|
pT->SetPerTypeId( id );
|
|
m_ConstructedObjects.push_back( pT );
|
|
}
|
|
else
|
|
{
|
|
PerTypeObjectId id = m_FreeIds.back();
|
|
m_FreeIds.pop_back();
|
|
pT = new T();
|
|
pT->SetPerTypeId( id );
|
|
AU_ASSERT( 0 == m_ConstructedObjects[ id ] );
|
|
m_ConstructedObjects[ id ] = pT;
|
|
|
|
}
|
|
return pT;
|
|
}
|
|
|
|
virtual void ConstructNull()
|
|
{
|
|
// should not occur for singletons
|
|
AU_ASSERT( !m_bIsSingleton );
|
|
m_ConstructedObjects.push_back( NULL );
|
|
}
|
|
|
|
virtual const char* GetName()
|
|
{
|
|
return T::GetTypeNameStatic();
|
|
}
|
|
|
|
virtual void SetProjectId( unsigned short projectId_ )
|
|
{
|
|
m_Project = projectId_;
|
|
}
|
|
|
|
virtual unsigned short GetProjectId() const
|
|
{
|
|
return m_Project;
|
|
}
|
|
|
|
virtual const char* GetFileName()
|
|
{
|
|
#ifndef RCCPPOFF
|
|
return m_FileName.c_str();
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
virtual const char* GetCompiledPath()
|
|
{
|
|
#ifndef RCCPPOFF
|
|
#ifdef COMPILE_PATH
|
|
return COMPILE_PATH;
|
|
#else
|
|
return "";
|
|
#endif
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
virtual const char* GetIncludeFile( size_t Num_ ) const
|
|
{
|
|
#ifndef RCCPPOFF
|
|
if( m_pIncludeFileList )
|
|
{
|
|
return m_pIncludeFileList->GetIncludeFile( Num_ );
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
virtual size_t GetMaxNumIncludeFiles() const
|
|
{
|
|
#ifndef RCCPPOFF
|
|
if( m_pIncludeFileList )
|
|
{
|
|
return m_pIncludeFileList->MaxNum;
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
virtual const char* GetLinkLibrary( size_t Num_ ) const
|
|
{
|
|
#ifndef RCCPPOFF
|
|
if( m_pLinkLibraryList )
|
|
{
|
|
return m_pLinkLibraryList->GetLinkLibrary( Num_ );
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
virtual size_t GetMaxNumLinkLibraries() const
|
|
{
|
|
#ifndef RCCPPOFF
|
|
if( m_pLinkLibraryList )
|
|
{
|
|
return m_pLinkLibraryList->MaxNum;
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
virtual SourceDependencyInfo GetSourceDependency( size_t Num_ ) const
|
|
{
|
|
#ifndef RCCPPOFF
|
|
if( m_pSourceDependencyList )
|
|
{
|
|
return m_pSourceDependencyList->GetSourceDependency( Num_ );
|
|
}
|
|
#endif
|
|
return SourceDependencyInfo::GetNULL();
|
|
}
|
|
|
|
virtual size_t GetMaxNumSourceDependencies() const
|
|
{
|
|
#ifndef RCCPPOFF
|
|
if( m_pSourceDependencyList )
|
|
{
|
|
return m_pSourceDependencyList->MaxNum;
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
virtual bool GetIsSingleton() const
|
|
{
|
|
return m_bIsSingleton;
|
|
}
|
|
virtual bool GetIsAutoConstructSingleton() const
|
|
{
|
|
return m_bIsSingleton && m_bIsAutoConstructSingleton;
|
|
}
|
|
|
|
|
|
virtual IObject* GetConstructedObject( PerTypeObjectId id ) const
|
|
{
|
|
if( m_ConstructedObjects.size() > id )
|
|
{
|
|
return m_ConstructedObjects[id];
|
|
}
|
|
return 0;
|
|
}
|
|
virtual size_t GetNumberConstructedObjects() const
|
|
{
|
|
return m_ConstructedObjects.size();
|
|
}
|
|
virtual ConstructorId GetConstructorId() const
|
|
{
|
|
return m_Id;
|
|
}
|
|
virtual void SetConstructorId( ConstructorId id )
|
|
{
|
|
if( InvalidId == m_Id )
|
|
{
|
|
m_Id = id;
|
|
}
|
|
}
|
|
|
|
void DeRegister( PerTypeObjectId id )
|
|
{
|
|
//remove from constructed objects.
|
|
//use swap with last one
|
|
if( m_ConstructedObjects.size() - 1 == id )
|
|
{
|
|
//it's the last one, just remove it.
|
|
m_ConstructedObjects.pop_back();
|
|
}
|
|
else
|
|
{
|
|
m_FreeIds.push_back( id );
|
|
m_ConstructedObjects[ id ] = 0;
|
|
}
|
|
}
|
|
virtual void ClearIfAllDeleted()
|
|
{
|
|
m_FreeIds.clear();
|
|
m_ConstructedObjects.clear();
|
|
}
|
|
|
|
private:
|
|
bool m_bIsSingleton;
|
|
bool m_bIsAutoConstructSingleton;
|
|
std::vector<T*> m_ConstructedObjects;
|
|
std::vector<PerTypeObjectId> m_FreeIds;
|
|
ConstructorId m_Id;
|
|
PerModuleInterface* m_pModuleInterface;
|
|
unsigned short m_Project;
|
|
#ifndef RCCPPOFF
|
|
std::string m_FileName;
|
|
IRuntimeIncludeFileList* m_pIncludeFileList;
|
|
IRuntimeSourceDependencyList* m_pSourceDependencyList;
|
|
IRuntimeLinkLibraryList* m_pLinkLibraryList;
|
|
#endif
|
|
};
|
|
|
|
|
|
template<typename T> class TActual: public T
|
|
{
|
|
public:
|
|
// overload new/delete to get alignment correct
|
|
#ifdef _WIN32
|
|
void* operator new(size_t size)
|
|
{
|
|
size_t align = __alignof( TActual<T> );
|
|
return _aligned_malloc( size, align );
|
|
}
|
|
void operator delete(void* p)
|
|
{
|
|
_aligned_free( p );
|
|
}
|
|
#else
|
|
void* operator new(size_t size)
|
|
{
|
|
size_t align = __alignof__( TActual<T> );
|
|
void* pRet;
|
|
int retval = posix_memalign( &pRet, align, size );
|
|
(void)retval; //unused
|
|
return pRet;
|
|
}
|
|
void operator delete(void* p)
|
|
{
|
|
free( p );
|
|
}
|
|
#endif //_WIN32
|
|
friend class TObjectConstructorConcrete<TActual>;
|
|
virtual ~TActual() { m_Constructor.DeRegister( m_Id ); }
|
|
virtual PerTypeObjectId GetPerTypeId() const { return m_Id; }
|
|
virtual IObjectConstructor* GetConstructor() const { return &m_Constructor; }
|
|
static const char* GetTypeNameStatic();
|
|
virtual const char* GetTypeName() const
|
|
{
|
|
return GetTypeNameStatic();
|
|
}
|
|
private:
|
|
void SetPerTypeId( PerTypeObjectId id ) { m_Id = id; }
|
|
PerTypeObjectId m_Id;
|
|
static TObjectConstructorConcrete<TActual> m_Constructor;
|
|
};
|
|
#ifndef RCCPPOFF
|
|
#define REGISTERBASE( T, bIsSingleton, bIsAutoConstructSingleton ) \
|
|
static RuntimeIncludeFiles< __COUNTER__ > g_includeFileList_##T; \
|
|
static RuntimeSourceDependency< __COUNTER__ > g_sourceDependencyList_##T; \
|
|
static RuntimeLinkLibrary< __COUNTER__ > g_linkLibraryList_##T; \
|
|
template<> TObjectConstructorConcrete< TActual< T > > TActual< T >::m_Constructor( __FILE__, &g_includeFileList_##T, &g_sourceDependencyList_##T, &g_linkLibraryList_##T, bIsSingleton, bIsAutoConstructSingleton );\
|
|
template<> const char* TActual< T >::GetTypeNameStatic() { return #T; } \
|
|
template class TActual< T >;
|
|
#else
|
|
#define REGISTERBASE( T, bIsSingleton, bIsAutoConstructSingleton ) \
|
|
template<> TObjectConstructorConcrete< TActual< T > > TActual< T >::m_Constructor( bIsSingleton, bIsAutoConstructSingleton); \
|
|
template<> const char* TActual< T >::GetTypeNameStatic() { return #T; } \
|
|
template class TActual< T >;
|
|
#endif
|
|
|
|
//NOTE: the file macro will only emit the full path if /FC option is used in visual studio or /ZI (Which forces /FC)
|
|
#define REGISTERCLASS( T ) REGISTERBASE( T, false, false )
|
|
|
|
#define REGISTERSINGLETON( T, bIsAutoConstructSingleton ) REGISTERBASE( T, true, bIsAutoConstructSingleton )
|
|
|
|
|
|
#endif // OBJECTINTERFACEPERMODULE_INCLUDED
|