diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index f517716b72..1dc3aefb61 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -166,11 +166,7 @@ void Agent::run() { // Setup MessagesClient auto messagesClient = DependencyManager::set(); - QThread* messagesThread = new QThread; - messagesThread->setObjectName("Messages Client Thread"); - messagesClient->moveToThread(messagesThread); - connect(messagesThread, &QThread::started, messagesClient.data(), &MessagesClient::init); - messagesThread->start(); + messagesClient->startThread(); // make sure we hear about connected nodes so we can grab an ATP script if a request is pending connect(nodeList.data(), &LimitedNodeList::nodeActivated, this, &Agent::nodeActivated); diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 0869329d68..abfc66ac55 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -69,17 +69,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri DependencyManager::set(); DependencyManager::set(); - // setup a thread for the NodeList and its PacketReceiver - QThread* nodeThread = new QThread(this); - nodeThread->setObjectName("NodeList Thread"); - nodeThread->start(); - - // make sure the node thread is given highest priority - nodeThread->setPriority(QThread::TimeCriticalPriority); - - // put the NodeList on the node thread - nodeList->moveToThread(nodeThread); - + nodeList->startThread(); // set the logging target to the the CHILD_TARGET_NAME LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME); @@ -166,14 +156,8 @@ void AssignmentClient::stopAssignmentClient() { } AssignmentClient::~AssignmentClient() { - QThread* nodeThread = DependencyManager::get()->thread(); - // remove the NodeList from the DependencyManager DependencyManager::destroy(); - - // ask the node thread to quit and wait until it is done - nodeThread->quit(); - nodeThread->wait(); } void AssignmentClient::aboutToQuit() { diff --git a/assignment-client/src/audio/AudioMixerSlavePool.h b/assignment-client/src/audio/AudioMixerSlavePool.h index 4082ea18d9..25047faa89 100644 --- a/assignment-client/src/audio/AudioMixerSlavePool.h +++ b/assignment-client/src/audio/AudioMixerSlavePool.h @@ -16,10 +16,10 @@ #include #include -#include - #include +#include + #include "AudioMixerSlave.h" class AudioMixerSlavePool; diff --git a/assignment-client/src/avatars/AvatarMixerSlavePool.h b/assignment-client/src/avatars/AvatarMixerSlavePool.h index e6ac2a1f4e..15bd681b2c 100644 --- a/assignment-client/src/avatars/AvatarMixerSlavePool.h +++ b/assignment-client/src/avatars/AvatarMixerSlavePool.h @@ -16,10 +16,9 @@ #include #include -#include - #include +#include #include #include "AvatarMixerSlave.h" diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 270a22e17b..1b226ab642 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -236,11 +236,7 @@ void EntityScriptServer::run() { // Setup MessagesClient auto messagesClient = DependencyManager::set(); - QThread* messagesThread = new QThread; - messagesThread->setObjectName("Messages Client Thread"); - messagesClient->moveToThread(messagesThread); - connect(messagesThread, &QThread::started, messagesClient.data(), &MessagesClient::init); - messagesThread->start(); + messagesClient->startThread(); DomainHandler& domainHandler = DependencyManager::get()->getDomainHandler(); connect(&domainHandler, &DomainHandler::settingsReceived, this, &EntityScriptServer::handleSettings); diff --git a/gvr-interface/src/RenderingClient.cpp b/gvr-interface/src/RenderingClient.cpp index e6d2f6b585..b7c6f30a73 100644 --- a/gvr-interface/src/RenderingClient.cpp +++ b/gvr-interface/src/RenderingClient.cpp @@ -37,20 +37,12 @@ RenderingClient::RenderingClient(QObject *parent, const QString& launchURLString DependencyManager::set(); // get our audio client setup on its own thread - QThread* audioThread = new QThread(); auto audioClient = DependencyManager::set(); - audioClient->setPositionGetter(getPositionForAudio); audioClient->setOrientationGetter(getOrientationForAudio); + audioClient->startThread(); - audioClient->moveToThread(audioThread); - connect(audioThread, &QThread::started, audioClient.data(), &AudioClient::start); - connect(audioClient.data(), &AudioClient::destroyed, audioThread, &QThread::quit); - connect(audioThread, &QThread::finished, audioThread, &QThread::deleteLater); - - audioThread->start(); - - + connect(&_avatarTimer, &QTimer::timeout, this, &RenderingClient::sendAvatarPacket); _avatarTimer.setInterval(16); // 60 FPS _avatarTimer.start(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ea5a9c0a89..b949110a2a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -653,6 +653,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo Model::setAbstractViewStateInterface(this); // The model class will sometimes need to know view state details from us auto nodeList = DependencyManager::get(); + nodeList->startThread(); // Set up a watchdog thread to intentionally crash the application on deadlocks _deadlockWatchdogThread = new DeadlockWatchdogThread(); @@ -678,25 +679,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo updateHeartbeat(); - // start the nodeThread so its event loop is running - QThread* nodeThread = new QThread(this); - nodeThread->setObjectName("NodeList Thread"); - nodeThread->start(); - - // make sure the node thread is given highest priority - nodeThread->setPriority(QThread::TimeCriticalPriority); - // setup a timer for domain-server check ins QTimer* domainCheckInTimer = new QTimer(nodeList.data()); connect(domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn); domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); - // put the NodeList and datagram processing on the node thread - nodeList->moveToThread(nodeThread); - - // put the audio processing on a separate thread - QThread* audioThread = new QThread(); - audioThread->setObjectName("Audio Thread"); auto audioIO = DependencyManager::get(); audioIO->setPositionGetter([]{ @@ -712,7 +699,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return myAvatar ? myAvatar->getOrientationForAudio() : Quaternions::IDENTITY; }); - audioIO->moveToThread(audioThread); recording::Frame::registerFrameHandler(AudioConstants::getAudioFrameName(), [=](recording::Frame::ConstPointer frame) { audioIO->handleRecordedAudioInput(frame->data); }); @@ -726,9 +712,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo }); auto audioScriptingInterface = DependencyManager::set(); - connect(audioThread, &QThread::started, audioIO.data(), &AudioClient::start); - connect(audioIO.data(), &AudioClient::destroyed, audioThread, &QThread::quit); - connect(audioThread, &QThread::finished, audioThread, &QThread::deleteLater); connect(audioIO.data(), &AudioClient::muteToggled, this, &Application::audioMuteToggled); connect(audioIO.data(), &AudioClient::mutedByMixer, audioScriptingInterface.data(), &AudioScriptingInterface::mutedByMixer); connect(audioIO.data(), &AudioClient::receivedFirstPacket, audioScriptingInterface.data(), &AudioScriptingInterface::receivedFirstPacket); @@ -746,19 +729,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } }); - audioThread->start(); + audioIO->startThread(); ResourceManager::init(); // Make sure we don't time out during slow operations at startup updateHeartbeat(); // Setup MessagesClient - auto messagesClient = DependencyManager::get(); - QThread* messagesThread = new QThread; - messagesThread->setObjectName("Messages Client Thread"); - messagesClient->moveToThread(messagesThread); - connect(messagesThread, &QThread::started, messagesClient.data(), &MessagesClient::init); - messagesThread->start(); + DependencyManager::get()->startThread(); const DomainHandler& domainHandler = nodeList->getDomainHandler(); @@ -1678,12 +1656,7 @@ void Application::aboutToQuit() { _autoSwitchDisplayModeSupportedHMDPlugin->endSession(); } // use the CloseEventSender via a QThread to send an event that says the user asked for the app to close - auto closeEventSender = DependencyManager::get(); - QThread* closureEventThread = new QThread(this); - closeEventSender->moveToThread(closureEventThread); - // sendQuitEventAsync will bail immediately if the UserActivityLogger is not enabled - connect(closureEventThread, &QThread::started, closeEventSender.data(), &CloseEventSender::sendQuitEventAsync); - closureEventThread->start(); + DependencyManager::get()->startThread(); // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. DependencyManager::get()->hide("RunningScripts"); @@ -1771,6 +1744,8 @@ void Application::cleanupBeforeQuit() { // stop QML DependencyManager::destroy(); + DependencyManager::destroy(); + if (_snapshotSoundInjector != nullptr) { _snapshotSoundInjector->stop(); } @@ -1830,15 +1805,9 @@ Application::~Application() { ResourceManager::cleanup(); - QThread* nodeThread = DependencyManager::get()->thread(); - // remove the NodeList from the DependencyManager DependencyManager::destroy(); - // ask the node thread to quit and wait until it is done - nodeThread->quit(); - nodeThread->wait(); - Leapmotion::destroy(); if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { diff --git a/interface/src/networking/CloseEventSender.cpp b/interface/src/networking/CloseEventSender.cpp index 8c3d6ae888..de8bd897b2 100644 --- a/interface/src/networking/CloseEventSender.cpp +++ b/interface/src/networking/CloseEventSender.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -87,4 +88,8 @@ bool CloseEventSender::hasTimedOutQuitEvent() { && QDateTime::currentMSecsSinceEpoch() - _quitEventStartTimestamp > CLOSURE_EVENT_TIMEOUT_MS; } - +void CloseEventSender::startThread() { + moveToNewNamedThread(this, "CloseEvent Logger Thread", [this] { + sendQuitEventAsync(); + }); +} diff --git a/interface/src/networking/CloseEventSender.h b/interface/src/networking/CloseEventSender.h index 05e6f81ad4..b74412c41c 100644 --- a/interface/src/networking/CloseEventSender.h +++ b/interface/src/networking/CloseEventSender.h @@ -24,6 +24,7 @@ class CloseEventSender : public QObject, public Dependency { SINGLETON_DEPENDENCY public: + void startThread(); bool hasTimedOutQuitEvent(); bool hasFinishedQuitEvent() { return _hasFinishedQuitEvent; } diff --git a/interface/src/scripting/LimitlessVoiceRecognitionScriptingInterface.cpp b/interface/src/scripting/LimitlessVoiceRecognitionScriptingInterface.cpp index 1352630f84..ebb5ca9280 100644 --- a/interface/src/scripting/LimitlessVoiceRecognitionScriptingInterface.cpp +++ b/interface/src/scripting/LimitlessVoiceRecognitionScriptingInterface.cpp @@ -9,9 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + +#include #include #include -#include + #include "LimitlessVoiceRecognitionScriptingInterface.h" const float LimitlessVoiceRecognitionScriptingInterface::_audioLevelThreshold = 0.33f; @@ -24,9 +27,7 @@ LimitlessVoiceRecognitionScriptingInterface::LimitlessVoiceRecognitionScriptingI connect(&_voiceTimer, &QTimer::timeout, this, &LimitlessVoiceRecognitionScriptingInterface::voiceTimeout); connect(&_connection, &LimitlessConnection::onReceivedTranscription, this, [this](QString transcription){emit onReceivedTranscription(transcription);}); connect(&_connection, &LimitlessConnection::onFinishedSpeaking, this, [this](QString transcription){emit onFinishedSpeaking(transcription);}); - _connection.moveToThread(&_connectionThread); - _connectionThread.setObjectName("Limitless Connection"); - _connectionThread.start(); + moveToNewNamedThread(&_connection, "Limitless Connection"); } void LimitlessVoiceRecognitionScriptingInterface::update() { diff --git a/interface/src/scripting/LimitlessVoiceRecognitionScriptingInterface.h b/interface/src/scripting/LimitlessVoiceRecognitionScriptingInterface.h index d1b1139695..2a35c37ab0 100644 --- a/interface/src/scripting/LimitlessVoiceRecognitionScriptingInterface.h +++ b/interface/src/scripting/LimitlessVoiceRecognitionScriptingInterface.h @@ -41,7 +41,6 @@ private: static const int _voiceTimeoutDuration; QTimer _voiceTimer; - QThread _connectionThread; LimitlessConnection _connection; void voiceTimeout(); diff --git a/interface/src/ui/ModelsBrowser.cpp b/interface/src/ui/ModelsBrowser.cpp index 430cc805ed..44089119c6 100644 --- a/interface/src/ui/ModelsBrowser.cpp +++ b/interface/src/ui/ModelsBrowser.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -84,12 +85,7 @@ ModelsBrowser::ModelsBrowser(FSTReader::ModelType modelsType, QWidget* parent) : _handler->connect(this, SIGNAL(destroyed()), SLOT(exit())); // Setup and launch update thread - QThread* thread = new QThread(); - thread->setObjectName("Models Browser"); - thread->connect(_handler, SIGNAL(destroyed()), SLOT(quit())); - thread->connect(thread, SIGNAL(finished()), SLOT(deleteLater())); - _handler->moveToThread(thread); - thread->start(); + moveToNewNamedThread(_handler, "Models Browser"); emit startDownloading(); // Initialize the view diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index e03ca83131..6caa4fb159 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -31,10 +31,13 @@ #include #endif +#include +#include #include #include #include +#include #include #include #include @@ -76,59 +79,6 @@ using Mutex = std::mutex; using Lock = std::unique_lock; static Mutex _deviceMutex; -class BackgroundThread : public QThread { -public: - BackgroundThread(AudioClient* client) : QThread((QObject*)client), _client(client) {} - virtual void join() = 0; -protected: - AudioClient* _client; -}; - -// background thread continuously polling device changes -class CheckDevicesThread : public BackgroundThread { -public: - CheckDevicesThread(AudioClient* client) : BackgroundThread(client) {} - - void join() override { - _shouldQuit = true; - std::unique_lock lock(_joinMutex); - _joinCondition.wait(lock, [&]{ return !_isRunning; }); - } - -protected: - void run() override { - while (!_shouldQuit) { - _client->checkDevices(); - - const unsigned long DEVICE_CHECK_INTERVAL_MSECS = 2 * 1000; - QThread::msleep(DEVICE_CHECK_INTERVAL_MSECS); - } - std::lock_guard lock(_joinMutex); - _isRunning = false; - _joinCondition.notify_one(); - } - -private: - std::atomic _shouldQuit { false }; - bool _isRunning { true }; - std::mutex _joinMutex; - std::condition_variable _joinCondition; -}; - -// background thread buffering local injectors -class LocalInjectorsThread : public BackgroundThread { - Q_OBJECT -public: - LocalInjectorsThread(AudioClient* client) : BackgroundThread(client) {} - - void join() override { return; } - -private slots: - void prepare() { _client->prepareLocalAudioInjectors(); } -}; - -#include "AudioClient.moc" - static void channelUpmix(int16_t* source, int16_t* dest, int numSamples, int numExtraChannels) { for (int i = 0; i < numSamples/2; i++) { @@ -223,16 +173,15 @@ AudioClient::AudioClient() : _inputDevices = getDeviceNames(QAudio::AudioInput); _outputDevices = getDeviceNames(QAudio::AudioOutput); - // start a thread to detect any device changes - _checkDevicesThread = new CheckDevicesThread(this); - _checkDevicesThread->setObjectName("AudioClient CheckDevices Thread"); - _checkDevicesThread->setPriority(QThread::LowPriority); - _checkDevicesThread->start(); - // start a thread to process local injectors - _localInjectorsThread = new LocalInjectorsThread(this); - _localInjectorsThread->setObjectName("AudioClient LocalInjectors Thread"); - _localInjectorsThread->start(); + // start a thread to detect any device changes + _checkDevicesTimer = new QTimer(this); + connect(_checkDevicesTimer, &QTimer::timeout, [this] { + QtConcurrent::run(QThreadPool::globalInstance(), [this] { + checkDevices(); + }); + }); + configureReverb(); @@ -263,15 +212,7 @@ void AudioClient::cleanupBeforeQuit() { stop(); - if (_checkDevicesThread) { - static_cast(_checkDevicesThread)->join(); - delete _checkDevicesThread; - } - - if (_localInjectorsThread) { - static_cast(_localInjectorsThread)->join(); - delete _localInjectorsThread; - } + _checkDevicesTimer->stop(); } void AudioClient::handleMismatchAudioFormat(SharedNodePointer node, const QString& currentCodec, const QString& recievedCodec) { @@ -1369,10 +1310,8 @@ bool AudioClient::outputLocalInjector(AudioInjector* injector) { if (!_activeLocalAudioInjectors.contains(injector)) { qCDebug(audioclient) << "adding new injector"; _activeLocalAudioInjectors.append(injector); - // move local buffer to the LocalAudioThread to avoid dataraces with AudioInjector (like stop()) injectorBuffer->setParent(nullptr); - injectorBuffer->moveToThread(_localInjectorsThread); // update the flag _localInjectorsAvailable.exchange(true, std::memory_order_release); @@ -1782,7 +1721,9 @@ qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) { } // prepare injectors for the next callback - QMetaObject::invokeMethod(_audio->_localInjectorsThread, "prepare", Qt::QueuedConnection); + QtConcurrent::run(QThreadPool::globalInstance(), [this] { + _audio->prepareLocalAudioInjectors(); + }); int samplesPopped = std::max(networkSamplesPopped, injectorSamplesPopped); int framesPopped = samplesPopped / AudioConstants::STEREO; @@ -1855,3 +1796,8 @@ void AudioClient::setAvatarBoundingBoxParameters(glm::vec3 corner, glm::vec3 sca avatarBoundingBoxCorner = corner; avatarBoundingBoxScale = scale; } + + +void AudioClient::startThread() { + moveToNewNamedThread(this, "Audio Thread", [this] { start(); }); +} diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index b79cee238c..bec2fd2cc9 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -104,6 +104,7 @@ public: int _unfulfilledReads; }; + void startThread(); void negotiateAudioFormat(); void selectAudioFormat(const QString& selectedCodecName); @@ -386,8 +387,7 @@ private: RateCounter<> _silentInbound; RateCounter<> _audioInbound; - QThread* _checkDevicesThread { nullptr }; - QThread* _localInjectorsThread { nullptr }; + QTimer* _checkDevicesTimer { nullptr }; }; diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index cba1e664ab..93ae941f1e 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -22,8 +22,6 @@ #include #include -#include - #include #include #include diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 056a4d16cf..554386f786 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -31,7 +31,7 @@ #include #include -#include +#include #include #include @@ -68,9 +68,8 @@ const QString USERNAME_UUID_REPLACEMENT_STATS_KEY = "$username"; const QString LOCAL_SOCKET_CHANGE_STAT = "LocalSocketChanges"; -using namespace tbb; typedef std::pair UUIDNodePair; -typedef concurrent_unordered_map NodeHash; +typedef tbb::concurrent_unordered_map NodeHash; typedef quint8 PingType_t; namespace PingType { diff --git a/libraries/networking/src/MessagesClient.cpp b/libraries/networking/src/MessagesClient.cpp index 333552db4e..2302c22a48 100644 --- a/libraries/networking/src/MessagesClient.cpp +++ b/libraries/networking/src/MessagesClient.cpp @@ -16,6 +16,8 @@ #include #include +#include + #include "NetworkLogging.h" #include "NodeList.h" #include "PacketReceiver.h" @@ -30,12 +32,6 @@ MessagesClient::MessagesClient() { connect(nodeList.data(), &LimitedNodeList::nodeActivated, this, &MessagesClient::handleNodeActivated); } -void MessagesClient::init() { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "init", Qt::BlockingQueuedConnection); - } -} - void MessagesClient::decodeMessagesPacket(QSharedPointer receivedMessage, QString& channel, bool& isText, QString& message, QByteArray& data, QUuid& senderID) { quint16 channelLength; @@ -185,3 +181,7 @@ void MessagesClient::handleNodeActivated(SharedNodePointer node) { } } } + +void MessagesClient::startThread() { + moveToNewNamedThread(this, "Messages Client Thread"); +} diff --git a/libraries/networking/src/MessagesClient.h b/libraries/networking/src/MessagesClient.h index 51b468d646..6d0483fe9d 100644 --- a/libraries/networking/src/MessagesClient.h +++ b/libraries/networking/src/MessagesClient.h @@ -28,7 +28,7 @@ class MessagesClient : public QObject, public Dependency { public: MessagesClient(); - Q_INVOKABLE void init(); + void startThread(); Q_INVOKABLE void sendMessage(QString channel, QString message, bool localOnly = false); Q_INVOKABLE void sendLocalMessage(QString channel, QString message); diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index d1bbffd817..1092fcc7fa 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include "HifiSockAddr.h" #include "NetworkPeer.h" diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 868128f093..2aa30b84aa 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -1115,3 +1116,8 @@ void NodeList::setRequestsDomainListData(bool isRequesting) { }); _requestsDomainListData = isRequesting; } + + +void NodeList::startThread() { + moveToNewNamedThread(this, "NodeList Thread", QThread::TimeCriticalPriority); +} \ No newline at end of file diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 293b0942d6..6db760b3ca 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -20,7 +20,7 @@ #include // not on windows, not needed for mac or windows #endif -#include +#include #include #include @@ -52,6 +52,7 @@ class NodeList : public LimitedNodeList { SINGLETON_DEPENDENCY public: + void startThread(); NodeType_t getOwnerType() const { return _ownerType.load(); } void setOwnerType(NodeType_t ownerType) { _ownerType.store(ownerType); } diff --git a/libraries/shared/src/TBBHelpers.h b/libraries/shared/src/TBBHelpers.h new file mode 100644 index 0000000000..6b5c4d416b --- /dev/null +++ b/libraries/shared/src/TBBHelpers.h @@ -0,0 +1,28 @@ +// +// Created by Bradley Austin Davis on 2017/06/06 +// Copyright 2013-2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once +#ifndef hifi_TBBHelpers_h +#define hifi_TBBHelpers_h + +#ifdef _WIN32 +#pragma warning( push ) +#pragma warning( disable : 4334 ) +#endif + +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#pragma warning( pop ) +#endif + +#endif // hifi_TBBHelpers_h diff --git a/libraries/shared/src/ThreadHelpers.cpp b/libraries/shared/src/ThreadHelpers.cpp new file mode 100644 index 0000000000..14ae35762b --- /dev/null +++ b/libraries/shared/src/ThreadHelpers.cpp @@ -0,0 +1,39 @@ +// +// Created by Bradley Austin Davis on 2017/06/06 +// Copyright 2013-2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "ThreadHelpers.h" + +#include + + +void moveToNewNamedThread(QObject* object, const QString& name, std::function startCallback, QThread::Priority priority) { + Q_ASSERT(QThread::currentThread() == object->thread()); + // setup a thread for the NodeList and its PacketReceiver + QThread* thread = new QThread(); + thread->setObjectName(name); + + if (priority != QThread::InheritPriority) { + thread->setPriority(priority); + } + + QString tempName = name; + QObject::connect(thread, &QThread::started, [startCallback] { + startCallback(); + }); + // Make sure the thread will be destroyed and cleaned up + QObject::connect(object, &QObject::destroyed, thread, &QThread::quit); + QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater); + + // put the object on the thread + object->moveToThread(thread); + thread->start(); +} + +void moveToNewNamedThread(QObject* object, const QString& name, QThread::Priority priority) { + moveToNewNamedThread(object, name, [] {}, priority); +} diff --git a/libraries/shared/src/ThreadHelpers.h b/libraries/shared/src/ThreadHelpers.h index 0a92d36b80..6461fa5724 100644 --- a/libraries/shared/src/ThreadHelpers.h +++ b/libraries/shared/src/ThreadHelpers.h @@ -12,8 +12,13 @@ #define hifi_ThreadHelpers_h #include -#include -#include +#include + +#include +#include +#include +#include +#include template void withLock(L lock, F function) { @@ -26,4 +31,7 @@ void withLock(QMutex& lock, F function) { function(); } +void moveToNewNamedThread(QObject* object, const QString& name, std::function startCallback, QThread::Priority priority = QThread::InheritPriority); +void moveToNewNamedThread(QObject* object, const QString& name, QThread::Priority priority = QThread::InheritPriority); + #endif diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 35ad2df359..9a27543e8f 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -146,7 +146,7 @@ private: int _trackedControllers { 0 }; vr::IVRSystem*& _system; - quint64 _timeTilCalibration { 0.0f }; + quint64 _timeTilCalibration { 0 }; float _leftHapticStrength { 0.0f }; float _leftHapticDuration { 0.0f }; float _rightHapticStrength { 0.0f }; diff --git a/tests/qt59/CMakeLists.txt b/tests/qt59/CMakeLists.txt new file mode 100644 index 0000000000..32cc125ecf --- /dev/null +++ b/tests/qt59/CMakeLists.txt @@ -0,0 +1,15 @@ + +set(TARGET_NAME qt59) + +if (WIN32) + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ignore:4049 /ignore:4217") +endif() + +# This is not a testcase -- just set it up as a regular hifi project +setup_hifi_project(Gui) +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") + +# link in the shared libraries +link_hifi_libraries(shared networking) + +package_libraries_for_deployment() diff --git a/tests/qt59/src/main.cpp b/tests/qt59/src/main.cpp new file mode 100644 index 0000000000..c66a5e6f9a --- /dev/null +++ b/tests/qt59/src/main.cpp @@ -0,0 +1,78 @@ +// +// Created by Bradley Austin Davis on 2017/06/06 +// Copyright 2013-2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include + +#include +#include +#include +#include + +#include + + +class Qt59TestApp : public QCoreApplication { + Q_OBJECT +public: + Qt59TestApp(int argc, char* argv[]); + ~Qt59TestApp(); + +private: + void finish(int exitCode); +}; + + + +Qt59TestApp::Qt59TestApp(int argc, char* argv[]) : + QCoreApplication(argc, argv) +{ + + Setting::init(); + DependencyManager::registerInheritance(); + DependencyManager::set([&] { return QString("Mozilla/5.0 (HighFidelityACClient)"); }); + DependencyManager::set(); + DependencyManager::set(NodeType::Agent, 0); + auto nodeList = DependencyManager::get(); + nodeList->startThread(); + auto messagesClient = DependencyManager::set(); + messagesClient->startThread(); + QTimer::singleShot(1000, [this] { finish(0); }); +} + +Qt59TestApp::~Qt59TestApp() { +} + + +void Qt59TestApp::finish(int exitCode) { + auto nodeList = DependencyManager::get(); + + // send the domain a disconnect packet, force stoppage of domain-server check-ins + nodeList->getDomainHandler().disconnect(); + nodeList->setIsShuttingDown(true); + nodeList->getPacketReceiver().setShouldDropPackets(true); + + // remove the NodeList from the DependencyManager + DependencyManager::destroy(); + QCoreApplication::exit(exitCode); +} + + +int main(int argc, char * argv[]) { + QCoreApplication::setApplicationName("Qt59Test"); + QCoreApplication::setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION); + QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN); + QCoreApplication::setApplicationVersion(BuildInfo::VERSION); + + Qt59TestApp app(argc, argv); + + return app.exec(); +} + +#include "main.moc" \ No newline at end of file diff --git a/tools/ac-client/src/ACClientApp.cpp b/tools/ac-client/src/ACClientApp.cpp index 4c12a09388..b81d092662 100644 --- a/tools/ac-client/src/ACClientApp.cpp +++ b/tools/ac-client/src/ACClientApp.cpp @@ -90,23 +90,14 @@ ACClientApp::ACClientApp(int argc, char* argv[]) : auto nodeList = DependencyManager::get(); - // start the nodeThread so its event loop is running - QThread* nodeThread = new QThread(this); - nodeThread->setObjectName("NodeList Thread"); - nodeThread->start(); - - // make sure the node thread is given highest priority - nodeThread->setPriority(QThread::TimeCriticalPriority); + nodeList->startThread(); // setup a timer for domain-server check ins QTimer* domainCheckInTimer = new QTimer(nodeList.data()); connect(domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn); domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); - // put the NodeList and datagram processing on the node thread - nodeList->moveToThread(nodeThread); - const DomainHandler& domainHandler = nodeList->getDomainHandler(); connect(&domainHandler, SIGNAL(hostnameChanged(const QString&)), SLOT(domainChanged(const QString&))); @@ -239,12 +230,8 @@ void ACClientApp::finish(int exitCode) { // tell the packet receiver we're shutting down, so it can drop packets nodeList->getPacketReceiver().setShouldDropPackets(true); - QThread* nodeThread = DependencyManager::get()->thread(); // remove the NodeList from the DependencyManager DependencyManager::destroy(); - // ask the node thread to quit and wait until it is done - nodeThread->quit(); - nodeThread->wait(); printFailedServers(); QCoreApplication::exit(exitCode); diff --git a/tools/atp-get/src/ATPGetApp.cpp b/tools/atp-get/src/ATPGetApp.cpp index 30054fffea..4125582c21 100644 --- a/tools/atp-get/src/ATPGetApp.cpp +++ b/tools/atp-get/src/ATPGetApp.cpp @@ -111,23 +111,13 @@ ATPGetApp::ATPGetApp(int argc, char* argv[]) : auto nodeList = DependencyManager::get(); - - // start the nodeThread so its event loop is running - QThread* nodeThread = new QThread(this); - nodeThread->setObjectName("NodeList Thread"); - nodeThread->start(); - - // make sure the node thread is given highest priority - nodeThread->setPriority(QThread::TimeCriticalPriority); + nodeList->startThread(); // setup a timer for domain-server check ins QTimer* domainCheckInTimer = new QTimer(nodeList.data()); connect(domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn); domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); - // put the NodeList and datagram processing on the node thread - nodeList->moveToThread(nodeThread); - const DomainHandler& domainHandler = nodeList->getDomainHandler(); connect(&domainHandler, SIGNAL(hostnameChanged(const QString&)), SLOT(domainChanged(const QString&))); @@ -258,12 +248,8 @@ void ATPGetApp::finish(int exitCode) { // tell the packet receiver we're shutting down, so it can drop packets nodeList->getPacketReceiver().setShouldDropPackets(true); - QThread* nodeThread = DependencyManager::get()->thread(); // remove the NodeList from the DependencyManager DependencyManager::destroy(); - // ask the node thread to quit and wait until it is done - nodeThread->quit(); - nodeThread->wait(); QCoreApplication::exit(exitCode); } diff --git a/tools/oven/src/Oven.h b/tools/oven/src/Oven.h index 350c615ce0..569b73a3e2 100644 --- a/tools/oven/src/Oven.h +++ b/tools/oven/src/Oven.h @@ -14,7 +14,7 @@ #include -#include +#include #include