mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-27 23:40:39 +00:00
Merge pull request #9810 from nagisa/master
Make the Loader API thread-safe
This commit is contained in:
commit
94a14bde27
@ -59,6 +59,10 @@ inline u64 __rotr64(u64 x, unsigned int shift){
|
||||
return (x >> n) | (x << (64 - n));
|
||||
}
|
||||
|
||||
#ifndef linux
|
||||
#define pread64 pread
|
||||
#endif
|
||||
|
||||
#else // WIN32
|
||||
|
||||
// Function Cross-Compatibility
|
||||
@ -74,7 +78,6 @@ inline u64 __rotr64(u64 x, unsigned int shift){
|
||||
#define fseeko _fseeki64
|
||||
#define ftello _ftelli64
|
||||
#define atoll _atoi64
|
||||
#define fileno _fileno
|
||||
#if _M_IX86
|
||||
#define Crash() {__asm int 3}
|
||||
#else
|
||||
|
@ -25,19 +25,16 @@
|
||||
|
||||
// Takes ownership of backend.
|
||||
CachingFileLoader::CachingFileLoader(FileLoader *backend)
|
||||
: filesize_(0), filepos_(0), backend_(backend), exists_(-1), isDirectory_(-1), aheadThread_(false), prepared_(false) {
|
||||
: filesize_(0), backend_(backend), exists_(-1), isDirectory_(-1), aheadThread_(false) {
|
||||
}
|
||||
|
||||
void CachingFileLoader::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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
CachingFileLoader::~CachingFileLoader() {
|
||||
@ -50,7 +47,6 @@ CachingFileLoader::~CachingFileLoader() {
|
||||
|
||||
bool CachingFileLoader::Exists() {
|
||||
if (exists_ == -1) {
|
||||
std::lock_guard<std::mutex> guard(backendMutex_);
|
||||
exists_ = backend_->Exists() ? 1 : 0;
|
||||
}
|
||||
return exists_ == 1;
|
||||
@ -58,7 +54,6 @@ bool CachingFileLoader::Exists() {
|
||||
|
||||
bool CachingFileLoader::ExistsFast() {
|
||||
if (exists_ == -1) {
|
||||
std::lock_guard<std::mutex> guard(backendMutex_);
|
||||
return backend_->ExistsFast();
|
||||
}
|
||||
return exists_ == 1;
|
||||
@ -66,7 +61,6 @@ bool CachingFileLoader::ExistsFast() {
|
||||
|
||||
bool CachingFileLoader::IsDirectory() {
|
||||
if (isDirectory_ == -1) {
|
||||
std::lock_guard<std::mutex> guard(backendMutex_);
|
||||
isDirectory_ = backend_->IsDirectory() ? 1 : 0;
|
||||
}
|
||||
return isDirectory_ == 1;
|
||||
@ -78,14 +72,9 @@ s64 CachingFileLoader::FileSize() {
|
||||
}
|
||||
|
||||
std::string CachingFileLoader::Path() const {
|
||||
std::lock_guard<std::mutex> guard(backendMutex_);
|
||||
return backend_->Path();
|
||||
}
|
||||
|
||||
void CachingFileLoader::Seek(s64 absolutePos) {
|
||||
filepos_ = absolutePos;
|
||||
}
|
||||
|
||||
size_t CachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags) {
|
||||
Prepare();
|
||||
if (absolutePos >= filesize_) {
|
||||
@ -96,7 +85,6 @@ size_t CachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flag
|
||||
|
||||
size_t readSize = 0;
|
||||
if ((flags & Flags::HINT_UNCACHED) != 0) {
|
||||
std::lock_guard<std::mutex> guard(backendMutex_);
|
||||
readSize = backend_->ReadAt(absolutePos, bytes, data, flags);
|
||||
} else {
|
||||
readSize = ReadFromCache(absolutePos, bytes, data);
|
||||
@ -114,7 +102,6 @@ size_t CachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flag
|
||||
StartReadAhead(absolutePos + readSize);
|
||||
}
|
||||
|
||||
filepos_ = absolutePos + readSize;
|
||||
return readSize;
|
||||
}
|
||||
|
||||
@ -191,9 +178,7 @@ void CachingFileLoader::SaveIntoCache(s64 pos, size_t bytes, Flags flags, bool r
|
||||
blocksMutex_.unlock();
|
||||
|
||||
u8 *buf = new u8[BLOCK_SIZE];
|
||||
backendMutex_.lock();
|
||||
backend_->ReadAt(cacheStartPos << BLOCK_SHIFT, BLOCK_SIZE, buf, flags);
|
||||
backendMutex_.unlock();
|
||||
|
||||
blocksMutex_.lock();
|
||||
// While blocksMutex_ was unlocked, another thread may have read.
|
||||
@ -207,9 +192,7 @@ void CachingFileLoader::SaveIntoCache(s64 pos, size_t bytes, Flags flags, bool r
|
||||
blocksMutex_.unlock();
|
||||
|
||||
u8 *wholeRead = new u8[blocksToRead << BLOCK_SHIFT];
|
||||
backendMutex_.lock();
|
||||
backend_->ReadAt(cacheStartPos << BLOCK_SHIFT, blocksToRead << BLOCK_SHIFT, wholeRead, flags);
|
||||
backendMutex_.unlock();
|
||||
|
||||
blocksMutex_.lock();
|
||||
for (size_t i = 0; i < blocksToRead; ++i) {
|
||||
|
@ -34,13 +34,6 @@ public:
|
||||
s64 FileSize() override;
|
||||
std::string Path() const override;
|
||||
|
||||
void Seek(s64 absolutePos) override;
|
||||
size_t Read(size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(filepos_, bytes, count, data, flags);
|
||||
}
|
||||
size_t Read(size_t bytes, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(filepos_, bytes, data, flags);
|
||||
}
|
||||
size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(absolutePos, bytes * count, data, flags) / bytes;
|
||||
}
|
||||
@ -65,7 +58,6 @@ private:
|
||||
};
|
||||
|
||||
s64 filesize_;
|
||||
s64 filepos_;
|
||||
FileLoader *backend_;
|
||||
int exists_;
|
||||
int isDirectory_;
|
||||
@ -85,7 +77,6 @@ private:
|
||||
|
||||
std::map<s64, BlockInfo> blocks_;
|
||||
std::recursive_mutex blocksMutex_;
|
||||
mutable std::mutex backendMutex_;
|
||||
bool aheadThread_;
|
||||
bool prepared_;
|
||||
std::once_flag preparedFlag_;
|
||||
};
|
||||
|
@ -41,7 +41,7 @@ std::mutex DiskCachingFileLoader::cachesMutex_;
|
||||
|
||||
// Takes ownership of backend.
|
||||
DiskCachingFileLoader::DiskCachingFileLoader(FileLoader *backend)
|
||||
: prepared_(false), filesize_(0), filepos_(0), backend_(backend), cache_(nullptr) {
|
||||
: prepared_(false), filesize_(0), backend_(backend), cache_(nullptr) {
|
||||
}
|
||||
|
||||
void DiskCachingFileLoader::Prepare() {
|
||||
@ -88,10 +88,6 @@ std::string DiskCachingFileLoader::Path() const {
|
||||
return backend_->Path();
|
||||
}
|
||||
|
||||
void DiskCachingFileLoader::Seek(s64 absolutePos) {
|
||||
filepos_ = absolutePos;
|
||||
}
|
||||
|
||||
size_t DiskCachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags) {
|
||||
Prepare();
|
||||
size_t readSize;
|
||||
@ -119,7 +115,6 @@ size_t DiskCachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data,
|
||||
readSize = backend_->ReadAt(absolutePos, bytes, data, flags);
|
||||
}
|
||||
|
||||
filepos_ = absolutePos + readSize;
|
||||
return readSize;
|
||||
}
|
||||
|
||||
|
@ -37,13 +37,6 @@ public:
|
||||
s64 FileSize() override;
|
||||
std::string Path() const override;
|
||||
|
||||
void Seek(s64 absolutePos) override;
|
||||
size_t Read(size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(filepos_, bytes, count, data, flags);
|
||||
}
|
||||
size_t Read(size_t bytes, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(filepos_, bytes, data, flags);
|
||||
}
|
||||
size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(absolutePos, bytes * count, data, flags) / bytes;
|
||||
}
|
||||
@ -58,7 +51,6 @@ private:
|
||||
|
||||
bool prepared_;
|
||||
s64 filesize_;
|
||||
s64 filepos_;
|
||||
FileLoader *backend_;
|
||||
DiskCachingFileLoaderCache *cache_;
|
||||
|
||||
|
@ -22,70 +22,67 @@
|
||||
#include "Core/FileLoaders/HTTPFileLoader.h"
|
||||
|
||||
HTTPFileLoader::HTTPFileLoader(const std::string &filename)
|
||||
: filesize_(0), filepos_(0), url_(filename), filename_(filename), connected_(false), prepared_(false) {
|
||||
: filesize_(0), filepos_(0), url_(filename), filename_(filename), connected_(false) {
|
||||
}
|
||||
|
||||
void HTTPFileLoader::Prepare() {
|
||||
if (prepared_) {
|
||||
return;
|
||||
}
|
||||
prepared_ = true;
|
||||
std::call_once(preparedFlag_, [this](){
|
||||
if (!client_.Resolve(url_.Host().c_str(), url_.Port())) {
|
||||
// TODO: Should probably set some flag?
|
||||
return;
|
||||
}
|
||||
|
||||
if (!client_.Resolve(url_.Host().c_str(), url_.Port())) {
|
||||
// TODO: Should probably set some flag?
|
||||
return;
|
||||
}
|
||||
Connect();
|
||||
int err = client_.SendRequest("HEAD", url_.Resource().c_str());
|
||||
if (err < 0) {
|
||||
Disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
Connect();
|
||||
int err = client_.SendRequest("HEAD", url_.Resource().c_str());
|
||||
if (err < 0) {
|
||||
Disconnect();
|
||||
return;
|
||||
}
|
||||
Buffer readbuf;
|
||||
std::vector<std::string> responseHeaders;
|
||||
int code = client_.ReadResponseHeaders(&readbuf, responseHeaders);
|
||||
if (code != 200) {
|
||||
// Leave size at 0, invalid.
|
||||
ERROR_LOG(LOADER, "HTTP request failed, got %03d for %s", code, filename_.c_str());
|
||||
Disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
Buffer readbuf;
|
||||
std::vector<std::string> responseHeaders;
|
||||
int code = client_.ReadResponseHeaders(&readbuf, responseHeaders);
|
||||
if (code != 200) {
|
||||
// Leave size at 0, invalid.
|
||||
ERROR_LOG(LOADER, "HTTP request failed, got %03d for %s", code, filename_.c_str());
|
||||
Disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Expire cache via ETag, etc.
|
||||
bool acceptsRange = false;
|
||||
for (std::string header : responseHeaders) {
|
||||
if (startsWithNoCase(header, "Content-Length:")) {
|
||||
size_t size_pos = header.find_first_of(' ');
|
||||
if (size_pos != header.npos) {
|
||||
size_pos = header.find_first_not_of(' ', size_pos);
|
||||
// TODO: Expire cache via ETag, etc.
|
||||
bool acceptsRange = false;
|
||||
for (std::string header : responseHeaders) {
|
||||
if (startsWithNoCase(header, "Content-Length:")) {
|
||||
size_t size_pos = header.find_first_of(' ');
|
||||
if (size_pos != header.npos) {
|
||||
size_pos = header.find_first_not_of(' ', size_pos);
|
||||
}
|
||||
if (size_pos != header.npos) {
|
||||
filesize_ = atoll(&header[size_pos]);
|
||||
}
|
||||
}
|
||||
if (size_pos != header.npos) {
|
||||
filesize_ = atoll(&header[size_pos]);
|
||||
if (startsWithNoCase(header, "Accept-Ranges:")) {
|
||||
std::string lowerHeader = header;
|
||||
std::transform(lowerHeader.begin(), lowerHeader.end(), lowerHeader.begin(), tolower);
|
||||
// TODO: Delimited.
|
||||
if (lowerHeader.find("bytes") != lowerHeader.npos) {
|
||||
acceptsRange = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (startsWithNoCase(header, "Accept-Ranges:")) {
|
||||
std::string lowerHeader = header;
|
||||
std::transform(lowerHeader.begin(), lowerHeader.end(), lowerHeader.begin(), tolower);
|
||||
// TODO: Delimited.
|
||||
if (lowerHeader.find("bytes") != lowerHeader.npos) {
|
||||
acceptsRange = true;
|
||||
}
|
||||
|
||||
// TODO: Keepalive instead.
|
||||
Disconnect();
|
||||
|
||||
if (!acceptsRange) {
|
||||
WARN_LOG(LOADER, "HTTP server did not advertise support for range requests.");
|
||||
}
|
||||
if (filesize_ == 0) {
|
||||
ERROR_LOG(LOADER, "Could not determine file size for %s", filename_.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Keepalive instead.
|
||||
Disconnect();
|
||||
|
||||
if (!acceptsRange) {
|
||||
WARN_LOG(LOADER, "HTTP server did not advertise support for range requests.");
|
||||
}
|
||||
if (filesize_ == 0) {
|
||||
ERROR_LOG(LOADER, "Could not determine file size for %s", filename_.c_str());
|
||||
}
|
||||
|
||||
// If we didn't end up with a filesize_ (e.g. chunked response), give up. File invalid.
|
||||
// If we didn't end up with a filesize_ (e.g. chunked response), give up. File invalid.
|
||||
});
|
||||
}
|
||||
|
||||
HTTPFileLoader::~HTTPFileLoader() {
|
||||
@ -115,12 +112,10 @@ std::string HTTPFileLoader::Path() const {
|
||||
return filename_;
|
||||
}
|
||||
|
||||
void HTTPFileLoader::Seek(s64 absolutePos) {
|
||||
filepos_ = absolutePos;
|
||||
}
|
||||
|
||||
size_t HTTPFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags) {
|
||||
Prepare();
|
||||
std::lock_guard<std::mutex> guard(readAtMutex_);
|
||||
|
||||
s64 absoluteEnd = std::min(absolutePos + (s64)bytes, filesize_);
|
||||
if (absolutePos >= filesize_ || bytes == 0) {
|
||||
// Read outside of the file or no read at all, just fail immediately.
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "net/http_client.h"
|
||||
#include "net/resolve.h"
|
||||
#include "net/url.h"
|
||||
@ -34,13 +36,6 @@ public:
|
||||
virtual s64 FileSize() override;
|
||||
virtual std::string Path() const override;
|
||||
|
||||
virtual void Seek(s64 absolutePos) override;
|
||||
virtual size_t Read(size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(filepos_, bytes, count, data, flags);
|
||||
}
|
||||
virtual size_t Read(size_t bytes, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(filepos_, bytes, data, flags);
|
||||
}
|
||||
virtual size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(absolutePos, bytes * count, data, flags) / bytes;
|
||||
}
|
||||
@ -68,5 +63,7 @@ private:
|
||||
http::Client client_;
|
||||
std::string filename_;
|
||||
bool connected_;
|
||||
bool prepared_;
|
||||
|
||||
std::once_flag preparedFlag_;
|
||||
std::mutex readAtMutex_;
|
||||
};
|
||||
|
@ -15,42 +15,71 @@
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include <cstdio>
|
||||
#include "ppsspp_config.h"
|
||||
#include "util/text/utf8.h"
|
||||
#include "file/file_util.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Core/FileLoaders/LocalFileLoader.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Common/CommonWindows.h"
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
LocalFileLoader::LocalFileLoader(const std::string &filename)
|
||||
: fd_(0), f_(nullptr), filesize_(0), filename_(filename) {
|
||||
f_ = File::OpenCFile(filename, "rb");
|
||||
if (!f_) {
|
||||
: filesize_(0), filename_(filename) {
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
fd_ = open(filename.c_str(), O_RDONLY | O_CLOEXEC);
|
||||
if (fd_ == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
// Android NDK does not support 64-bit file I/O using C streams
|
||||
// so we fall back onto syscalls
|
||||
fd_ = fileno(f_);
|
||||
|
||||
off64_t off = lseek64(fd_, 0, SEEK_END);
|
||||
filesize_ = off;
|
||||
lseek64(fd_, 0, SEEK_SET);
|
||||
|
||||
#else // !_WIN32
|
||||
|
||||
const DWORD access = GENERIC_READ, share = FILE_SHARE_READ, mode = OPEN_EXISTING, flags = FILE_ATTRIBUTE_NORMAL;
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
handle_ = CreateFile2(ConvertUTF8ToWString(filename).c_str(), access, share, mode, nullptr);
|
||||
#else
|
||||
fseek(f_, 0, SEEK_END);
|
||||
filesize_ = ftello(f_);
|
||||
fseek(f_, 0, SEEK_SET);
|
||||
handle_ = CreateFile(ConvertUTF8ToWString(filename).c_str(), access, share, nullptr, mode, flags, nullptr);
|
||||
#endif
|
||||
if (handle_ == INVALID_HANDLE_VALUE) {
|
||||
return;
|
||||
}
|
||||
FILE_STANDARD_INFO info;
|
||||
if (GetFileInformationByHandleEx(handle_, FileStandardInfo, &info, sizeof(info)) == 0) {
|
||||
return;
|
||||
}
|
||||
filesize_ = info.EndOfFile.QuadPart;
|
||||
|
||||
#endif // !_WIN32
|
||||
|
||||
}
|
||||
|
||||
LocalFileLoader::~LocalFileLoader() {
|
||||
if (f_) {
|
||||
fclose(f_);
|
||||
#ifndef _WIN32
|
||||
if (fd_ != -1) {
|
||||
close(fd_);
|
||||
}
|
||||
#else
|
||||
if (handle_ != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(handle_);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool LocalFileLoader::Exists() {
|
||||
// If we couldn't open it for reading, we say it does not exist.
|
||||
if (f_ || IsDirectory()) {
|
||||
#ifndef _WIN32
|
||||
if (fd_ != -1 || IsDirectory()) {
|
||||
#else
|
||||
if (handle_ != INVALID_HANDLE_VALUE || IsDirectory()) {
|
||||
#endif
|
||||
FileInfo info;
|
||||
return getFileInfo(filename_.c_str(), &info);
|
||||
}
|
||||
@ -73,23 +102,15 @@ std::string LocalFileLoader::Path() const {
|
||||
return filename_;
|
||||
}
|
||||
|
||||
void LocalFileLoader::Seek(s64 absolutePos) {
|
||||
#ifdef __ANDROID__
|
||||
lseek64(fd_, absolutePos, SEEK_SET);
|
||||
#else
|
||||
fseeko(f_, absolutePos, SEEK_SET);
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t LocalFileLoader::Read(size_t bytes, size_t count, void *data, Flags flags) {
|
||||
#ifdef __ANDROID__
|
||||
return read(fd_, data, bytes * count) / bytes;
|
||||
#else
|
||||
return fread(data, bytes, count, f_);
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t LocalFileLoader::ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags) {
|
||||
Seek(absolutePos);
|
||||
return Read(bytes, count, data);
|
||||
#ifndef _WIN32
|
||||
return pread64(fd_, data, bytes * count, absolutePos) / bytes;
|
||||
#else
|
||||
DWORD read = -1;
|
||||
OVERLAPPED offset = { 0 };
|
||||
offset.Offset = (DWORD)(absolutePos & 0xffffffff);
|
||||
offset.OffsetHigh = (DWORD)((absolutePos & 0xffffffff00000000) >> 32);
|
||||
auto result = ReadFile(handle_, data, (DWORD)(bytes * count), &read, &offset);
|
||||
return result == TRUE ? (size_t)read / bytes : -1;
|
||||
#endif
|
||||
}
|
||||
|
@ -19,6 +19,9 @@
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Core/Loaders.h"
|
||||
#ifdef _WIN32
|
||||
typedef void *HANDLE;
|
||||
#endif
|
||||
|
||||
class LocalFileLoader : public FileLoader {
|
||||
public:
|
||||
@ -29,15 +32,14 @@ public:
|
||||
virtual bool IsDirectory() override;
|
||||
virtual s64 FileSize() override;
|
||||
virtual std::string Path() const override;
|
||||
|
||||
virtual void Seek(s64 absolutePos) override;
|
||||
virtual size_t Read(size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override;
|
||||
virtual size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override;
|
||||
|
||||
private:
|
||||
// First only used by Android, but we can keep it here for everyone.
|
||||
#ifndef _WIN32
|
||||
int fd_;
|
||||
FILE *f_;
|
||||
#else
|
||||
HANDLE handle_;
|
||||
#endif
|
||||
u64 filesize_;
|
||||
std::string filename_;
|
||||
};
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
// Takes ownership of backend.
|
||||
RamCachingFileLoader::RamCachingFileLoader(FileLoader *backend)
|
||||
: filesize_(0), filepos_(0), backend_(backend), exists_(-1), isDirectory_(-1), aheadThread_(false) {
|
||||
: filesize_(0), backend_(backend), exists_(-1), isDirectory_(-1), aheadThread_(false) {
|
||||
filesize_ = backend->FileSize();
|
||||
if (filesize_ > 0) {
|
||||
InitCache();
|
||||
@ -45,7 +45,6 @@ RamCachingFileLoader::~RamCachingFileLoader() {
|
||||
|
||||
bool RamCachingFileLoader::Exists() {
|
||||
if (exists_ == -1) {
|
||||
std::lock_guard<std::mutex> guard(backendMutex_);
|
||||
exists_ = backend_->Exists() ? 1 : 0;
|
||||
}
|
||||
return exists_ == 1;
|
||||
@ -53,7 +52,6 @@ bool RamCachingFileLoader::Exists() {
|
||||
|
||||
bool RamCachingFileLoader::ExistsFast() {
|
||||
if (exists_ == -1) {
|
||||
std::lock_guard<std::mutex> guard(backendMutex_);
|
||||
return backend_->ExistsFast();
|
||||
}
|
||||
return exists_ == 1;
|
||||
@ -61,7 +59,6 @@ bool RamCachingFileLoader::ExistsFast() {
|
||||
|
||||
bool RamCachingFileLoader::IsDirectory() {
|
||||
if (isDirectory_ == -1) {
|
||||
std::lock_guard<std::mutex> guard(backendMutex_);
|
||||
isDirectory_ = backend_->IsDirectory() ? 1 : 0;
|
||||
}
|
||||
return isDirectory_ == 1;
|
||||
@ -72,18 +69,12 @@ s64 RamCachingFileLoader::FileSize() {
|
||||
}
|
||||
|
||||
std::string RamCachingFileLoader::Path() const {
|
||||
std::lock_guard<std::mutex> guard(backendMutex_);
|
||||
return backend_->Path();
|
||||
}
|
||||
|
||||
void RamCachingFileLoader::Seek(s64 absolutePos) {
|
||||
filepos_ = absolutePos;
|
||||
}
|
||||
|
||||
size_t RamCachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags) {
|
||||
size_t readSize = 0;
|
||||
if (cache_ == nullptr || (flags & Flags::HINT_UNCACHED) != 0) {
|
||||
std::lock_guard<std::mutex> guard(backendMutex_);
|
||||
readSize = backend_->ReadAt(absolutePos, bytes, data, flags);
|
||||
} else {
|
||||
readSize = ReadFromCache(absolutePos, bytes, data);
|
||||
@ -100,8 +91,6 @@ size_t RamCachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, F
|
||||
|
||||
StartReadAhead(absolutePos + readSize);
|
||||
}
|
||||
|
||||
filepos_ = absolutePos + readSize;
|
||||
return readSize;
|
||||
}
|
||||
|
||||
@ -195,10 +184,8 @@ void RamCachingFileLoader::SaveIntoCache(s64 pos, size_t bytes, Flags flags) {
|
||||
}
|
||||
}
|
||||
|
||||
backendMutex_.lock();
|
||||
s64 cacheFilePos = cacheStartPos << BLOCK_SHIFT;
|
||||
size_t bytesRead = backend_->ReadAt(cacheFilePos, blocksToRead << BLOCK_SHIFT, &cache_[cacheFilePos], flags);
|
||||
backendMutex_.unlock();
|
||||
|
||||
// In case there was an error, let's not mark blocks that failed to read as read.
|
||||
u32 blocksActuallyRead = (u32)((bytesRead + BLOCK_SIZE - 1) >> BLOCK_SHIFT);
|
||||
|
@ -34,13 +34,6 @@ public:
|
||||
s64 FileSize() override;
|
||||
std::string Path() const override;
|
||||
|
||||
void Seek(s64 absolutePos) override;
|
||||
size_t Read(size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(filepos_, bytes, count, data, flags);
|
||||
}
|
||||
size_t Read(size_t bytes, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(filepos_, bytes, data, flags);
|
||||
}
|
||||
size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(absolutePos, bytes * count, data, flags) / bytes;
|
||||
}
|
||||
@ -63,7 +56,6 @@ private:
|
||||
};
|
||||
|
||||
s64 filesize_;
|
||||
s64 filepos_;
|
||||
FileLoader *backend_;
|
||||
u8 *cache_;
|
||||
int exists_;
|
||||
@ -71,7 +63,6 @@ private:
|
||||
|
||||
std::vector<u8> blocks_;
|
||||
std::mutex blocksMutex_;
|
||||
mutable std::mutex backendMutex_;
|
||||
u32 aheadRemaining_;
|
||||
s64 aheadPos_;
|
||||
bool aheadThread_;
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
// Takes ownership of backend.
|
||||
RetryingFileLoader::RetryingFileLoader(FileLoader *backend)
|
||||
: filepos_(0), backend_(backend) {
|
||||
: backend_(backend) {
|
||||
}
|
||||
|
||||
RetryingFileLoader::~RetryingFileLoader() {
|
||||
@ -60,10 +60,6 @@ std::string RetryingFileLoader::Path() const {
|
||||
return backend_->Path();
|
||||
}
|
||||
|
||||
void RetryingFileLoader::Seek(s64 absolutePos) {
|
||||
filepos_ = absolutePos;
|
||||
}
|
||||
|
||||
size_t RetryingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags) {
|
||||
size_t readSize = backend_->ReadAt(absolutePos, bytes, data, flags);
|
||||
|
||||
@ -74,6 +70,5 @@ size_t RetryingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Fla
|
||||
++retries;
|
||||
}
|
||||
|
||||
filepos_ = absolutePos + readSize;
|
||||
return readSize;
|
||||
}
|
||||
|
@ -31,13 +31,6 @@ public:
|
||||
s64 FileSize() override;
|
||||
std::string Path() const override;
|
||||
|
||||
void Seek(s64 absolutePos) override;
|
||||
size_t Read(size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(filepos_, bytes, count, data, flags);
|
||||
}
|
||||
size_t Read(size_t bytes, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(filepos_, bytes, data, flags);
|
||||
}
|
||||
size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(absolutePos, bytes * count, data, flags) / bytes;
|
||||
}
|
||||
@ -48,6 +41,5 @@ private:
|
||||
MAX_RETRIES = 3,
|
||||
};
|
||||
|
||||
s64 filepos_;
|
||||
FileLoader *backend_;
|
||||
};
|
||||
|
@ -38,7 +38,6 @@ BlockDevice *constructBlockDevice(FileLoader *fileLoader) {
|
||||
return nullptr;
|
||||
char buffer[4]{};
|
||||
size_t size = fileLoader->ReadAt(0, 1, 4, buffer);
|
||||
fileLoader->Seek(0);
|
||||
if (size == 4 && !memcmp(buffer, "CISO", 4))
|
||||
return new CISOFileBlockDevice(fileLoader);
|
||||
else if (size == 4 && !memcmp(buffer, "\x00PBP", 4))
|
||||
|
@ -54,7 +54,9 @@ enum class IdentifiedFileType {
|
||||
UNKNOWN,
|
||||
};
|
||||
|
||||
|
||||
class FileLoader {
|
||||
// NB: It is a REQUIREMENT that implementations of this class are entirely thread safe!
|
||||
public:
|
||||
enum class Flags {
|
||||
NONE,
|
||||
@ -80,12 +82,6 @@ public:
|
||||
return filename.substr(pos);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Seek(s64 absolutePos) = 0;
|
||||
virtual size_t Read(size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) = 0;
|
||||
virtual size_t Read(size_t bytes, void *data, Flags flags = Flags::NONE) {
|
||||
return Read(1, bytes, data, flags);
|
||||
}
|
||||
virtual size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) = 0;
|
||||
virtual size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) {
|
||||
return ReadAt(absolutePos, 1, bytes, data, flags);
|
||||
|
Loading…
Reference in New Issue
Block a user