Skip to content

Commit de5a3bd

Browse files
committed
Clean-up shared pointers when stopping instances, plus support tracking
1 parent 742d045 commit de5a3bd

File tree

12 files changed

+258
-91
lines changed

12 files changed

+258
-91
lines changed

include/api/JsonCallbacks.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,14 @@ private slots:
179179
///
180180
void handleEventUpdate(const Event &event);
181181

182+
///
183+
/// @brief Handle whenever the state of a instance (HyperionIManager) changes according to enum instanceState
184+
/// @param instaneState A state from enum
185+
/// @param instanceId The index of instance
186+
/// @param name The name of the instance, just available with H_CREATED
187+
///
188+
void handleInstanceStateChange(InstanceState state, quint8 instanceId, const QString &name = QString());
189+
182190
private:
183191

184192
/// construct callback msg
@@ -194,7 +202,7 @@ private slots:
194202
QString _peerAddress;
195203

196204
/// pointer of comp register
197-
ComponentRegister* _componentRegister;
205+
QSharedPointer<ComponentRegister> _componentRegister;
198206

199207
/// priority muxer instance
200208
QSharedPointer<PriorityMuxer> _prioMuxer;

include/effectengine/EffectEngine.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@
99
#include <QJsonArray>
1010
#include <QEventLoop>
1111

12-
// Hyperion includes
13-
#include <hyperion/Hyperion.h>
14-
1512
// Effect engine includes
1613
#include <effectengine/EffectDefinition.h>
1714
#include <effectengine/Effect.h>
@@ -21,6 +18,7 @@
2118
#include <hyperion/LinearColorSmoothing.h>
2219

2320
// pre-declaration
21+
class Hyperion;
2422
class Effect;
2523
class EffectFileHandler;
2624

include/hyperion/BGEffectHandler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
#define BGEFFECTHANDLER_H
33

44
#include <utils/Logger.h>
5-
#include <hyperion/Hyperion.h>
65
#include <utils/settings.h>
76

87
#include <QObject>
98
#include <QJsonDocument>
109

10+
class Hyperion;
11+
1112
///
1213
/// @brief Handle the background Effect settings, reacts on runtime to settings changes
1314
///

include/hyperion/Hyperion.h

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <QScopedPointer>
1616
#include <QSharedPointer>
1717
#include <QElapsedTimer>
18+
#include <QThread>
1819

1920
// hyperion-utils includes
2021
#include <utils/Image.h>
@@ -25,10 +26,19 @@
2526
// Hyperion includes
2627
#include <hyperion/LedString.h>
2728
#include <hyperion/PriorityMuxer.h>
29+
#include <hyperion/MultiColorAdjustment.h>
2830
#include <hyperion/ColorAdjustment.h>
2931
#include <hyperion/ComponentRegister.h>
3032

33+
#include <hyperion/SettingsManager.h>
34+
#include <hyperion/CaptureCont.h>
35+
#include <hyperion/BGEffectHandler.h>
36+
37+
#include <leddevice/LedDeviceWrapper.h>
38+
#include <boblightserver/BoblightServer.h>
39+
3140
#if defined(ENABLE_EFFECTENGINE)
41+
#include <effectengine/EffectEngine.h>
3242
#include <effectengine/ActiveEffectDefinition.h>
3343
#endif
3444

@@ -38,22 +48,8 @@
3848
#include <utils/settings.h>
3949

4050
// Forward class declaration
41-
class HyperionDaemon;
42-
class HyperionIManager;
4351
class ImageProcessor;
4452
class LinearColorSmoothing;
45-
#if defined(ENABLE_EFFECTENGINE)
46-
class EffectEngine;
47-
#endif
48-
class MultiColorAdjustment;
49-
class ColorAdjustment;
50-
class SettingsManager;
51-
class BGEffectHandler;
52-
class CaptureCont;
53-
#if defined(ENABLE_BOBLIGHT_SERVER)
54-
class BoblightServer;
55-
#endif
56-
class LedDeviceWrapper;
5753
class Logger;
5854

