lyrics fetcher: limit number of worker threads downloading lyrics in background

This commit is contained in:
Andrzej Rybczak
2011-12-29 18:47:44 +01:00
parent e8f08ea884
commit 91477e034d
2 changed files with 58 additions and 16 deletions

View File

@@ -39,7 +39,9 @@ using Global::myOldScreen;
#ifdef HAVE_CURL_CURL_H
LyricsFetcher **Lyrics::itsFetcher = 0;
std::set<MPD::Song *> Lyrics::itsDownloaded;
std::queue<MPD::Song *> Lyrics::itsToDownload;
pthread_mutex_t Lyrics::itsDIBLock = PTHREAD_MUTEX_INITIALIZER;
size_t Lyrics::itsWorkersNumber = 0;
#endif // HAVE_CURL_CURL_H
Lyrics *myLyrics = new Lyrics;
@@ -106,7 +108,7 @@ void Lyrics::SwitchTo()
if (isReadyToTake)
Take();
if (isDownloadInProgress || !itsDownloaded.empty())
if (isDownloadInProgress || itsWorkersNumber > 0)
{
ShowMessage("Lyrics are being downloaded...");
return;
@@ -170,20 +172,56 @@ void Lyrics::DownloadInBackground(const MPD::Song *s)
return;
}
ShowMessage("Fetching lyrics for %s...", s->toString(Config.song_status_format_no_colors).c_str());
// we need to copy it and store separetely since this song may get deleted in the meantime.
MPD::Song *s_copy = new MPD::Song(*s);
itsDownloaded.insert(s_copy);
pthread_t t;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&t, &attr, DownloadInBackgroundImpl, s_copy);
pthread_mutex_lock(&itsDIBLock);
if (itsWorkersNumber == itsMaxWorkersNumber)
itsToDownload.push(s_copy);
else
{
++itsWorkersNumber;
pthread_t t;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&t, &attr, DownloadInBackgroundImpl, s_copy);
}
pthread_mutex_unlock(&itsDIBLock);
}
void *Lyrics::DownloadInBackgroundImpl(void *void_ptr)
{
MPD::Song *s = static_cast<MPD::Song *>(void_ptr);
DownloadInBackgroundImplHelper(s);
delete s;
while (true)
{
pthread_mutex_lock(&itsDIBLock);
if (itsToDownload.empty())
{
pthread_mutex_unlock(&itsDIBLock);
break;
}
else
{
s = itsToDownload.front();
itsToDownload.pop();
pthread_mutex_unlock(&itsDIBLock);
}
DownloadInBackgroundImplHelper(s);
delete s;
}
pthread_mutex_lock(&itsDIBLock);
--itsWorkersNumber;
pthread_mutex_unlock(&itsDIBLock);
pthread_exit(0);
}
void Lyrics::DownloadInBackgroundImplHelper(MPD::Song *s)
{
std::string artist = Curl::escape(locale_to_utf_cpy(s->GetArtist()));
std::string title = Curl::escape(locale_to_utf_cpy(s->GetTitle()));
@@ -199,11 +237,6 @@ void *Lyrics::DownloadInBackgroundImpl(void *void_ptr)
}
if (result.first == true)
Save(GenerateFilename(*s), result.second);
delete s;
itsDownloaded.erase(s);
pthread_exit(0);
}
void *Lyrics::Download()

View File

@@ -22,6 +22,7 @@
#define _LYRICS_H
#include <pthread.h>
#include <queue>
#include "ncmpcpp.h"
#include "mpdpp.h"
@@ -72,8 +73,16 @@ class Lyrics : public Screen<Scrollpad>
# ifdef HAVE_CURL_CURL_H
static void *DownloadInBackgroundImpl(void *);
// storage for songs for which lyrics are being downloaded at the moment
static std::set<MPD::Song *> itsDownloaded;
static void DownloadInBackgroundImplHelper(MPD::Song *);
// lock for allowing exclusive access to itsToDownload and itsWorkersNumber
static pthread_mutex_t itsDIBLock;
// storage for songs for which lyrics are scheduled to be downloaded
static std::queue<MPD::Song *> itsToDownload;
// current worker threads (ie. downloading lyrics)
static size_t itsWorkersNumber;
// maximum number of worker threads. if it's reached, next lyrics requests
// are put into itsToDownload queue.
static const size_t itsMaxWorkersNumber = 4;
void *Download();
static void *DownloadWrapper(void *);