Browse Source

Introduce BUILD_MULTITHREADED CMake option.

Enabled by default, makes the current Magnum context a thread-local
variable instead of a global one, so it's possible to have multiple
thread-local contexts. Might have some performance implications, that's
why it's possible to disable it (but enabled by default is the safer
option).

GCC 4.7 and Apple platforms don't support thread_local, but __thread
does the job too (though on iOS not until Xcode 7.3). Also had to move
it to file-local because MSVC doesn't like having thread local variables
as part of DLL interface. (And there is *of course* no way to disable
exporting one particular member. F' that.)
pull/158/head
Vladimír Vondruš 10 years ago
parent
commit
51cf1d6120
  1. 5
      CMakeLists.txt
  2. 9
      doc/building.dox
  3. 2
      doc/cmake.dox
  4. 3
      modules/FindMagnum.cmake
  5. 7
      package/ci/travis.yml
  6. 25
      src/Magnum/Context.cpp
  7. 8
      src/Magnum/Context.h
  8. 10
      src/Magnum/Magnum.h
  9. 3
      src/Magnum/Platform/magnum-info.cpp
  10. 1
      src/Magnum/configure.h.cmake

5
CMakeLists.txt

@ -138,6 +138,11 @@ if(BUILD_DEPRECATED)
set(MAGNUM_BUILD_DEPRECATED 1)
endif()
option(BUILD_MULTITHREADED "Build in a way that makes it possible to use multiple thread-local Magnum contexts" ON)
if(BUILD_MULTITHREADED)
set(MAGNUM_BUILD_MULTITHREADED 1)
endif()
option(BUILD_STATIC "Build static libraries (default are shared)" OFF)
option(BUILD_STATIC_PIC "Build static libraries and plugins with position-independent code" ON)
option(BUILD_PLUGINS_STATIC "Build static plugins (default are dynamic)" OFF)

9
doc/building.dox

@ -173,6 +173,11 @@ available for desktop OpenGL only, see @ref requires-gl.
Supported mainly on OpenGL ES drivers, for desktop OpenGL the only driver
that supports this configuration is NVidia >= 355.
By default the engine is built in a way that allows having multiple
thread-local Magnum contents. This might cause some performance penalties -- if
you are sure that you will never need such feature, you can disable it via the
`BUILD_MULTITHREADED` option.
The features used can be conveniently detected in depending projects both in
CMake and C++ sources, see @ref cmake and @ref Magnum/Magnum.h for more
information. See also @ref corrade-cmake and @ref Corrade/Corrade.h for
@ -542,6 +547,10 @@ static libraries. You might also have problems using dynamic plugins, enable
`BUILD_PLUGINS_STATIC` to build also plugins as static. OpenGL ES 2.0 is
enabled by default, switch to 3.0 by disabling `TARGET_GLES2`.
Please note that `BUILD_MULTITHREADED` is supported only since Xcode 7.3 and
doesn't work on `i386` iOS Simulator, you need to disable it in order to build
for older platforms.
mkdir build-ios && cd build-ios
cmake .. \
-DCMAKE_TOOLCHAIN_FILE=../toolchains/generic/iOS.cmake \

2
doc/cmake.dox

@ -180,6 +180,8 @@ are also available as preprocessor variables if including
included
- `MAGNUM_BUILD_STATIC` -- Defined if compiled as static libraries. Default
are shared libraries.
- `MAGNUM_BUILD_MULTITHREADED` -- Defined if compiled in a way that allows
having multiple thread-local Magnum contexts. The default.
- `MAGNUM_TARGET_GLES` -- Defined if compiled for OpenGL ES
- `MAGNUM_TARGET_GLES2` -- Defined if compiled for OpenGL ES 2.0
- `MAGNUM_TARGET_GLES3` -- Defined if compiled for OpenGL ES 3.0

3
modules/FindMagnum.cmake

@ -105,6 +105,8 @@
# MAGNUM_BUILD_DEPRECATED - Defined if compiled with deprecated APIs
# included
# MAGNUM_BUILD_STATIC - Defined if compiled as static libraries
# MAGNUM_BUILD_MULTITHREADED - Defined if compiled in a way that allows
# having multiple thread-local Magnum contexts
# MAGNUM_TARGET_GLES - Defined if compiled for OpenGL ES
# MAGNUM_TARGET_GLES2 - Defined if compiled for OpenGL ES 2.0
# MAGNUM_TARGET_GLES3 - Defined if compiled for OpenGL ES 3.0
@ -206,6 +208,7 @@ file(READ ${_MAGNUM_CONFIGURE_FILE} _magnumConfigure)
set(_magnumFlags
BUILD_DEPRECATED
BUILD_STATIC
BUILD_MULTITHREADED
TARGET_GLES
TARGET_GLES2
TARGET_GLES3

7
package/ci/travis.yml

@ -14,10 +14,12 @@ matrix:
compiler: clang
env: TARGET=desktop
- os: osx
osx_image: xcode7.3
env:
- TARGET=ios-simulator
- TARGET_GLES2=ON
- os: osx
osx_image: xcode7.3
env:
- TARGET=ios-simulator
- TARGET_GLES2=OFF
@ -59,13 +61,14 @@ install:
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then export PLATFORM_GL_API=GLX; fi
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then export PLATFORM_GL_API=CGL; fi
- if [ "$TRAVIS_OS_NAME" == "osx" ] && [ "$TARGET" == "ios-simulator" ]; then gem install xcpretty; fi
- if [ "$TRAVIS_OS_NAME" == "osx" ] && [ "$TARGET" == "ios-simulator" ]; then brew upgrade cmake; fi
# Xcode 7.2 image doesn't have cmake installed using Homebrew, so we can't use `upgrade`
- if [ "$TRAVIS_OS_NAME" == "osx" ] && [ "$TARGET" == "ios-simulator" ]; then brew install cmake; fi
- if [ "$TRAVIS_OS_NAME" == "osx" ] && [ "$TARGET" == "emscripten" ]; then brew install emscripten && export LLVM=/usr/local/opt/emscripten/libexec/llvm/bin && emcc; fi
- if [ "$TARGET" == "desktop" ]; then printf "[General]\ndrivers=null" > ~/.alsoftrc; fi
# SDL (cached)
- if [ "$TRAVIS_OS_NAME" == "osx" ] && [ "$TARGET" == "desktop" ]; then brew install sdl2; fi
- if [ "$TRAVIS_OS_NAME" == "osx" ] && [ "$TARGET" == "ios-simulator" ]; then curl -O https://www.libsdl.org/release/SDL2-2.0.4.tar.gz && tar -xzvf SDL2-2.0.4.tar.gz && cd SDL2-2.0.4/Xcode-iOS/SDL && xcodebuild -sdk iphonesimulator8.1 | xcpretty && mkdir -p ../../../sdl2/lib && cp build/Release-iphonesimulator/libSDL2.a ../../../sdl2/lib && mkdir -p ../../../sdl2/include/SDL2 && cp -R ../../include/* ../../../sdl2/include/SDL2 && cd ../../..; fi
- if [ "$TRAVIS_OS_NAME" == "osx" ] && [ "$TARGET" == "ios-simulator" ]; then curl -O https://www.libsdl.org/release/SDL2-2.0.4.tar.gz && tar -xzvf SDL2-2.0.4.tar.gz && cd SDL2-2.0.4/Xcode-iOS/SDL && xcodebuild -sdk iphonesimulator9.3 | xcpretty && mkdir -p ../../../sdl2/lib && cp build/Release-iphonesimulator/libSDL2.a ../../../sdl2/lib && mkdir -p ../../../sdl2/include/SDL2 && cp -R ../../include/* ../../../sdl2/include/SDL2 && cd ../../..; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ] && [ ! -e "$HOME/sdl2/include" ]; then curl -O http://www.libsdl.org/release/SDL2-2.0.4.tar.gz && tar -xzvf SDL2-2.0.4.tar.gz && cd SDL2-2.0.4 && mkdir build && cd build && cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/sdl2 -DCMAKE_BUILD_TYPE=Release && cmake --build . --target install && cd ../..; fi
# GLFW (cached)

25
src/Magnum/Context.cpp

@ -409,13 +409,22 @@ const std::vector<Extension>& Extension::extensions(Version version) {
CORRADE_ASSERT_UNREACHABLE();
}
Context* Context::_current = nullptr;
namespace {
#ifdef MAGNUM_BUILD_MULTITHREADED
#if !defined(CORRADE_GCC47_COMPATIBILITY) && !defined(CORRADE_TARGET_APPLE)
thread_local
#else
__thread
#endif
#endif
Context* currentContext = nullptr;
}
bool Context::hasCurrent() { return _current; }
bool Context::hasCurrent() { return currentContext; }
Context& Context::current() {
CORRADE_ASSERT(_current, "Context::current(): no current context", *_current);
return *_current;
CORRADE_ASSERT(currentContext, "Context::current(): no current context", *currentContext);
return *currentContext;
}
Context::Context(NoCreateT, Int argc, char** argv, void functionLoader()): _functionLoader{functionLoader}, _version{Version::None} {
@ -448,13 +457,13 @@ Context::Context(Context&& other): _version{std::move(other._version)},
_detectedDrivers{std::move(other._detectedDrivers)}
{
other._state = nullptr;
if(_current == &other) _current = this;
if(currentContext == &other) currentContext = this;
}
Context::~Context() {
delete _state;
if(_current == this) _current = nullptr;
if(currentContext == this) currentContext = nullptr;
}
void Context::create() {
@ -640,8 +649,8 @@ bool Context::tryCreate() {
setupDriverWorkarounds();
/* Set this context as current */
CORRADE_ASSERT(!_current, "Context: Another context currently active", false);
_current = this;
CORRADE_ASSERT(!currentContext, "Context: Another context currently active", false);
currentContext = this;
/* Print some info and initialize state tracker (which also prints some
more info) */

8
src/Magnum/Context.h

@ -244,6 +244,8 @@ class MAGNUM_EXPORT Context {
/**
* @brief Whether there is any current context
*
* If Magnum is built with @ref MAGNUM_BUILD_MULTITHREADED, current
* context is thread-local instead of global (the default).
* @see @ref current()
*/
static bool hasCurrent();
@ -251,7 +253,9 @@ class MAGNUM_EXPORT Context {
/**
* @brief Current context
*
* Expect that there is current context.
* Expect that there is current context. If Magnum is built with
* @ref MAGNUM_BUILD_MULTITHREADED, current context is thread-local
* instead of global (the default).
* @see @ref hasCurrent()
*/
static Context& current();
@ -501,8 +505,6 @@ class MAGNUM_EXPORT Context {
Implementation::State& state() { return *_state; }
private:
MAGNUM_LOCAL static Context* _current;
explicit Context(NoCreateT, Int argc, char** argv, void functionLoader());
bool tryCreate();

10
src/Magnum/Magnum.h

@ -91,6 +91,16 @@ Defined if built as static libraries. Default are shared libraries.
#define MAGNUM_BUILD_STATIC
#undef MAGNUM_BUILD_STATIC
/**
@brief Multi-threaded build
Defined if the library is built in a way that allows multiple thread-local
Magnum contexts. Enabled by default.
@see @ref building, @ref cmake, @ref Context::current()
*/
#define MAGNUM_BUILD_MULTITHREADED
#undef MAGNUM_BUILD_MULTITHREADED
/**
@brief OpenGL ES target

3
src/Magnum/Platform/magnum-info.cpp

@ -246,6 +246,9 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
#ifdef MAGNUM_BUILD_STATIC
Debug() << " MAGNUM_BUILD_STATIC";
#endif
#ifdef MAGNUM_BUILD_MULTITHREADED
Debug() << " MAGNUM_BUILD_MULTITHREADED";
#endif
#ifdef MAGNUM_TARGET_GLES
Debug() << " MAGNUM_TARGET_GLES";
#endif

1
src/Magnum/configure.h.cmake

@ -25,6 +25,7 @@
#cmakedefine MAGNUM_BUILD_DEPRECATED
#cmakedefine MAGNUM_BUILD_STATIC
#cmakedefine MAGNUM_BUILD_MULTITHREADED
#cmakedefine MAGNUM_TARGET_GLES
#cmakedefine MAGNUM_TARGET_GLES2
#cmakedefine MAGNUM_TARGET_GLES3

Loading…
Cancel
Save