types 0 and 1 exit cleanly, type 6 crashes

This commit is contained in:
Seth Alves 2015-04-29 11:56:45 -07:00
parent b2e99b754f
commit d2cd4fc405
16 changed files with 211 additions and 111 deletions

View file

@ -116,8 +116,11 @@ void AssignmentClient::stopAssignmentClient() {
_statsTimerACM.stop();
if (_currentAssignment) {
_currentAssignment->aboutToQuit();
// _currentAssignment->aboutToFinish();
_currentAssignment->thread()->wait();
QThread* currentAssignmentThread = _currentAssignment->thread();
qDebug() << "main thread waiting on _currentAssignment->thread()" << currentAssignmentThread->objectName();
currentAssignmentThread->quit();
currentAssignmentThread->wait();
qDebug() << "done waiting.";
}
}

View file

@ -183,6 +183,8 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
QThread::currentThread()->setObjectName("main thread");
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
if (numForks || minForks || maxForks) {
AssignmentClientMonitor monitor(numForks, minForks, maxForks, requestAssignmentType, assignmentPool,
walletUUID, assignmentServerHostname, assignmentServerPort);

View file

@ -588,6 +588,7 @@ void AudioMixer::sendStatsPacket() {
_sumMixes = 0;
_numStatFrames = 0;
// NOTE: These stats can be too large to fit in an MTU, so we break it up into multiple packts...
QJsonObject statsObject2;
@ -711,90 +712,78 @@ void AudioMixer::run() {
// check the settings object to see if we have anything we can parse out
parseSettingsObject(settingsObject);
_nextFrame = 0;
_timer.start();
int nextFrame = 0;
QElapsedTimer timer;
timer.start();
_idleTimer = new QTimer();
connect(_idleTimer, SIGNAL(timeout()), this, SLOT(insideLoop()));
_idleTimer->start(0);
}
char clientMixBuffer[MAX_PACKET_SIZE];
int usecToSleep = AudioConstants::NETWORK_FRAME_USECS;
const int TRAILING_AVERAGE_FRAMES = 100;
int framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES;
void AudioMixer::insideLoop() {
if (_isFinished) {
qDebug() << "AudioMixer::insideLoop stoping _idleTimer";
_idleTimer->stop();
delete _idleTimer;
_idleTimer = nullptr;
QThread *thisThread = QThread::currentThread();
thisThread->quit();
return;
}
auto nodeList = DependencyManager::get<NodeList>();
const float STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.10f;
const float BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.20f;
while (!_isFinished) {
const float STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.10f;
const float BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.20f;
const float RATIO_BACK_OFF = 0.02f;
const float RATIO_BACK_OFF = 0.02f;
const float CURRENT_FRAME_RATIO = 1.0f / TRAILING_AVERAGE_FRAMES;
const float PREVIOUS_FRAMES_RATIO = 1.0f - CURRENT_FRAME_RATIO;
const float CURRENT_FRAME_RATIO = 1.0f / TRAILING_AVERAGE_FRAMES;
const float PREVIOUS_FRAMES_RATIO = 1.0f - CURRENT_FRAME_RATIO;
if (_usecToSleep < 0) {
_usecToSleep = 0;
}
if (usecToSleep < 0) {
usecToSleep = 0;
}
_trailingSleepRatio = (PREVIOUS_FRAMES_RATIO * _trailingSleepRatio)
+ (_usecToSleep * CURRENT_FRAME_RATIO / (float) AudioConstants::NETWORK_FRAME_USECS);
_trailingSleepRatio = (PREVIOUS_FRAMES_RATIO * _trailingSleepRatio)
+ (usecToSleep * CURRENT_FRAME_RATIO / (float) AudioConstants::NETWORK_FRAME_USECS);
float lastCutoffRatio = _performanceThrottlingRatio;
bool hasRatioChanged = false;
float lastCutoffRatio = _performanceThrottlingRatio;
bool hasRatioChanged = false;
if (_framesSinceCutoffEvent >= TRAILING_AVERAGE_FRAMES) {
if (_trailingSleepRatio <= STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD) {
// we're struggling - change our min required loudness to reduce some load
_performanceThrottlingRatio = _performanceThrottlingRatio + (0.5f * (1.0f - _performanceThrottlingRatio));
if (framesSinceCutoffEvent >= TRAILING_AVERAGE_FRAMES) {
if (_trailingSleepRatio <= STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD) {
// we're struggling - change our min required loudness to reduce some load
_performanceThrottlingRatio = _performanceThrottlingRatio + (0.5f * (1.0f - _performanceThrottlingRatio));
qDebug() << "Mixer is struggling, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was"
<< lastCutoffRatio << "and is now" << _performanceThrottlingRatio;
hasRatioChanged = true;
} else if (_trailingSleepRatio >= BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD && _performanceThrottlingRatio != 0) {
// we've recovered and can back off the required loudness
_performanceThrottlingRatio = _performanceThrottlingRatio - RATIO_BACK_OFF;
qDebug() << "Mixer is struggling, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was"
<< lastCutoffRatio << "and is now" << _performanceThrottlingRatio;
hasRatioChanged = true;
} else if (_trailingSleepRatio >= BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD && _performanceThrottlingRatio != 0) {
// we've recovered and can back off the required loudness
_performanceThrottlingRatio = _performanceThrottlingRatio - RATIO_BACK_OFF;
if (_performanceThrottlingRatio < 0) {
_performanceThrottlingRatio = 0;
if (_performanceThrottlingRatio < 0) {
_performanceThrottlingRatio = 0;
}
qDebug() << "Mixer is recovering, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was"
<< lastCutoffRatio << "and is now" << _performanceThrottlingRatio;
hasRatioChanged = true;
}
qDebug() << "Mixer is recovering, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was"
<< lastCutoffRatio << "and is now" << _performanceThrottlingRatio;
hasRatioChanged = true;
}
if (hasRatioChanged) {
// set out min audability threshold from the new ratio
_minAudibilityThreshold = LOUDNESS_TO_DISTANCE_RATIO / (2.0f * (1.0f - _performanceThrottlingRatio));
qDebug() << "Minimum audability required to be mixed is now" << _minAudibilityThreshold;
if (hasRatioChanged) {
// set out min audability threshold from the new ratio
_minAudibilityThreshold = LOUDNESS_TO_DISTANCE_RATIO / (2.0f * (1.0f - _performanceThrottlingRatio));
qDebug() << "Minimum audability required to be mixed is now" << _minAudibilityThreshold;
_framesSinceCutoffEvent = 0;
framesSinceCutoffEvent = 0;
}
}
}
if (!hasRatioChanged) {
++_framesSinceCutoffEvent;
}
if (!hasRatioChanged) {
++framesSinceCutoffEvent;
}
quint64 now = usecTimestampNow();
if (now - _lastPerSecondCallbackTime > USECS_PER_SECOND) {
perSecondActions();
_lastPerSecondCallbackTime = now;
}
quint64 now = usecTimestampNow();
if (now - _lastPerSecondCallbackTime > USECS_PER_SECOND) {
perSecondActions();
_lastPerSecondCallbackTime = now;
}
nodeList->eachNode([&](const SharedNodePointer& node) {
nodeList->eachNode([&](const SharedNodePointer& node) {
if (node->getLinkedData()) {
AudioMixerClientData* nodeData = (AudioMixerClientData*)node->getLinkedData();
@ -818,8 +807,8 @@ void AudioMixer::insideLoop() {
char* mixDataAt;
if (streamsMixed > 0) {
// pack header
int numBytesMixPacketHeader = populatePacketHeader(_clientMixBuffer, PacketTypeMixedAudio);
mixDataAt = _clientMixBuffer + numBytesMixPacketHeader;
int numBytesMixPacketHeader = populatePacketHeader(clientMixBuffer, PacketTypeMixedAudio);
mixDataAt = clientMixBuffer + numBytesMixPacketHeader;
// pack sequence number
quint16 sequence = nodeData->getOutgoingSequenceNumber();
@ -831,8 +820,8 @@ void AudioMixer::insideLoop() {
mixDataAt += AudioConstants::NETWORK_FRAME_BYTES_STEREO;
} else {
// pack header
int numBytesPacketHeader = populatePacketHeader(_clientMixBuffer, PacketTypeSilentAudioFrame);
mixDataAt = _clientMixBuffer + numBytesPacketHeader;
int numBytesPacketHeader = populatePacketHeader(clientMixBuffer, PacketTypeSilentAudioFrame);
mixDataAt = clientMixBuffer + numBytesPacketHeader;
// pack sequence number
quint16 sequence = nodeData->getOutgoingSequenceNumber();
@ -844,12 +833,12 @@ void AudioMixer::insideLoop() {
memcpy(mixDataAt, &numSilentSamples, sizeof(quint16));
mixDataAt += sizeof(quint16);
}
// Send audio environment
sendAudioEnvironmentPacket(node);
// send mixed audio packet
nodeList->writeDatagram(_clientMixBuffer, mixDataAt - _clientMixBuffer, node);
nodeList->writeDatagram(clientMixBuffer, mixDataAt - clientMixBuffer, node);
nodeData->incrementOutgoingMixedAudioSequenceNumber();
// send an audio stream stats packet if it's time
@ -863,22 +852,22 @@ void AudioMixer::insideLoop() {
}
});
++_numStatFrames;
++_numStatFrames;
QCoreApplication::processEvents();
QCoreApplication::processEvents();
if (_isFinished) {
return;
}
if (_isFinished) {
break;
}
_usecToSleep = (++_nextFrame * AudioConstants::NETWORK_FRAME_USECS) - _timer.nsecsElapsed() / 1000; // ns to us
usecToSleep = (++nextFrame * AudioConstants::NETWORK_FRAME_USECS) - timer.nsecsElapsed() / 1000; // ns to us
if (_usecToSleep > 0) {
usleep(_usecToSleep);
if (usecToSleep > 0) {
usleep(usecToSleep);
}
}
}
void AudioMixer::perSecondActions() {
_sendAudioStreamStats = true;

View file

@ -32,7 +32,6 @@ public:
public slots:
/// threaded run of assignment
void run();
void insideLoop();
void readPendingDatagrams() { }; // this will not be called since our datagram processing thread will handle
void readPendingDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr);
@ -112,14 +111,14 @@ private:
MovingMinMaxAvg<int> _readPendingCallsPerSecondStats; // update with # of readPendingDatagrams calls in the last second
// loop variables
QTimer* _idleTimer = nullptr;
int _nextFrame = 0;
QElapsedTimer _timer;
char _clientMixBuffer[MAX_PACKET_SIZE];
int _usecToSleep = AudioConstants::NETWORK_FRAME_USECS;
const int TRAILING_AVERAGE_FRAMES = 100;
int _framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES;
/* // loop variables */
/* // QTimer* _idleTimer = nullptr; */
/* int _nextFrame = 0; */
/* QElapsedTimer _timer; */
/* char _clientMixBuffer[MAX_PACKET_SIZE]; */
/* int _usecToSleep = AudioConstants::NETWORK_FRAME_USECS; */
/* const int TRAILING_AVERAGE_FRAMES = 100; */
/* int _framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES; */
};
#endif // hifi_AudioMixer_h

View file

@ -45,6 +45,10 @@ AvatarMixer::AvatarMixer(const QByteArray& packet) :
}
AvatarMixer::~AvatarMixer() {
qDebug() << "AvatarMixer::~AvatarMixer";
if (_broadcastTimer) {
_broadcastTimer->deleteLater();
}
_broadcastThread.quit();
_broadcastThread.wait();
}
@ -61,9 +65,7 @@ const float BILLBOARD_AND_IDENTITY_SEND_PROBABILITY = 1.0f / 300.0f;
// 1) use the view frustum to cull those avatars that are out of view. Since avatar data doesn't need to be present
// if the avatar is not in view or in the keyhole.
void AvatarMixer::broadcastAvatarData() {
int idleTime = QDateTime::currentMSecsSinceEpoch() - _lastFrameTimestamp;
++_numStatFrames;
const float STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.10f;
@ -334,6 +336,22 @@ void AvatarMixer::sendStatsPacket() {
_numStatFrames = 0;
}
// void AvatarMixer::stop() {
// qDebug() << "AvatarMixer::stop";
// if (_broadcastTimer) {
// // _broadcastTimer->stop();
// // delete _broadcastTimer;
// _broadcastTimer->deleteLater();
// // _broadcastTimer = nullptr;
// }
// _broadcastThread.quit();
// _broadcastThread.wait();
// ThreadedAssignment::stop();
// }
void AvatarMixer::run() {
ThreadedAssignment::commonInit(AVATAR_MIXER_LOGGING_NAME, NodeType::AvatarMixer);
@ -343,13 +361,13 @@ void AvatarMixer::run() {
nodeList->linkedDataCreateCallback = attachAvatarDataToNode;
// setup the timer that will be fired on the broadcast thread
QTimer* broadcastTimer = new QTimer();
broadcastTimer->setInterval(AVATAR_DATA_SEND_INTERVAL_MSECS);
broadcastTimer->moveToThread(&_broadcastThread);
_broadcastTimer = new QTimer();
_broadcastTimer->setInterval(AVATAR_DATA_SEND_INTERVAL_MSECS);
_broadcastTimer->moveToThread(&_broadcastThread);
// connect appropriate signals and slots
connect(broadcastTimer, &QTimer::timeout, this, &AvatarMixer::broadcastAvatarData, Qt::DirectConnection);
connect(&_broadcastThread, SIGNAL(started()), broadcastTimer, SLOT(start()));
connect(_broadcastTimer, &QTimer::timeout, this, &AvatarMixer::broadcastAvatarData, Qt::DirectConnection);
connect(&_broadcastThread, SIGNAL(started()), _broadcastTimer, SLOT(start()));
// start the broadcastThread
_broadcastThread.start();

View file

@ -25,6 +25,7 @@ public:
public slots:
/// runs the avatar mixer
void run();
// Q_INVOKABLE virtual void stop();
void nodeAdded(SharedNodePointer nodeAdded);
void nodeKilled(SharedNodePointer killedNode);
@ -32,6 +33,8 @@ public slots:
void readPendingDatagrams();
void sendStatsPacket();
void finished();
private:
void broadcastAvatarData();
@ -47,6 +50,8 @@ private:
int _numStatFrames;
int _sumBillboardPackets;
int _sumIdentityPackets;
QTimer* _broadcastTimer = nullptr;
};
#endif // hifi_AvatarMixer_h

View file

@ -27,6 +27,13 @@ EntityServer::EntityServer(const QByteArray& packet)
}
EntityServer::~EntityServer() {
qDebug() << "EntityServer::~EntityServer";
if (_pruneDeletedEntitiesTimer) {
_pruneDeletedEntitiesTimer->stop();
_pruneDeletedEntitiesTimer->deleteLater();
}
EntityTree* tree = (EntityTree*)_tree;
tree->removeNewlyCreatedHook(this);
}
@ -48,10 +55,10 @@ Octree* EntityServer::createTree() {
}
void EntityServer::beforeRun() {
QTimer* pruneDeletedEntitiesTimer = new QTimer(this);
connect(pruneDeletedEntitiesTimer, SIGNAL(timeout()), this, SLOT(pruneDeletedEntities()));
_pruneDeletedEntitiesTimer = new QTimer(this);
connect(_pruneDeletedEntitiesTimer, SIGNAL(timeout()), this, SLOT(pruneDeletedEntities()));
const int PRUNE_DELETED_MODELS_INTERVAL_MSECS = 1 * 1000; // once every second
pruneDeletedEntitiesTimer->start(PRUNE_DELETED_MODELS_INTERVAL_MSECS);
_pruneDeletedEntitiesTimer->start(PRUNE_DELETED_MODELS_INTERVAL_MSECS);
}
void EntityServer::entityCreated(const EntityItem& newEntity, const SharedNodePointer& senderNode) {
@ -158,3 +165,12 @@ void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectio
}
// void EntityServer::stop() {
// qDebug() << "EntityServer::stop";
// if (_pruneDeletedEntitiesTimer) {
// _pruneDeletedEntitiesTimer->stop();
// delete _pruneDeletedEntitiesTimer;
// _pruneDeletedEntitiesTimer = nullptr;
// }
// OctreeServer::stop();
// }

View file

@ -44,6 +44,7 @@ public:
virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject);
public slots:
// Q_INVOKABLE virtual void stop();
void pruneDeletedEntities();
protected:
@ -51,6 +52,7 @@ protected:
private:
EntitySimulation* _entitySimulation;
QTimer* _pruneDeletedEntitiesTimer = nullptr;
};
#endif // hifi_EntityServer_h

View file

@ -74,7 +74,8 @@ public:
NodeToSenderStatsMap& getSingleSenderStats() { return _singleSenderStats; }
void shuttingDown() { _shuttingDown = true;}
// void shuttingDown() { _shuttingDown = true;}
virtual void terminating() { _shuttingDown = true; ReceivedPacketProcessor::terminating(); }
protected:

View file

@ -266,16 +266,19 @@ OctreeServer::~OctreeServer() {
}
if (_jurisdictionSender) {
_jurisdictionSender->terminating();
_jurisdictionSender->terminate();
_jurisdictionSender->deleteLater();
}
if (_octreeInboundPacketProcessor) {
_octreeInboundPacketProcessor->terminating();
_octreeInboundPacketProcessor->terminate();
_octreeInboundPacketProcessor->deleteLater();
}
if (_persistThread) {
_persistThread->terminating();
_persistThread->terminate();
_persistThread->deleteLater();
}
@ -1219,7 +1222,7 @@ void OctreeServer::forceNodeShutdown(SharedNodePointer node) {
void OctreeServer::aboutToFinish() {
qDebug() << qPrintable(_safeServerName) << "server STARTING about to finish...";
qDebug() << qPrintable(_safeServerName) << "inform Octree Inbound Packet Processor that we are shutting down...";
_octreeInboundPacketProcessor->shuttingDown();
_octreeInboundPacketProcessor->terminating();
DependencyManager::get<NodeList>()->eachNode([this](const SharedNodePointer& node) {
qDebug() << qPrintable(_safeServerName) << "server about to finish while node still connected node:" << *node;
@ -1233,6 +1236,40 @@ void OctreeServer::aboutToFinish() {
qDebug() << qPrintable(_safeServerName) << "server ENDING about to finish...";
}
// void OctreeServer::stop() {
// qDebug() << "OctreeServer::stop";
// // setFinished(true);
// // QThread *thisThread = QThread::currentThread();
// // thisThread->quit();
// if (_jurisdictionSender) {
// _jurisdictionSender->terminating();
// _jurisdictionSender->terminate();
// // delete _jurisdictionSender;
// // _jurisdictionSender = nullptr;
// }
// _datagramProcessingThread->quit();
// if (_octreeInboundPacketProcessor) {
// _octreeInboundPacketProcessor->terminating();
// _octreeInboundPacketProcessor->terminate();
// // delete _octreeInboundPacketProcessor;
// // _octreeInboundPacketProcessor = nullptr;
// }
// // _persistThread
// if (_persistThread) {
// _persistThread->terminating();
// _persistThread->terminate();
// // delete _persistThread;
// // _persistThread = nullptr;
// }
// ThreadedAssignment::stop();
// }
QString OctreeServer::getUptime() {
QString formattedUptime;
quint64 now = usecTimestampNow();

View file

@ -123,6 +123,7 @@ public:
public slots:
/// runs the octree server assignment
void run();
// Q_INVOKABLE virtual void stop();
void nodeAdded(SharedNodePointer node);
void nodeKilled(SharedNodePointer node);
void sendStatsPacket();

View file

@ -47,6 +47,8 @@ public:
/// How many received packets waiting are to be processed
int packetsToProcessCount() const { return _packets.size(); }
virtual void terminating();
public slots:
void nodeKilled(SharedNodePointer node);
@ -71,8 +73,6 @@ protected:
/// Override to do work after the packets processing loop. Default does nothing.
virtual void postProcess() { }
virtual void terminating();
protected:
QVector<NetworkPacket> _packets;

View file

@ -26,7 +26,14 @@ ThreadedAssignment::ThreadedAssignment(const QByteArray& packet) :
}
ThreadedAssignment::~ThreadedAssignment() {
// setFinished(true);
}
void ThreadedAssignment::setFinished(bool isFinished) {
qDebug() << "------------- ThreadedAssignment::setFinished" << isFinished << " -------------------";
_isFinished = isFinished;
if (_isFinished) {
@ -50,8 +57,10 @@ void ThreadedAssignment::setFinished(bool isFinished) {
if (_datagramProcessingThread) {
// tell the datagram processing thread to quit and wait until it is done, then return the node socket to the NodeList
qDebug() << "stopping datagramProcessingThread...";
_datagramProcessingThread->quit();
_datagramProcessingThread->wait();
qDebug() << "done stopping datagramProcessingThread.";
// set node socket parent back to NodeList
nodeList->getNodeSocket().setParent(nodeList.data());
@ -64,6 +73,15 @@ void ThreadedAssignment::setFinished(bool isFinished) {
}
}
// void ThreadedAssignment::stop() {
// setFinished(true);
// qDebug() << "ThreadedAssignment::stop";
// QThread *thisThread = QThread::currentThread();
// thisThread->quit();
// }
void ThreadedAssignment::commonInit(const QString& targetName, NodeType_t nodeType, bool shouldSendStats) {
// change the logging target name while the assignment is running
LogHandler::getInstance().setTargetName(targetName);

View file

@ -20,6 +20,7 @@ class ThreadedAssignment : public Assignment {
Q_OBJECT
public:
ThreadedAssignment(const QByteArray& packet);
virtual ~ThreadedAssignment();
void setFinished(bool isFinished);
virtual void aboutToFinish() { };
@ -28,14 +29,13 @@ public:
public slots:
/// threaded run of assignment
virtual void run() = 0;
Q_INVOKABLE void stop() { setFinished(true); }
Q_INVOKABLE virtual void stop() { setFinished(true); }
virtual void readPendingDatagrams() = 0;
virtual void sendStatsPacket();
public slots:
virtual void aboutToQuit() {
// emit finished();
QMetaObject::invokeMethod(this, "stop");
QMetaObject::invokeMethod(this, "stop");
}
signals:

View file

@ -228,6 +228,7 @@ void OctreePersistThread::aboutToFinish() {
qCDebug(octree) << "Persist thread about to finish...";
persist();
qCDebug(octree) << "Persist thread done with about to finish...";
_stopThread = true;
}
void OctreePersistThread::persist() {

View file

@ -26,15 +26,21 @@
class Dependency {
public:
typedef std::function<void(Dependency* pointer)> DeleterFunction;
const QString& getDependencyName() { return _name; }
protected:
virtual ~Dependency() {}
virtual ~Dependency() {
qDebug() << "DESTRUCTING" << _name;
}
virtual void customDeleter() {
_customDeleter(this);
}
void setCustomDeleter(DeleterFunction customDeleter) { _customDeleter = customDeleter; }
DeleterFunction _customDeleter = [](Dependency* pointer) { delete pointer; };
void setDependencyName(QString name) { _name = name; }
QString _name;
friend class DependencyManager;
};
@ -95,6 +101,7 @@ QSharedPointer<T> DependencyManager::set(Args&&... args) {
QSharedPointer<T> newInstance(new T(args...), &T::customDeleter);
QSharedPointer<Dependency> storedInstance = qSharedPointerCast<Dependency>(newInstance);
instance.swap(storedInstance);
newInstance->setDependencyName(typeid(T).name());
return newInstance;
}
@ -102,6 +109,7 @@ QSharedPointer<T> DependencyManager::set(Args&&... args) {
template <typename T>
void DependencyManager::destroy() {
static size_t hashCode = _manager.getHashCode<T>();
qDebug() << "DESTROYING" << _manager.safeGet(hashCode)->getDependencyName();
_manager.safeGet(hashCode).clear();
}