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 diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 92ff39a489..24033325f6 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 = globalInstance(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..a870feab98 100644 --- a/libraries/shared/src/DependencyManager.cpp +++ b/libraries/shared/src/DependencyManager.cpp @@ -11,8 +11,16 @@ #include "DependencyManager.h" -DependencyManager DependencyManager::_manager; +#include "SharedUtil.h" +#include "Finally.h" + +static const char* const DEPENDENCY_PROPERTY_NAME = "com.highfidelity.DependencyMananger"; + +DependencyManager& DependencyManager::manager() { + 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/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..89ccba1479 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,36 @@ #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* 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); + if (!resultInstance) { + auto variant = qApp->property(propertyName); + 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::unique_ptr(new T(std::forward(args)...)); + + void* voidInstance = &(*instancePtr); + variant = QVariant::fromValue(voidInstance); + qApp->setProperty(propertyName, variant); + } + void* returnedVoidInstance = variant.value(); + resultInstance = static_cast(returnedVoidInstance); + } + } + return resultInstance; +} const int BYTES_PER_COLOR = 3; const int BYTES_PER_FLAGS = 1;