I'm setting up a concurrent-tasks-based engine, built over tbb, and I have this separate thread with the Ogre-related stuffs running.
So far so good, everything works as expected as far as no code is using Ogre outside of this thread.
The thing is, with Ogre classes being accessible globally because of the static accessors in the Singleton class, it is too easy to get in trouble. It should not be a problem most of the time, but it's better if the compiler can check that you are not accessing data that you shouldn't, as much as it can.
So I was considering this: making Ogre::Singleton class static accessors optional, removed by a simple CMake option for users who don't want global access.
First it would allow me to provide the Ogre::Root instance only to systems/code/functions that are supposed to modify something in the graphic rendering. This would be very very useful to me as it would make impossible for most of my code to try to access Ogre systems outside the graphic thread. Inside the graphic thread, I have a loop wich execute tasks (extended functors basically) which then could take the Ogre::Root instance as parameter:
Code: Select all
void my_graphic_function( Ogre::Root& ogre )
{
// ... do something that can only be executed in the graphic thread
}
void GraphicEngine::main_loop() // GraphicEngine is the only object that owns the Ogre::Root instance, and is singleton itself (but not global access)
{
while( is_running() )
{
task_list.execute( ogre_root ); // this will execute a list of graphic tasks that are objects which have a execute( Ogre::Root& ) function.
}
}
Second, from what I understand, it is possible to do this without impacting concurrent loading. However, I couldn't try this (because of an obscure problem I have with tbb+Ogre, but I'll get to this another time).
Third, I tried a first simple implementation of this idea:
Code: Select all
diff -r 1a6e4cfcb9b9 CMake/ConfigureBuild.cmake
--- a/CMake/ConfigureBuild.cmake Fri Aug 17 21:21:32 2012 +0200
+++ b/CMake/ConfigureBuild.cmake Sun Sep 23 01:48:57 2012 +0200
@@ -85,6 +85,8 @@
set(OGRE_STATIC_LIB 0)
set(OGRE_SET_USE_BOOST 0)
set(OGRE_SET_PROFILING 0)
+set(OGRE_SET_SINGLETON_GLOBAL_ACCESS 1)
+
if (OGRE_CONFIG_DOUBLE)
set(OGRE_SET_DOUBLE 1)
endif()
@@ -133,6 +135,9 @@
if (OGRE_PROFILING)
set(OGRE_SET_PROFILING 1)
endif()
+if (NOT OGRE_CONFIG_SINGLETON_GLOBAL_ACCESS)
+ set(OGRE_SET_SINGLETON_GLOBAL_ACCESS 0)
+endif()
if (OGRE_TEST_BIG_ENDIAN)
set(OGRE_CONFIG_BIG_ENDIAN 1)
diff -r 1a6e4cfcb9b9 CMake/Templates/OgreBuildSettings.h.in
--- a/CMake/Templates/OgreBuildSettings.h.in Fri Aug 17 21:21:32 2012 +0200
+++ b/CMake/Templates/OgreBuildSettings.h.in Sun Sep 23 01:48:57 2012 +0200
@@ -55,6 +55,8 @@
#define OGRE_PROFILING @OGRE_SET_PROFILING@
+#define OGRE_SINGLETON_GLOBAL_ACCESS @OGRE_SET_SINGLETON_GLOBAL_ACCESS@
+
#cmakedefine RTSHADER_SYSTEM_BUILD_CORE_SHADERS
#cmakedefine RTSHADER_SYSTEM_BUILD_EXT_SHADERS
diff -r 1a6e4cfcb9b9 CMakeLists.txt
--- a/CMakeLists.txt Fri Aug 17 21:21:32 2012 +0200
+++ b/CMakeLists.txt Sun Sep 23 01:48:57 2012 +0200
@@ -329,6 +329,9 @@
option(OGRE_UNITY_BUILD "Enable unity build for Ogre." FALSE)
set(OGRE_UNITY_FILES_PER_UNIT "50" CACHE STRING "Number of files per compilation unit in Unity build.")
+# Utility options
+option(OGRE_CONFIG_SINGLETON_GLOBAL_ACCESS "Ogre singletons are available globally for the client code (using getSingleton() static functions)." TRUE)
+
# hide advanced options
mark_as_advanced(
OGRE_BUILD_RTSHADERSYSTEM_CORE_SHADERS
diff -r 1a6e4cfcb9b9 OgreMain/include/OgreSingleton.h
--- a/OgreMain/include/OgreSingleton.h Fri Aug 17 21:21:32 2012 +0200
+++ b/OgreMain/include/OgreSingleton.h Sun Sep 23 01:48:57 2012 +0200
@@ -87,10 +87,14 @@
}
~Singleton( void )
{ assert( msSingleton ); msSingleton = 0; }
+
+ // Provide global access functions only if requested or if it's Ogre code that is compiled.
+#if OGRE_SINGLETON_GLOBAL_ACCESS == 1 || defined( OGRE_NONCLIENT_BUILD )
static T& getSingleton( void )
{ assert( msSingleton ); return ( *msSingleton ); }
static T* getSingletonPtr( void )
{ return msSingleton; }
+#endif
};
/** @} */
/** @} */
This basically add an option to set or not global access of Ogre's singleton. It's set to true by default, like the current implementation.
If you look in details, you'll see that Ogre's code will compile with the accessors enabled, which makes it really a simple change.
So I tried to compile this and in my setup only the OpenGL rendersystem doe snot compile. I don't have all projects enabled so I don't know if DX rendersystem does not compile but I guess that yes as Cabalistic pointed before that rendersystems needs to access Ogre's root too. Here is a screenshot of all the Ogre related projects I'm compiling with:
Only RenderSystem_GL don't compile because of Ogre::Singleton accesses.
To my surprise, all other projects compiles fine, including Ogre Procedural.
Now, I wanted to see what you think guys about this?
To solve the plugins or component's or addons systems compilation to be backward compatible, a simple simple solution would be to add another define that would have to be used by any Ogre's extension source, like OGRE_EXTENSION_SOURCE, that would be checked in the same way and would automatically enable access to the global accessors. I think it's ok that Ogre-specific code have access globally to the singletons, it's only to isolate them from the client code that it's useful to disable the global access.
This solution seems good to me but it's 2 in the morning so maybe not.
Maybe there is a better solution?
What do you think?
Is a patch that would provide this option and also add the OGRE_EXTENSION_SOURCE to Ogre's plugins and components project definitions would be interesting for Ogre team? If yes, then I'll provide it ASAP and the only additional thing would be to test the patch and also notify addon maker about the necessary define to setup on ogre addon projects.