Checkpoint

This commit is contained in:
Robin E.R. Davies
2026-02-05 11:51:43 -05:00
parent e5beb97466
commit aec88fa9f1
24 changed files with 949 additions and 306 deletions
+127 -27
View File
@@ -22,6 +22,10 @@
*/
#include "Tone3000DownloaderImpl.hpp"
#include "Tone3000DownloadProgress.hpp"
#include "Tone3000Download.hpp"
#include "Uri.hpp"
#include <functional>
using namespace pipedal;
@@ -67,9 +71,10 @@ Tone3000DownloaderImpl::handle_t Tone3000DownloaderImpl::RequestDownload(
this->requestQueue.push_back(request);
request = nullptr;
if (!this->thread)
if (!this->thread)
{
this->thread = std::make_unique<std::jthread>([this]{ this->ThreadProc(); });
this->thread = std::make_unique<std::jthread>([this]
{ this->ThreadProc(); });
}
}
this->thread_cv.notify_one();
@@ -97,7 +102,8 @@ void Tone3000DownloaderImpl::CancelDownload(
}
}
void Tone3000DownloaderImpl::Close() {
void Tone3000DownloaderImpl::Close()
{
bool notify = false;
{
std::lock_guard<std::mutex> lockGuard{this->mutex};
@@ -109,7 +115,7 @@ void Tone3000DownloaderImpl::Close() {
this->requestQueue.resize(0);
DownloadProgress progress;
Tone3000DownloadProgress progress;
fgDownloadProgress = progress;
if (listener)
@@ -121,12 +127,14 @@ void Tone3000DownloaderImpl::Close() {
activeRequest->cancelled = true;
}
}
if (notify) {
if (notify)
{
thread_cv.notify_one();
}
}
Tone3000DownloaderImpl::DownloadProgress Tone3000DownloaderImpl::GetDownloadStatus() {
DownloadProgress result;
Tone3000DownloadProgress Tone3000DownloaderImpl::GetDownloadStatus()
{
Tone3000DownloadProgress result;
{
std::lock_guard<std::mutex> lockGuard{this->mutex};
result = fgDownloadProgress;
@@ -134,47 +142,139 @@ Tone3000DownloaderImpl::DownloadProgress Tone3000DownloaderImpl::GetDownloadStat
return result;
}
void Tone3000DownloaderImpl::bgUpdateDownloadProgress(const DownloadProgress &progress)
void Tone3000DownloaderImpl::bgUpdateDownloadProgress(const Tone3000DownloadProgress &progress)
{
std::lock_guard<std::mutex> lockGuard{this->mutex};
if (closed)
if (closed)
{
return;
}
this->fgDownloadProgress = progress;
if (listener)
if (activeRequest != nullptr && !activeRequest->cancelled)
{
listener->OnTone3000Progress(this->fgDownloadProgress);
this->fgDownloadProgress = progress;
if (listener)
{
listener->OnTone3000Progress(this->fgDownloadProgress);
}
}
}
std::string Tone3000DownloaderImpl::PerformDownload(
const std::string &downloadPath,
const std::string &downloadUrl,
int64_t downloadHandle,
std::function<bool()> isCancelled)
{
std::string downloadedDirectory;
// Validate Tone3000 URL
uri downloadUri{downloadUrl};
if (!downloadUri.authority().ends_with(".tone3000.com"))
{
throw std::runtime_error("Invalid Tone3000 URL address.");
}
// Check for cancellation before starting
if (isCancelled())
{
return downloadedDirectory;
}
Tone3000DownloadProgress progress;
this->bgUpdateDownloadProgress(progress);
// Perform the download using existing code
downloadedDirectory = tone3000::DownloadTone3000Bundle(
downloadPath,
downloadUrl,
downloadHandle,
[this](const Tone3000DownloadProgress &progress)
{
this->bgUpdateDownloadProgress(progress);
},
[isCancelled]()
{
return isCancelled();
});
// Check for cancellation after download
if (isCancelled())
{
// maybe there's a partial result.
return downloadedDirectory;
}
return downloadedDirectory;
}
void Tone3000DownloaderImpl::ThreadProc()
{
while (true)
{
std::shared_ptr<DownloadRequest> downloadRequest;
std::shared_ptr<DownloadRequest> request;
Listener *currentListener = nullptr;
Tone3000DownloadProgress progress;
{
std::unique_lock lock { this->mutex};
this->activeRequest = nullptr;
std::unique_lock<std::mutex> lock{this->mutex};
thread_cv.wait(lock, [this]()
{ return this->closed || this->requestQueue.size() != 0; });
this->thread_cv.wait(lock,[this] { return this->closed || this->requestQueue.size() != 0;});
if (this->closed) {
if (closed)
{
return;
}
if (this->requestQueue.size() != 0)
if (requestQueue.empty())
{
this->activeRequest = this->requestQueue[0];
this->requestQueue.erase(requestQueue.begin());
continue;
}
downloadRequest = this->activeRequest;
}
if (!downloadRequest)
{
continue;
// Dequeue the next request
request = requestQueue.front();
requestQueue.erase(requestQueue.begin());
activeRequest = request;
currentListener = listener;
}
// Notify download started
if (currentListener)
{
currentListener->OnStartTone3000Download(request->handle, request->downloadUrl);
}
// Create cancellation predicate that checks the atomic flag
auto isCancelled = [request]() -> bool
{
return request->cancelled.load();
};
try
{
std::string outputPath = PerformDownload(request->downloadPath, request->downloadUrl, request->handle, isCancelled);
// Notify completion if not cancelled
{
std::lock_guard lockGuard{mutex};
if (!request->cancelled.load() && currentListener)
{
currentListener->OnTone3000DownloadComplete(request->handle,outputPath);
}
}
}
catch (const std::exception &e)
{
{
std::lock_guard lockGuard{mutex};
// Notify error
if (!request->cancelled.load() && currentListener)
{
currentListener->OnTone3000DownloadError(request->handle, e.what());
}
}
}
{
std::lock_guard<std::mutex> lock{this->mutex};
activeRequest = nullptr;
}
}
}