mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 13:30:02 +00:00
Loaders: Add cancelation to all file loaders.
Mainly, for HTTP which might be stalled trying to connect (especially if you're not near your PC right now and it's in your recent, for example.)
This commit is contained in:
parent
6e3cb0cd48
commit
ee5b68f1fc
@ -25,7 +25,7 @@
|
||||
|
||||
// Takes ownership of backend.
|
||||
CachingFileLoader::CachingFileLoader(FileLoader *backend)
|
||||
: filesize_(0), backend_(backend), exists_(-1), isDirectory_(-1), aheadThread_(false) {
|
||||
: backend_(backend) {
|
||||
}
|
||||
|
||||
void CachingFileLoader::Prepare() {
|
||||
@ -288,3 +288,7 @@ void CachingFileLoader::StartReadAhead(s64 pos) {
|
||||
});
|
||||
th.detach();
|
||||
}
|
||||
|
||||
void CachingFileLoader::Cancel() {
|
||||
backend_->Cancel();
|
||||
}
|
||||
|
@ -39,6 +39,8 @@ public:
|
||||
}
|
||||
size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override;
|
||||
|
||||
void Cancel() override;
|
||||
|
||||
private:
|
||||
void Prepare();
|
||||
void InitCache();
|
||||
@ -57,10 +59,10 @@ private:
|
||||
BLOCK_READAHEAD = 4,
|
||||
};
|
||||
|
||||
s64 filesize_;
|
||||
s64 filesize_ = 0;
|
||||
FileLoader *backend_;
|
||||
int exists_;
|
||||
int isDirectory_;
|
||||
int exists_ = -1;
|
||||
int isDirectory_ = -1;
|
||||
u64 generation_;
|
||||
u64 oldestGeneration_;
|
||||
size_t cacheSize_;
|
||||
@ -77,6 +79,6 @@ private:
|
||||
|
||||
std::map<s64, BlockInfo> blocks_;
|
||||
std::recursive_mutex blocksMutex_;
|
||||
bool aheadThread_;
|
||||
bool aheadThread_ = false;
|
||||
std::once_flag preparedFlag_;
|
||||
};
|
||||
|
@ -41,19 +41,16 @@ std::mutex DiskCachingFileLoader::cachesMutex_;
|
||||
|
||||
// Takes ownership of backend.
|
||||
DiskCachingFileLoader::DiskCachingFileLoader(FileLoader *backend)
|
||||
: prepared_(false), filesize_(0), backend_(backend), cache_(nullptr) {
|
||||
: backend_(backend) {
|
||||
}
|
||||
|
||||
void DiskCachingFileLoader::Prepare() {
|
||||
if (prepared_) {
|
||||
return;
|
||||
}
|
||||
prepared_ = true;
|
||||
|
||||
filesize_ = backend_->FileSize();
|
||||
if (filesize_ > 0) {
|
||||
InitCache();
|
||||
}
|
||||
std::call_once(preparedFlag_, [this]() {
|
||||
filesize_ = backend_->FileSize();
|
||||
if (filesize_ > 0) {
|
||||
InitCache();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
DiskCachingFileLoader::~DiskCachingFileLoader() {
|
||||
@ -118,6 +115,10 @@ size_t DiskCachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data,
|
||||
return readSize;
|
||||
}
|
||||
|
||||
void DiskCachingFileLoader::Cancel() {
|
||||
backend_->Cancel();
|
||||
}
|
||||
|
||||
std::vector<std::string> DiskCachingFileLoader::GetCachedPathsInUse() {
|
||||
std::lock_guard<std::mutex> guard(cachesMutex_);
|
||||
|
||||
@ -156,7 +157,7 @@ void DiskCachingFileLoader::ShutdownCache() {
|
||||
}
|
||||
|
||||
DiskCachingFileLoaderCache::DiskCachingFileLoaderCache(const std::string &path, u64 filesize)
|
||||
: refCount_(0), filesize_(filesize), origPath_(path), f_(nullptr), fd_(0) {
|
||||
: filesize_(filesize), origPath_(path) {
|
||||
InitCache(path);
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,8 @@ public:
|
||||
}
|
||||
size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override;
|
||||
|
||||
void Cancel() override;
|
||||
|
||||
static std::vector<std::string> GetCachedPathsInUse();
|
||||
|
||||
private:
|
||||
@ -50,10 +52,10 @@ private:
|
||||
void InitCache();
|
||||
void ShutdownCache();
|
||||
|
||||
bool prepared_;
|
||||
s64 filesize_;
|
||||
std::once_flag preparedFlag_;
|
||||
s64 filesize_ = 0;
|
||||
FileLoader *backend_;
|
||||
DiskCachingFileLoaderCache *cache_;
|
||||
DiskCachingFileLoaderCache *cache_ = nullptr;
|
||||
|
||||
// We don't support concurrent disk cache access (we use memory cached indexes.)
|
||||
// So we have to ensure there's only one of these per.
|
||||
@ -139,7 +141,7 @@ private:
|
||||
INVALID_INDEX = 0xFFFFFFFF,
|
||||
};
|
||||
|
||||
int refCount_;
|
||||
int refCount_ = 0;
|
||||
s64 filesize_;
|
||||
u32 blockSize_;
|
||||
u16 generation_;
|
||||
@ -176,8 +178,8 @@ private:
|
||||
std::vector<BlockInfo> index_;
|
||||
std::vector<u32> blockIndexLookup_;
|
||||
|
||||
FILE *f_;
|
||||
int fd_;
|
||||
FILE *f_ = nullptr;
|
||||
int fd_ = 0;
|
||||
|
||||
static std::string cacheDir_;
|
||||
};
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "Core/FileLoaders/HTTPFileLoader.h"
|
||||
|
||||
HTTPFileLoader::HTTPFileLoader(const std::string &filename)
|
||||
: filesize_(0), filepos_(0), url_(filename), filename_(filename), connected_(false) {
|
||||
: url_(filename), filename_(filename) {
|
||||
}
|
||||
|
||||
void HTTPFileLoader::Prepare() {
|
||||
@ -33,6 +33,10 @@ void HTTPFileLoader::Prepare() {
|
||||
}
|
||||
|
||||
Connect();
|
||||
if (!connected_) {
|
||||
return;
|
||||
}
|
||||
|
||||
int err = client_.SendRequest("HEAD", url_.Resource().c_str());
|
||||
if (err < 0) {
|
||||
Disconnect();
|
||||
@ -123,6 +127,9 @@ size_t HTTPFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags f
|
||||
}
|
||||
|
||||
Connect();
|
||||
if (!connected_) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char requestHeaders[4096];
|
||||
// Note that the Range header is *inclusive*.
|
||||
@ -186,3 +193,11 @@ size_t HTTPFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags f
|
||||
filepos_ = absolutePos + readBytes;
|
||||
return readBytes;
|
||||
}
|
||||
|
||||
void HTTPFileLoader::Connect() {
|
||||
if (!connected_) {
|
||||
cancelConnect_ = false;
|
||||
// Latency is important here, so reduce the timeout.
|
||||
connected_ = client_.Connect(3, 10.0, &cancelConnect_);
|
||||
}
|
||||
}
|
||||
|
@ -41,14 +41,14 @@ public:
|
||||
}
|
||||
virtual size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override;
|
||||
|
||||
void Cancel() override {
|
||||
cancelConnect_ = true;
|
||||
}
|
||||
|
||||
private:
|
||||
void Prepare();
|
||||
|
||||
void Connect() {
|
||||
if (!connected_) {
|
||||
connected_ = client_.Connect();
|
||||
}
|
||||
}
|
||||
void Connect();
|
||||
|
||||
void Disconnect() {
|
||||
if (connected_) {
|
||||
@ -57,12 +57,13 @@ private:
|
||||
connected_ = false;
|
||||
}
|
||||
|
||||
s64 filesize_;
|
||||
s64 filepos_;
|
||||
s64 filesize_ = 0;
|
||||
s64 filepos_ = 0;
|
||||
Url url_;
|
||||
http::Client client_;
|
||||
std::string filename_;
|
||||
bool connected_;
|
||||
bool connected_ = false;
|
||||
bool cancelConnect_ = false;
|
||||
|
||||
std::once_flag preparedFlag_;
|
||||
std::mutex readAtMutex_;
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
// Takes ownership of backend.
|
||||
RamCachingFileLoader::RamCachingFileLoader(FileLoader *backend)
|
||||
: filesize_(0), backend_(backend), exists_(-1), isDirectory_(-1), aheadThread_(false) {
|
||||
: backend_(backend) {
|
||||
filesize_ = backend->FileSize();
|
||||
if (filesize_ > 0) {
|
||||
InitCache();
|
||||
@ -107,11 +107,7 @@ void RamCachingFileLoader::InitCache() {
|
||||
}
|
||||
|
||||
void RamCachingFileLoader::ShutdownCache() {
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(blocksMutex_);
|
||||
// Try to have the thread stop.
|
||||
aheadRemaining_ = 0;
|
||||
}
|
||||
Cancel();
|
||||
|
||||
// We can't delete while the thread is running, so have to wait.
|
||||
// This should only happen from the menu.
|
||||
@ -127,6 +123,15 @@ void RamCachingFileLoader::ShutdownCache() {
|
||||
}
|
||||
}
|
||||
|
||||
void RamCachingFileLoader::Cancel() {
|
||||
if (aheadThread_) {
|
||||
std::lock_guard<std::mutex> guard(blocksMutex_);
|
||||
aheadCancel_ = true;
|
||||
}
|
||||
|
||||
backend_->Cancel();
|
||||
}
|
||||
|
||||
size_t RamCachingFileLoader::ReadFromCache(s64 pos, size_t bytes, void *data) {
|
||||
s64 cacheStartPos = pos >> BLOCK_SHIFT;
|
||||
s64 cacheEndPos = (pos + bytes - 1) >> BLOCK_SHIFT;
|
||||
@ -220,10 +225,11 @@ void RamCachingFileLoader::StartReadAhead(s64 pos) {
|
||||
}
|
||||
|
||||
aheadThread_ = true;
|
||||
aheadCancel_ = false;
|
||||
std::thread th([this] {
|
||||
setCurrentThreadName("FileLoaderReadAhead");
|
||||
|
||||
while (aheadRemaining_ != 0) {
|
||||
while (aheadRemaining_ != 0 && !aheadCancel_) {
|
||||
// Where should we look?
|
||||
const u32 cacheStartPos = NextAheadBlock();
|
||||
if (cacheStartPos == 0xFFFFFFFF) {
|
||||
|
@ -39,6 +39,8 @@ public:
|
||||
}
|
||||
size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override;
|
||||
|
||||
void Cancel() override;
|
||||
|
||||
private:
|
||||
void InitCache();
|
||||
void ShutdownCache();
|
||||
@ -55,15 +57,16 @@ private:
|
||||
BLOCK_READAHEAD = 4,
|
||||
};
|
||||
|
||||
s64 filesize_;
|
||||
s64 filesize_ = 0;
|
||||
FileLoader *backend_;
|
||||
u8 *cache_;
|
||||
int exists_;
|
||||
int isDirectory_;
|
||||
u8 *cache_ = nullptr;
|
||||
int exists_ = -1;
|
||||
int isDirectory_ = -1;
|
||||
|
||||
std::vector<u8> blocks_;
|
||||
std::mutex blocksMutex_;
|
||||
u32 aheadRemaining_;
|
||||
s64 aheadPos_;
|
||||
bool aheadThread_;
|
||||
bool aheadThread_ = false;
|
||||
bool aheadCancel_ = false;
|
||||
};
|
||||
|
@ -72,3 +72,7 @@ size_t RetryingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Fla
|
||||
|
||||
return readSize;
|
||||
}
|
||||
|
||||
void RetryingFileLoader::Cancel() {
|
||||
backend_->Cancel();
|
||||
}
|
||||
|
@ -36,6 +36,8 @@ public:
|
||||
}
|
||||
size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override;
|
||||
|
||||
void Cancel() override;
|
||||
|
||||
private:
|
||||
enum {
|
||||
MAX_RETRIES = 3,
|
||||
|
@ -86,6 +86,10 @@ public:
|
||||
virtual size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) {
|
||||
return ReadAt(absolutePos, 1, bytes, data, flags);
|
||||
}
|
||||
|
||||
// Cancel any operations that might block, if possible.
|
||||
virtual void Cancel() {
|
||||
}
|
||||
};
|
||||
|
||||
inline u32 operator & (const FileLoader::Flags &a, const FileLoader::Flags &b) {
|
||||
|
Loading…
Reference in New Issue
Block a user