Safely close database connections and delete backends
Also fix NewClosure leak caused by disconnected object signals
This commit is contained in:
@@ -20,8 +20,11 @@
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <assert.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QApplication>
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#include <QIODevice>
|
||||
#include <QDir>
|
||||
@@ -56,7 +59,36 @@ using std::shared_ptr;
|
||||
const int PlaylistBackend::kSongTableJoins = 2;
|
||||
|
||||
PlaylistBackend::PlaylistBackend(Application *app, QObject *parent)
|
||||
: QObject(parent), app_(app), db_(app_->database()) {}
|
||||
: QObject(parent), app_(app), db_(app_->database()), original_thread_(nullptr) {
|
||||
|
||||
original_thread_ = thread();
|
||||
|
||||
}
|
||||
|
||||
PlaylistBackend::~PlaylistBackend() {}
|
||||
|
||||
void PlaylistBackend::Close() {
|
||||
|
||||
if (db_) {
|
||||
QMutexLocker l(db_->Mutex());
|
||||
db_->Close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PlaylistBackend::ExitAsync() {
|
||||
metaObject()->invokeMethod(this, "Exit", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void PlaylistBackend::Exit() {
|
||||
|
||||
assert(QThread::currentThread() == thread());
|
||||
|
||||
Close();
|
||||
moveToThread(original_thread_);
|
||||
emit ExitFinished();
|
||||
|
||||
}
|
||||
|
||||
PlaylistBackend::PlaylistList PlaylistBackend::GetAllPlaylists() {
|
||||
return GetPlaylists(GetPlaylists_All);
|
||||
@@ -157,6 +189,10 @@ QSqlQuery PlaylistBackend::GetPlaylistRows(int playlist) {
|
||||
q.bindValue(":playlist", playlist);
|
||||
q.exec();
|
||||
|
||||
if (QThread::currentThread() != thread() && QThread::currentThread() != qApp->thread()) {
|
||||
db_->Close();
|
||||
}
|
||||
|
||||
return q;
|
||||
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "collection/sqlrow.h"
|
||||
#include "playlistitem.h"
|
||||
|
||||
class QThread;
|
||||
class Application;
|
||||
class Database;
|
||||
|
||||
@@ -47,6 +48,7 @@ class PlaylistBackend : public QObject {
|
||||
|
||||
public:
|
||||
Q_INVOKABLE PlaylistBackend(Application *app, QObject *parent = nullptr);
|
||||
~PlaylistBackend();
|
||||
|
||||
struct Playlist {
|
||||
Playlist() : id(-1), favorite(false), last_played(0) {}
|
||||
@@ -62,6 +64,9 @@ class PlaylistBackend : public QObject {
|
||||
|
||||
static const int kSongTableJoins;
|
||||
|
||||
void Close();
|
||||
void ExitAsync();
|
||||
|
||||
PlaylistList GetAllPlaylists();
|
||||
PlaylistList GetAllOpenPlaylists();
|
||||
PlaylistList GetAllFavoritePlaylists();
|
||||
@@ -82,8 +87,12 @@ class PlaylistBackend : public QObject {
|
||||
Application *app() const { return app_; }
|
||||
|
||||
public slots:
|
||||
void Exit();
|
||||
void SavePlaylist(int playlist, const PlaylistItemList &items, int last_played);
|
||||
|
||||
signals:
|
||||
void ExitFinished();
|
||||
|
||||
private:
|
||||
struct NewSongFromQueryState {
|
||||
QHash<QString, SongList> cached_cues_;
|
||||
@@ -105,6 +114,7 @@ class PlaylistBackend : public QObject {
|
||||
|
||||
Application *app_;
|
||||
Database *db_;
|
||||
QThread *original_thread_;
|
||||
};
|
||||
|
||||
#endif // PLAYLISTBACKEND_H
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QApplication>
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <QtConcurrentRun>
|
||||
@@ -363,6 +364,10 @@ TagCompletionModel::TagCompletionModel(CollectionBackend *backend, Playlist::Col
|
||||
setStringList(backend->GetAll(col));
|
||||
}
|
||||
|
||||
if (QThread::currentThread() != backend->thread() && QThread::currentThread() != qApp->thread()) {
|
||||
backend->Close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QString TagCompletionModel::database_column(Playlist::Column column) {
|
||||
|
||||
@@ -80,6 +80,7 @@ class PlaylistHeader;
|
||||
class PlaylistProxyStyle : public QProxyStyle {
|
||||
public:
|
||||
PlaylistProxyStyle(QStyle *base);
|
||||
|
||||
void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const;
|
||||
void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user