* Fixed a bug where queries may be enqueued into the library during

shutdown, and run after calling components have been destroyed.

* Fixed a bug in PlaybackService where the "ModeChanged" event wasn't
getting called after shuffling, and sometimes not on the MessageQueue
thread.
This commit is contained in:
casey langen 2017-02-01 23:21:27 -08:00
parent 7721f7d412
commit 5b9338c61e
5 changed files with 64 additions and 33 deletions

View File

@ -206,7 +206,6 @@ void PlaybackService::PrepareNextTrack() {
void PlaybackService::SetRepeatMode(RepeatMode mode) {
if (this->repeatMode != mode) {
this->repeatMode = mode;
this->ModeChanged();
POST(this, MESSAGE_PREPARE_NEXT_TRACK, NO_POSITION, 0);
POST(this, MESSAGE_MODE_CHANGED, 0, 0);
}
@ -244,6 +243,8 @@ void PlaybackService::ToggleShuffle() {
POST(this, MESSAGE_PREPARE_NEXT_TRACK, NO_POSITION, 0);
}
}
POST(this, MESSAGE_MODE_CHANGED, 0, 0);
}
void PlaybackService::ProcessMessage(IMessage &message) {
@ -323,6 +324,7 @@ void PlaybackService::ProcessMessage(IMessage &message) {
for (auto it = remotes.begin(); it != remotes.end(); it++) {
(*it)->OnModeChanged(repeatMode, shuffled);
}
this->ModeChanged();
}
else if (type == MESSAGE_TIME_CHANGED) {
this->TimeChanged(transport.Position());

View File

@ -58,6 +58,7 @@ namespace musik { namespace core {
virtual int Id() = 0;
virtual const std::string& Name() = 0;
virtual void SetMessageQueue(musik::core::runtime::IMessageQueue& queue) = 0;
virtual void Close() = 0;
};
typedef std::shared_ptr<ILibrary> ILibraryPtr;

View File

@ -81,6 +81,10 @@ ILibraryPtr LibraryFactory::AddLibrary(int id, int type, const std::string& name
}
void LibraryFactory::Shutdown() {
for (ILibraryPtr library : this->libraries) {
library->Close();
}
Instance().libraries.clear();
}

View File

@ -98,10 +98,7 @@ LocalLibrary::LocalLibrary(std::string name,int id)
}
LocalLibrary::~LocalLibrary() {
this->Exit();
this->thread->join();
delete this->thread;
delete this->indexer;
this->Close();
}
int LocalLibrary::Id() {
@ -112,6 +109,32 @@ const std::string& LocalLibrary::Name() {
return this->name;
}
void LocalLibrary::Close() {
std::thread* thread = nullptr;
{
std::unique_lock<std::mutex> lock(this->mutex);
if (this->indexer) {
delete this->indexer;
this->indexer = nullptr;
}
if (this->thread) {
thread = this->thread;
this->thread = nullptr;
this->exit = true;
this->queryQueue.clear();
this->Exit();
}
}
if (thread) {
thread->join();
delete thread;
}
}
std::string LocalLibrary::GetLibraryDirectory() {
std::string directory(musik::core::GetDataDirectory());
@ -134,7 +157,11 @@ std::string LocalLibrary::GetDatabaseFilename() {
}
int LocalLibrary::Enqueue(IQueryPtr query, unsigned int options) {
std::unique_lock<std::recursive_mutex> lock(this->mutex);
std::unique_lock<std::mutex> lock(this->mutex);
if (this->exit) { /* closed */
return -1;
}
if (options & ILibrary::QuerySynchronous) {
this->RunQuery(query, false); /* false = do not notify via QueryCompleted */
@ -152,20 +179,34 @@ int LocalLibrary::Enqueue(IQueryPtr query, unsigned int options) {
}
bool LocalLibrary::Exited() {
std::unique_lock<std::recursive_mutex> lock(this->mutex);
return this->exit;
}
void LocalLibrary::Exit() {
{
std::unique_lock<std::recursive_mutex> lock(this->mutex);
this->exit = true;
}
/* kick sleeping threads back to the top of the loop */
this->exit = true;
this->queueCondition.notify_all();
}
void LocalLibrary::ThreadProc() {
IQueryPtr query;
while (true) {
std::unique_lock<std::mutex> lock(this->mutex);
if (query = GetNextQuery()) {
this->RunQuery(query);
}
if (!this->queryQueue.size() && !this->Exited()) {
this->queueCondition.wait(lock);
}
if (this->Exited()) {
return;
}
}
}
IQueryPtr LocalLibrary::GetNextQuery() {
if (queryQueue.size()) {
IQueryPtr front = queryQueue.front();
@ -206,24 +247,6 @@ void LocalLibrary::RunQuery(IQueryPtr query, bool notify) {
}
}
void LocalLibrary::ThreadProc() {
while (!this->Exited()) {
IQueryPtr query;
{
std::unique_lock<std::recursive_mutex> lock(this->mutex);
query = GetNextQuery();
while (!query && !this->Exited()) {
this->queueCondition.wait(lock);
query = GetNextQuery();
}
}
this->RunQuery(query);
}
}
void LocalLibrary::SetMessageQueue(musik::core::runtime::IMessageQueue& queue) {
this->messageQueue = &queue;
}

View File

@ -74,6 +74,7 @@ namespace musik { namespace core { namespace library {
virtual int Id();
virtual const std::string& Name();
virtual void SetMessageQueue(musik::core::runtime::IMessageQueue& queue);
virtual void Close();
/* IMessageTarget */
virtual void ProcessMessage(musik::core::runtime::IMessage &message);
@ -107,8 +108,8 @@ namespace musik { namespace core { namespace library {
bool exit;
std::thread* thread;
std::condition_variable_any queueCondition;
std::recursive_mutex mutex;
std::condition_variable queueCondition;
std::mutex mutex;
core::IIndexer *indexer;
core::db::Connection db;