From 14302ddbac1e6d9c95de15c97362c3de09f545eb Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 7 Oct 2016 16:20:20 +0900 Subject: Fixed massive leaks of Event objects --- connection.cpp | 3 +-- jobs/syncjob.cpp | 2 +- jobs/syncjob.h | 37 +++++++++++++++++++++++++++++++++---- room.cpp | 6 +++--- room.h | 6 +++--- 5 files changed, 41 insertions(+), 13 deletions(-) diff --git a/connection.cpp b/connection.cpp index 9f56ec96..bc6d1f26 100644 --- a/connection.cpp +++ b/connection.cpp @@ -18,7 +18,6 @@ #include "connection.h" #include "connectiondata.h" -//#include "connectionprivate.h" #include "user.h" #include "events/event.h" #include "room.h" @@ -172,7 +171,7 @@ void Connection::sync(int timeout) auto job = d->startSyncJob(filter, timeout); connect( job, &SyncJob::success, [=] () { d->data->setLastEvent(job->nextBatch()); - for( const auto& roomData: job->roomData() ) + for( auto& roomData: job->roomData() ) { if ( Room* r = provideRoom(roomData.roomId) ) r->updateData(roomData); diff --git a/jobs/syncjob.cpp b/jobs/syncjob.cpp index 2b2705b1..59c40785 100644 --- a/jobs/syncjob.cpp +++ b/jobs/syncjob.cpp @@ -83,7 +83,7 @@ QString SyncJob::nextBatch() const return d->nextBatch; } -const SyncData& SyncJob::roomData() const +SyncData& SyncJob::roomData() { return d->roomData; } diff --git a/jobs/syncjob.h b/jobs/syncjob.h index ed99b38b..55d7458c 100644 --- a/jobs/syncjob.h +++ b/jobs/syncjob.h @@ -26,10 +26,34 @@ namespace QMatrixClient { + /** + * @brief A crude wrapper around a container of pointers that owns pointers + * to contained objects + * + * Similar to vector>, upon deletion, EventsHolder + * will delete all events contained in it. + */ + template + class Owning : public ContainerT + { + public: + Owning() = default; + Owning(Owning&) = delete; + Owning(Owning&& other) : ContainerT(std::move(other)) { } + ~Owning() { for (auto e: *this) delete e; } + + /** + * @brief returns the underlying events and releases the ownership + * + * Acts similar to unique_ptr::release. + */ + ContainerT release() { return std::move(*this); } + }; + class SyncRoomData { public: - class EventList : public Events + class EventList : public Owning { private: QString jsonKey; @@ -55,7 +79,13 @@ namespace QMatrixClient JoinState joinState_ = JoinState::Join, const QJsonObject& room_ = QJsonObject()); }; - using SyncData = QVector; +} +Q_DECLARE_TYPEINFO(QMatrixClient::SyncRoomData, Q_MOVABLE_TYPE); + +namespace QMatrixClient +{ + // QVector cannot work with non-copiable objects, std::vector can. + using SyncData = std::vector; class ConnectionData; class SyncJob: public BaseJob @@ -69,7 +99,7 @@ namespace QMatrixClient void setPresence(QString presence); void setTimeout(int timeout); - const SyncData& roomData() const; + SyncData& roomData(); QString nextBatch() const; protected: @@ -82,6 +112,5 @@ namespace QMatrixClient Private* d; }; } -Q_DECLARE_TYPEINFO(QMatrixClient::SyncRoomData, Q_MOVABLE_TYPE); #endif // QMATRIXCLIENT_SYNCJOB_H diff --git a/room.cpp b/room.cpp index c693898f..e07426a7 100644 --- a/room.cpp +++ b/room.cpp @@ -119,7 +119,7 @@ QString Room::id() const return d->id; } -Room::Timeline Room::messageEvents() const +const Room::Timeline& Room::messageEvents() const { return d->messageEvents; } @@ -329,7 +329,7 @@ QString Room::roomMembername(QString userId) const return roomMembername(connection()->user(userId)); } -void Room::updateData(const SyncRoomData& data) +void Room::updateData(SyncRoomData& data) { if( d->prevBatch.isEmpty() ) d->prevBatch = data.timelinePrevBatch; @@ -339,7 +339,7 @@ void Room::updateData(const SyncRoomData& data) // State changes can arrive in a timeline event; so check those. processStateEvents(data.timeline); - addNewMessageEvents(data.timeline); + addNewMessageEvents(data.timeline.release()); for( Event* ephemeralEvent: data.ephemeral ) { diff --git a/room.h b/room.h index 1c29aa01..7266ae70 100644 --- a/room.h +++ b/room.h @@ -37,13 +37,13 @@ namespace QMatrixClient { Q_OBJECT public: - using Timeline = Events; + using Timeline = Owning; Room(Connection* connection, QString id); virtual ~Room(); Q_INVOKABLE QString id() const; - Q_INVOKABLE Timeline messageEvents() const; + Q_INVOKABLE const Timeline& messageEvents() const; Q_INVOKABLE QString name() const; Q_INVOKABLE QStringList aliases() const; Q_INVOKABLE QString canonicalAlias() const; @@ -66,7 +66,7 @@ namespace QMatrixClient */ Q_INVOKABLE QString roomMembername(QString userId) const; - Q_INVOKABLE void updateData( const SyncRoomData& data ); + Q_INVOKABLE void updateData(SyncRoomData& data ); Q_INVOKABLE void setJoinState( JoinState state ); Q_INVOKABLE void markMessageAsRead( Event* event ); -- cgit v1.2.3