This repository has been archived on 2025-03-20. You can view files and clone it, but cannot push or open issues or pull requests.
The-Powder-Toy/src/client/DownloadManager.cpp
2016-03-27 11:46:30 -04:00

145 lines
3.3 KiB
C++

#include "DownloadManager.h"
#include "Download.h"
#include "HTTP.h"
#include "Config.h"
#include "Platform.h"
DownloadManager::DownloadManager():
threadStarted(false),
lastUsed(time(NULL)),
managerRunning(false),
managerShutdown(false),
downloads(NULL),
downloadsAddQueue(NULL)
{
pthread_mutex_init(&downloadLock, NULL);
pthread_mutex_init(&downloadAddLock, NULL);
}
DownloadManager::~DownloadManager()
{
}
void DownloadManager::Shutdown()
{
pthread_mutex_lock(&downloadLock);
pthread_mutex_lock(&downloadAddLock);
for (std::vector<Download*>::iterator iter = downloads.begin(); iter != downloads.end(); ++iter)
{
Download *download = (*iter);
if (download->http)
http_force_close(download->http);
download->downloadCanceled = true;
delete download;
}
downloads.clear();
downloadsAddQueue.clear();
managerShutdown = true;
pthread_mutex_unlock(&downloadAddLock);
pthread_mutex_unlock(&downloadLock);
pthread_join(downloadThread, NULL);
}
//helper function for download
TH_ENTRY_POINT void* DownloadManagerHelper(void* obj)
{
DownloadManager *temp = (DownloadManager*)obj;
temp->Update();
return NULL;
}
void DownloadManager::Start()
{
managerRunning = true;
lastUsed = time(NULL);
pthread_create(&downloadThread, NULL, &DownloadManagerHelper, this);
}
void DownloadManager::Update()
{
unsigned int numActiveDownloads;
while (!managerShutdown)
{
pthread_mutex_lock(&downloadAddLock);
if (downloadsAddQueue.size())
{
for (size_t i = 0; i < downloadsAddQueue.size(); i++)
{
downloads.push_back(downloadsAddQueue[i]);
}
downloadsAddQueue.clear();
}
pthread_mutex_unlock(&downloadAddLock);
if (downloads.size())
{
numActiveDownloads = 0;
pthread_mutex_lock(&downloadLock);
for (size_t i = 0; i < downloads.size(); i++)
{
Download *download = downloads[i];
if (download->downloadCanceled)
{
if (download->http && download->downloadStarted)
http_force_close(download->http);
delete download;
downloads.erase(downloads.begin()+i);
i--;
}
else if (download->downloadStarted && !download->downloadFinished)
{
if (http_async_req_status(download->http) != 0)
{
download->downloadData = http_async_req_stop(download->http, &download->downloadStatus, &download->downloadSize);
download->downloadFinished = true;
if (!download->keepAlive)
download->http = NULL;
}
lastUsed = time(NULL);
numActiveDownloads++;
}
}
pthread_mutex_unlock(&downloadLock);
}
if (time(NULL) > lastUsed+http_timeout*2 && !numActiveDownloads)
{
pthread_mutex_lock(&downloadLock);
managerRunning = false;
pthread_mutex_unlock(&downloadLock);
return;
}
Platform::Millisleep(1);
}
}
void DownloadManager::EnsureRunning()
{
pthread_mutex_lock(&downloadLock);
if (!managerRunning)
{
if (threadStarted)
pthread_join(downloadThread, NULL);
else
threadStarted = true;
Start();
}
pthread_mutex_unlock(&downloadLock);
}
void DownloadManager::AddDownload(Download *download)
{
pthread_mutex_lock(&downloadAddLock);
downloadsAddQueue.push_back(download);
pthread_mutex_unlock(&downloadAddLock);
EnsureRunning();
}
void DownloadManager::Lock()
{
pthread_mutex_lock(&downloadAddLock);
}
void DownloadManager::Unlock()
{
pthread_mutex_unlock(&downloadAddLock);
}