5955
///
@@ -69,9 +65,10 @@ class Hyperion : public QObject
6965
using InputInfo = PriorityMuxer::InputInfo;
7066

7167
///
72-
/// Destructor; cleans up resources
68+
/// @brief Constructs the Hyperion instance
69+
/// @param instance The instance index
7370
///
74-
~Hyperion() override;
71+
explicit Hyperion(quint8 instance, QObject* parent = nullptr);
7572

7673
ImageProcessor* getImageProcessor() const { return _imageProcessor.get(); }
7774

@@ -205,7 +202,7 @@ public slots:
205202
/// @brief Get a pointer to the effect engine
206203
/// @return EffectEngine instance pointer
207204
///
208-
EffectEngine* getEffectEngineInstance() const { return _effectEngine.get(); }
205+
QSharedPointer<EffectEngine> getEffectEngineInstance() const { return _effectEngine; }
209206

210207
/// Run the specified effect on the given priority channel and optionally specify a timeout
211208
/// @param effectName Name of the effec to run
@@ -321,7 +318,7 @@ public slots:
321318
/// @brief Get the component Register
322319
/// return Component register pointer
323320
///
324-
ComponentRegister* getComponentRegister() const { return _componentRegister.get(); }
321+
QSharedPointer<ComponentRegister> getComponentRegister() const { return _componentRegister; }
325322

326323
///
327324
/// @brief Called from components to update their current state. DO NOT CALL FROM USERS
@@ -512,15 +509,6 @@ private slots:
512509
void handleSourceAvailability(int priority);
513510

514511
private:
515-
friend class HyperionDaemon;
516-
517-
///
518-
/// @brief Constructs the Hyperion instance, just accessible for HyperionIManager
519-
/// @param instance The instance index
520-
///
521-
explicit Hyperion(quint8 instance, QObject* parent = nullptr);
522-
523-
friend class HyperionIManager; // Grant HyperionIManager access to private members
524512

525513
void updateLedColorAdjustment(int ledCount, const QJsonObject& colors);
526514
void updateLedLayout(const QJsonArray& ledLayout);
@@ -556,7 +544,7 @@ private slots:
556544

557545
#if defined(ENABLE_EFFECTENGINE)
558546
/// Effect engine
559-
QScopedPointer<EffectEngine, QScopedPointerDeleteLater> _effectEngine;
547+
QSharedPointer<EffectEngine> _effectEngine;
560548
#endif
561549

562550
/// Logger instance

