From 0c60538952e82a3b0ce5afe338ca490ec88048ee Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 2 Nov 2015 17:47:02 -0800 Subject: [PATCH 1/4] Ensure that dependencies of runtime plugins are included in the DLL copy --- cmake/macros/CopyDllsBesideWindowsExecutable.cmake | 7 +++++++ cmake/templates/FixupBundlePostBuild.cmake.in | 14 +++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake index b57c781eff..69fd20a57b 100644 --- a/cmake/macros/CopyDllsBesideWindowsExecutable.cmake +++ b/cmake/macros/CopyDllsBesideWindowsExecutable.cmake @@ -18,12 +18,19 @@ macro(COPY_DLLS_BESIDE_WINDOWS_EXECUTABLE) @ONLY ) + if (APPLE) + set(PLUGIN_PATH "interface.app/Contents/MacOS/plugins") + else() + set(PLUGIN_PATH "plugins") + endif() + # add a post-build command to copy DLLs beside the executable add_custom_command( TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -DBUNDLE_EXECUTABLE=$ + -DBUNDLE_PLUGIN_DIR=$/${PLUGIN_PATH} -P ${CMAKE_CURRENT_BINARY_DIR}/FixupBundlePostBuild.cmake ) diff --git a/cmake/templates/FixupBundlePostBuild.cmake.in b/cmake/templates/FixupBundlePostBuild.cmake.in index 4afe4de403..ee686a6967 100644 --- a/cmake/templates/FixupBundlePostBuild.cmake.in +++ b/cmake/templates/FixupBundlePostBuild.cmake.in @@ -41,4 +41,16 @@ function(copy_resolved_item_into_bundle resolved_item resolved_embedded_item) endfunction() message(STATUS "FIXUP_LIBS for fixup_bundle called for bundle ${BUNDLE_EXECUTABLE} are @FIXUP_LIBS@") -fixup_bundle("${BUNDLE_EXECUTABLE}" "" "@FIXUP_LIBS@") \ No newline at end of file + +message(STATUS "Scanning for plugins from ${BUNDLE_PLUGIN_DIR}") + +if (APPLE) + set(PLUGIN_EXTENSION "dylib") +elseif (WIN32) + set(PLUGIN_EXTENSION "dll") +else() + set(PLUGIN_EXTENSION "so") +endif() + +file(GLOB RUNTIME_PLUGINS "${BUNDLE_PLUGIN_DIR}/*.${PLUGIN_EXTENSION}") +fixup_bundle("${BUNDLE_EXECUTABLE}" "${RUNTIME_PLUGINS}" "@FIXUP_LIBS@") \ No newline at end of file From 11733c039f5311c09de192e76d286cd9298f7269 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 2 Nov 2015 17:16:28 -0800 Subject: [PATCH 2/4] Allow shared libraries to access core global objects --- interface/src/Menu.cpp | 17 +++---------- interface/src/Menu.h | 4 +--- libraries/shared/src/DependencyManager.cpp | 9 ++++++- libraries/shared/src/DependencyManager.h | 22 ++++++++--------- libraries/shared/src/SharedUtil.h | 28 +++++++++++++++++++++- 5 files changed, 50 insertions(+), 30 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 92ff39a489..2d60b9d79f 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -44,22 +44,11 @@ #include "Menu.h" -Menu* Menu::_instance = NULL; +static const char* const MENU_PROPERTY_NAME = "com.highfidelity.Menu"; Menu* Menu::getInstance() { - static QMutex menuInstanceMutex; - - // lock the menu instance mutex to make sure we don't race and create two menus and crash - menuInstanceMutex.lock(); - - if (!_instance) { - qCDebug(interfaceapp, "First call to Menu::getInstance() - initing menu."); - _instance = new Menu(); - } - - menuInstanceMutex.unlock(); - - return _instance; + static Menu& instance = globalInstace(MENU_PROPERTY_NAME); + return &instance; } Menu::Menu() { diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 162fad1b9f..dfa2cfa41b 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -57,6 +57,7 @@ private: class Menu : public QMenuBar { Q_OBJECT public: + Menu(); static Menu* getInstance(); void loadSettings(); @@ -103,9 +104,6 @@ public slots: void setIsOptionChecked(const QString& menuOption, bool isChecked); private: - static Menu* _instance; - Menu(); - typedef void(*settingsAction)(Settings&, QAction&); static void loadAction(Settings& settings, QAction& action); static void saveAction(Settings& settings, QAction& action); diff --git a/libraries/shared/src/DependencyManager.cpp b/libraries/shared/src/DependencyManager.cpp index 5f78f6bcd5..54d4e08259 100644 --- a/libraries/shared/src/DependencyManager.cpp +++ b/libraries/shared/src/DependencyManager.cpp @@ -11,7 +11,14 @@ #include "DependencyManager.h" -DependencyManager DependencyManager::_manager; +#include "SharedUtil.h" + +static const char* const DEPENDENCY_PROPERTY_NAME = "com.highfidelity.DependencyMananger"; + +DependencyManager& DependencyManager::manager() { + static DependencyManager& instance = globalInstace(DEPENDENCY_PROPERTY_NAME); + return instance; +} QSharedPointer& DependencyManager::safeGet(size_t hashCode) { return _instanceHash[hashCode]; diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h index db41e72e1e..c0568bc752 100644 --- a/libraries/shared/src/DependencyManager.h +++ b/libraries/shared/src/DependencyManager.h @@ -62,8 +62,8 @@ public: static void registerInheritance(); private: - static DependencyManager _manager; - + static DependencyManager& manager(); + template size_t getHashCode(); @@ -75,11 +75,11 @@ private: template QSharedPointer DependencyManager::get() { - static size_t hashCode = _manager.getHashCode(); + static size_t hashCode = manager().getHashCode(); static QWeakPointer instance; if (instance.isNull()) { - instance = qSharedPointerCast(_manager.safeGet(hashCode)); + instance = qSharedPointerCast(manager().safeGet(hashCode)); if (instance.isNull()) { qWarning() << "DependencyManager::get(): No instance available for" << typeid(T).name(); @@ -91,9 +91,9 @@ QSharedPointer DependencyManager::get() { template QSharedPointer DependencyManager::set(Args&&... args) { - static size_t hashCode = _manager.getHashCode(); + static size_t hashCode = manager().getHashCode(); - QSharedPointer& instance = _manager.safeGet(hashCode); + QSharedPointer& instance = manager().safeGet(hashCode); instance.clear(); // Clear instance before creation of new one to avoid edge cases QSharedPointer newInstance(new T(args...), &T::customDeleter); QSharedPointer storedInstance = qSharedPointerCast(newInstance); @@ -104,9 +104,9 @@ QSharedPointer DependencyManager::set(Args&&... args) { template QSharedPointer DependencyManager::set(Args&&... args) { - static size_t hashCode = _manager.getHashCode(); + static size_t hashCode = manager().getHashCode(); - QSharedPointer& instance = _manager.safeGet(hashCode); + QSharedPointer& instance = manager().safeGet(hashCode); instance.clear(); // Clear instance before creation of new one to avoid edge cases QSharedPointer newInstance(new I(args...), &I::customDeleter); QSharedPointer storedInstance = qSharedPointerCast(newInstance); @@ -117,15 +117,15 @@ QSharedPointer DependencyManager::set(Args&&... args) { template void DependencyManager::destroy() { - static size_t hashCode = _manager.getHashCode(); - _manager.safeGet(hashCode).clear(); + static size_t hashCode = manager().getHashCode(); + manager().safeGet(hashCode).clear(); } template void DependencyManager::registerInheritance() { size_t baseHashCode = typeid(Base).hash_code(); size_t derivedHashCode = typeid(Derived).hash_code(); - _manager._inheritanceHash.insert(baseHashCode, derivedHashCode); + manager()._inheritanceHash.insert(baseHashCode, derivedHashCode); } template diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index cd4f734d40..4c547417c8 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -13,6 +13,7 @@ #define hifi_SharedUtil_h #include +#include #include #include @@ -20,7 +21,32 @@ #include // not on windows, not needed for mac or windows #endif -#include +#include +#include + +// Provides efficient access to a named global type. By storing the value +// in the QApplication by name we can implement the singleton pattern and +// have the single instance function across DLL boundaries. +template +T& globalInstace(const char* propertyName, Args&&... args) { + static T *instance { nullptr }; + static std::mutex mutex; + if (!instance) { + std::unique_lock lock(mutex); + if (!instance) { + auto variant = qApp->property(propertyName); + if (variant.isNull()) { + auto* typedInstance = new T(args...); + void* voidInstance = typedInstance; + variant = QVariant::fromValue(voidInstance); + qApp->setProperty(propertyName, variant); + } + void* returnedVoidInstance = variant.value(); + instance = static_cast(returnedVoidInstance); + } + } + return *instance; +} const int BYTES_PER_COLOR = 3; const int BYTES_PER_FLAGS = 1; From 37a9538f104b6efec4b7cfc34f9474c6ba746be4 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 4 Nov 2015 19:10:31 -0800 Subject: [PATCH 3/4] PR feedback, ensure destruction of shared objects --- interface/src/Menu.cpp | 4 ++-- libraries/shared/src/DependencyManager.cpp | 5 +++-- libraries/shared/src/SharedUtil.h | 19 +++++++++++-------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 2d60b9d79f..3ed31e609a 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -47,8 +47,8 @@ static const char* const MENU_PROPERTY_NAME = "com.highfidelity.Menu"; Menu* Menu::getInstance() { - static Menu& instance = globalInstace(MENU_PROPERTY_NAME); - return &instance; + static Menu* instance = globalInstace(MENU_PROPERTY_NAME); + return instance; } Menu::Menu() { diff --git a/libraries/shared/src/DependencyManager.cpp b/libraries/shared/src/DependencyManager.cpp index 54d4e08259..5100d99691 100644 --- a/libraries/shared/src/DependencyManager.cpp +++ b/libraries/shared/src/DependencyManager.cpp @@ -12,12 +12,13 @@ #include "DependencyManager.h" #include "SharedUtil.h" +#include "Finally.h" static const char* const DEPENDENCY_PROPERTY_NAME = "com.highfidelity.DependencyMananger"; DependencyManager& DependencyManager::manager() { - static DependencyManager& instance = globalInstace(DEPENDENCY_PROPERTY_NAME); - return instance; + static DependencyManager* instance = globalInstace(DEPENDENCY_PROPERTY_NAME); + return *instance; } QSharedPointer& DependencyManager::safeGet(size_t hashCode) { diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 4c547417c8..097444a62c 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -28,24 +28,27 @@ // in the QApplication by name we can implement the singleton pattern and // have the single instance function across DLL boundaries. template -T& globalInstace(const char* propertyName, Args&&... args) { - static T *instance { nullptr }; +T* globalInstace(const char* propertyName, Args&&... args) { + static std::shared_ptr instancePtr; + static T *resultInstance { nullptr }; static std::mutex mutex; - if (!instance) { + if (!resultInstance) { std::unique_lock lock(mutex); - if (!instance) { + if (!resultInstance) { auto variant = qApp->property(propertyName); if (variant.isNull()) { - auto* typedInstance = new T(args...); - void* voidInstance = typedInstance; + // Since we're building the object, store it in a shared_ptr so it's + // destroyed by the destructor of the static instancePtr + instancePtr = std::make_shared(args...); + void* voidInstance = &(*instancePtr); variant = QVariant::fromValue(voidInstance); qApp->setProperty(propertyName, variant); } void* returnedVoidInstance = variant.value(); - instance = static_cast(returnedVoidInstance); + resultInstance = static_cast(returnedVoidInstance); } } - return *instance; + return resultInstance; } const int BYTES_PER_COLOR = 3; From 6122fa145db9beadb66581223c80a48cc11901fc Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 6 Nov 2015 17:02:56 -0800 Subject: [PATCH 4/4] More PR feedback --- interface/src/Menu.cpp | 2 +- libraries/shared/src/DependencyManager.cpp | 4 ++-- libraries/shared/src/SharedUtil.h | 11 ++++++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 3ed31e609a..24033325f6 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -47,7 +47,7 @@ static const char* const MENU_PROPERTY_NAME = "com.highfidelity.Menu"; Menu* Menu::getInstance() { - static Menu* instance = globalInstace(MENU_PROPERTY_NAME); + static Menu* instance = globalInstance(MENU_PROPERTY_NAME); return instance; } diff --git a/libraries/shared/src/DependencyManager.cpp b/libraries/shared/src/DependencyManager.cpp index 5100d99691..a870feab98 100644 --- a/libraries/shared/src/DependencyManager.cpp +++ b/libraries/shared/src/DependencyManager.cpp @@ -17,10 +17,10 @@ static const char* const DEPENDENCY_PROPERTY_NAME = "com.highfidelity.DependencyMananger"; DependencyManager& DependencyManager::manager() { - static DependencyManager* instance = globalInstace(DEPENDENCY_PROPERTY_NAME); + static DependencyManager* instance = globalInstance(DEPENDENCY_PROPERTY_NAME); return *instance; } QSharedPointer& DependencyManager::safeGet(size_t hashCode) { return _instanceHash[hashCode]; -} \ No newline at end of file +} diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 097444a62c..89ccba1479 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -27,10 +27,10 @@ // Provides efficient access to a named global type. By storing the value // in the QApplication by name we can implement the singleton pattern and // have the single instance function across DLL boundaries. -template -T* globalInstace(const char* propertyName, Args&&... args) { - static std::shared_ptr instancePtr; - static T *resultInstance { nullptr }; +template +T* globalInstance(const char* propertyName, Args&&... args) { + static std::unique_ptr instancePtr; + static T* resultInstance { nullptr }; static std::mutex mutex; if (!resultInstance) { std::unique_lock lock(mutex); @@ -39,7 +39,8 @@ T* globalInstace(const char* propertyName, Args&&... args) { if (variant.isNull()) { // Since we're building the object, store it in a shared_ptr so it's // destroyed by the destructor of the static instancePtr - instancePtr = std::make_shared(args...); + instancePtr = std::unique_ptr(new T(std::forward(args)...)); + void* voidInstance = &(*instancePtr); variant = QVariant::fromValue(voidInstance); qApp->setProperty(propertyName, variant);