diff --git a/src/public/asyncrenderloop.cpp b/src/public/asyncrenderloop.cpp index 408ae63..34402e7 100644 --- a/src/public/asyncrenderloop.cpp +++ b/src/public/asyncrenderloop.cpp @@ -7,6 +7,7 @@ #include "asyncrenderloop.h" #include +#include namespace QH { @@ -14,7 +15,16 @@ AsyncRenderLoop::AsyncRenderLoop(QThread *thread, QObject *ptr): Async(thread, p } AsyncRenderLoop::~AsyncRenderLoop() { + +#ifdef QT_DEBUG + Q_ASSERT_X(!isRun(), __FUNCTION__, "try to delete runned render loop! Please stop before delete." + "If you the SharedPointer," + " it should be stoped monualy Or You can use AsyncRenderLoop::MainSharedPtr class"); +#endif AsyncRenderLoop::stop(); + + delete thread(); + } void QH::AsyncRenderLoop::run() { @@ -31,9 +41,12 @@ void QH::AsyncRenderLoop::run() { } void QH::AsyncRenderLoop::stop() { - m_run = false; - thread()->quit(); - thread()->wait(); + if (isRun()) { + m_run = false; + thread()->quit(); + thread()->wait(); + } + } bool AsyncRenderLoop::isRun() const { diff --git a/src/public/asyncrenderloop.h b/src/public/asyncrenderloop.h index a947bd8..f653c40 100644 --- a/src/public/asyncrenderloop.h +++ b/src/public/asyncrenderloop.h @@ -16,7 +16,7 @@ namespace QH { * @brief The AsyncRenderLoop is a class for asynchronous rendering. * This class is used to create a render loop that is executed in a separate thread. * To use this class, you must inherit from it and implement the renderIteration method. - * @example : + * **example:** : * @code{cpp} * class MyRenderLoop: public AsyncRenderLoop * { @@ -35,11 +35,92 @@ namespace QH { * * return app.exec(); * @endcode + * + * @warning This class may be broken if you use it as a QSharedPointer and push WeackPointer to the child objects. To solve this issue use the @a AsyncRenderLoop::MainSharedPtr class. + * + * Example: + * + * @code{cpp} + * class MyRenderLoop: public AsyncRenderLoop + * { + * ... + * }; + * + * int main (int argc, char* argv[]) { + * auto loop = QSharedPointer(new MyRenderLoop(new QThread())); // wrong! it will be broken + * auto loop = MyRenderLoop::MainSharedPtr>(new QThread()); // right! + * auto loop = MyRenderLoop::createMainPtr(new QThread()); // this is short version of initialization Main pointer + * ... + * return app.exec(); + * } + * @endcode */ class HEARTSHARED_EXPORT AsyncRenderLoop: public Async { + Q_OBJECT public: + + /** + * @brief The MainSharedPtr class is a helper class for creating a shared pointer to the render loop. + * @tparam T type of the render loop object. + * This class make main sharedPointer of your render loop object. it is used to solve issue with deleting object in self thread. + * + * if you use the AsyncRenderLoop as a QSharedPointer and push WeackPointer to the child objects, you must use this wrapper class. + */ + template + class MainSharedPtr { + public: + MainSharedPtr() { + static_assert(std::is_base_of_v, + "T must be derived from AsyncRenderLoop"); + } + + MainSharedPtr(const QSharedPointer& ptr): _ptr(ptr) { + static_assert(std::is_base_of_v, + "T must be derived from AsyncRenderLoop"); + } + ~MainSharedPtr() { + if (_ptr) { + _ptr->stop(); + } + } + + T* operator->() const { + return _ptr.operator->(); + } + + /** + * @brief get This is a alias of the QSharedPointer::get method. + * @return pointer to the object. + */ + T* get() const { + return _ptr.get(); + } + + /** + * @brief create This method creates a shared pointer to the render loop. + * @param arguments arguments for the constructor of the render loop object. + * @return shared pointer to the render loop. + */ + template + [[nodiscard]] static MainSharedPtr create(Args && ...arguments) { + return MainSharedPtr(QSharedPointer::create(std::forward(arguments)...)); + } + + /** + * @brief getShared This method return child shared pointer. You can use them as a general shared pointer of the object. + * @return reference to the object. + */ + const QSharedPointer& getShared() const { + return _ptr; + } + + private: + QSharedPointer _ptr; + }; + + AsyncRenderLoop(QThread* thread, QObject* ptr = nullptr); ~AsyncRenderLoop(); @@ -59,6 +140,18 @@ public: */ bool isRun() const; + /** + * @brief createMainPtr This method creates a shared pointer to the render loop. + * @tparam Type type of the render loop object. + * @tparam Args arguments for the constructor of the render loop object. + * @param arguments arguments for the constructor of the render loop object. + * @return shared pointer to the render loop. + */ + template + static MainSharedPtr createMainPtr(Args && ...arguments) { + return MainSharedPtr(QSharedPointer::create(std::forward(arguments)...)); + }; + protected: /** @@ -79,4 +172,5 @@ private: }; } + #endif // ASYNCRENDERLOOP_H diff --git a/src/public/streammultiversion.cpp b/src/public/streammultiversion.cpp index e664611..dbf1750 100644 --- a/src/public/streammultiversion.cpp +++ b/src/public/streammultiversion.cpp @@ -7,18 +7,19 @@ StreamMultiversion::StreamMultiversion() { } -QDataStream &StreamMultiversion::fromStream(QDataStream &stream) { - stream >> _realVersion ; - return stream; +StreamMultiversion::~StreamMultiversion() { + } -QDataStream &StreamMultiversion::toStream(QDataStream &stream) const { - stream << _realVersion; - - return stream; +void StreamMultiversion::saveVersion(char version, QDataStream &stream) const { + stream << version; } -int StreamMultiversion::realVersion() const { - return _realVersion; +char StreamMultiversion::readVersion(QDataStream &stream) { + char version; + stream >> version; + + return version; + } } diff --git a/src/public/streammultiversion.h b/src/public/streammultiversion.h index 744a3e1..0030335 100644 --- a/src/public/streammultiversion.h +++ b/src/public/streammultiversion.h @@ -14,34 +14,55 @@ namespace QH { /** * @brief The StreamMultiversion class this parser works with simple multiversion packages. + * + * This class used to save and read version of the object in file. + * + * @see StreamBase + * + * @code{cpp} + * class myClass: public StreamMultiversion { + * protected: + * QDataStream &fromStream(QDataStream &stream) override { + * char version = readVersion(); + * return stream; + * } + * + * QDataStream &toStream(QDataStream &stream) const override { + * saveVersion(1, stream); + * return stream; + * } + * + * } + * */ class HEARTSHARED_EXPORT StreamMultiversion: public StreamBase { public: StreamMultiversion(); - + ~StreamMultiversion(); // StreamBase interface - /** - * @brief version override this method to sets version of package. - * @return - */ - virtual int version() const = 0; /** - * @brief realVersion This method return value of the version that was be saved in the bytes array. - * @return - * @note use this method to check version of read package in the fromStream method.. + * @brief saveVersion save version of the object to the stream. + * @param version - version of the object. + * @param stream - stream to save. + * + * This method used to save version of the object in file. + * @see toStream */ - virtual int realVersion() const; -protected: - QDataStream &fromStream(QDataStream &stream) override; - QDataStream &toStream(QDataStream &stream) const override; + void saveVersion(char version, QDataStream &stream) const; + + /** + * @brief readVersion read version of the object from the stream. + * @param stream - stream to read. + * @return version of the object. + * @see fromStream + + */ + char readVersion(QDataStream &stream); - -private: - int _realVersion = 0; }; } #endif // STREAMMULTIVERSION_H