include/utils/TrackedMemory.h

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#ifndef TRACKEDMEMORY_H
2+
#define TRACKEDMEMORY_H
3+
4+
#include <QSharedPointer>
5+
#include <QObject>
6+
#include <QThread>
7+
#include <QString>
8+
#include <typeinfo>
9+
#include <type_traits>
10+
#include <utils/Logger.h>
11+
12+
#define ENABLE_MEMORY_TRACKING 0
13+
14+
#define USE_TRACKED_SHARED_PTR ENABLE_MEMORY_TRACKING
15+
#define USE_TRACKED_DELETE_LATER ENABLE_MEMORY_TRACKING
16+
17+
#if USE_TRACKED_SHARED_PTR
18+
#define MAKE_TRACKED_SHARED(T, ...) makeTrackedShared<T>(__VA_ARGS__)
19+
#else
20+
#define MAKE_TRACKED_SHARED(T, ...) QSharedPointer<T>(new T(__VA_ARGS__), &QObject::deleteLater)
21+
#endif
22+
23+
#if USE_TRACKED_DELETE_LATER
24+
#define DELETE_LATER_FN(T) trackedDeleteLater<T>
25+
#else
26+
#define DELETE_LATER_FN(T) &QObject::deleteLater
27+
#endif
28+
29+
// Deleter function template
30+
template<typename T>
31+
void trackedDeleteLater(T* ptr)
32+
{
33+
if (!ptr)
34+
return;
35+
36+
QString subComponent = "__";
37+
QString typeName;
38+
39+
if constexpr (std::is_base_of<QObject, T>::value)
40+
{
41+
QVariant prop = ptr->property("instance");
42+
if (prop.isValid() && prop.canConvert<QString>())
43+
{
44+
subComponent = prop.toString();
45+
}
46+
typeName = ptr->metaObject()->className();
47+
}
48+
else
49+
{
50+
typeName = typeid(T).name();
51+
}
52+
53+
Logger* log = Logger::getInstance("MEMORY", subComponent);
54+
55+
Debug(log, "Deleting object of type '%s' at %p", QSTRING_CSTR(typeName), static_cast<void*>(ptr));
56+
57+
if constexpr (std::is_base_of<QObject, T>::value)
58+
{
59+
QThread* thread = ptr->thread();
60+
if (thread && thread->isRunning())
61+
{
62+
ptr->deleteLater();
63+
Debug(log, "QObject<%s>::deleteLater() scheduled on thread '%s'", QSTRING_CSTR(typeName), QSTRING_CSTR(thread->objectName()));
64+
}
65+
else
66+
{
67+
delete ptr;
68+
Debug(log, "QObject<%s> deleted immediately (thread not running).", QSTRING_CSTR(typeName));
69+
}
70+
}
71+
else
72+
{
73+
delete ptr;
74+
Debug(log, "Non-QObject<%s> deleted immediately.", QSTRING_CSTR(typeName));
75+
}
76+
}
77+
78+
// Factory function template to create tracked QSharedPointer
79+
template<typename T, typename... Args>
80+
QSharedPointer<T> makeTrackedShared(Args&&... args)
81+
{
82+
T* rawPtr = new T(std::forward<Args>(args)...);
83+
84+
QString subComponent = "__";
85+
QString typeName;
86+
87+
if constexpr (std::is_base_of<QObject, T>::value)
88+
{
89+
QVariant prop = rawPtr->property("instance");
90+
if (prop.isValid() && prop.canConvert<QString>())
91+
{
92+
subComponent = prop.toString();
93+
}
94+
typeName = rawPtr->metaObject()->className();
95+
}
96+
else
97+
{
98+
typeName = typeid(T).name();
99+
}
100+
101+
Logger* log = Logger::getInstance("MEMORY", subComponent);
102+
Debug(log, "Creating object of type '%s' at %p", QSTRING_CSTR(typeName), static_cast<void*>(rawPtr));
103+
104+
return QSharedPointer<T>(rawPtr, DELETE_LATER_FN(T));
105+
}
106+
107+
#endif // TRACKEDMEMORY_H

libsrc/api/JsonAPI.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1896,17 +1896,6 @@ void JsonAPI::handleInstanceStateChange(InstanceState state, quint8 instanceID,
18961896
{
18971897
switch (state)
18981898
{
1899-
case InstanceState::H_ON_STOP:
1900-
{
1901-
if (!_hyperion.isNull() && _hyperion->getInstanceIndex() == instanceID)
1902-
{
1903-
_hyperion.reset(nullptr);
1904-
_jsonCB->setSubscriptionsTo(NO_INSTANCE_ID);
1905-
}
1906-
}
1907-
break;
1908-
1909-
case InstanceState::H_STARTING:
19101899
case InstanceState::H_STARTED:
19111900
{
19121901
quint8 const currentInstance = _currInstanceIndex;
@@ -1916,7 +1905,17 @@ void JsonAPI::handleInstanceStateChange(InstanceState state, quint8 instanceID,
19161905
_jsonCB->setSubscriptionsTo(instanceID);
19171906
}
19181907
}
1908+
break;
1909+
19191910
case InstanceState::H_STOPPED:
1911+
{
1912+
//Release reference to stopped Hyperion instance
1913+
_hyperion.clear();
1914+
}
1915+
break;
1916+
1917+
case InstanceState::H_STARTING:
1918+
case InstanceState::H_ON_STOP:
19201919
case InstanceState::H_CREATED:
19211920
case InstanceState::H_DELETED:
19221921
break;

0 commit comments

Comments
 (0)