common: Miscellaneous cleanups (#7239)
* code: Remove some old msvc workarounds * android: Upgrade to NDK 26 * Allows access to newer libc++ * common/swap: Make use of std::endian Allows removing a bunch of defines in favor of a two liner. * common: Remove misc.cpp * GetLastErrorMsg has been in error.h for a while and also helps removing a depedency from a hot header like common_funcs * common: use SetThreadDescription API for thread names * common: Remove linear disk cache * Has never been used? * bit_set: Make constexpr * ring_buffer: Use feature macro * bit_set: Use <bit> and concepts * gsp_gpu: Restore comment * core: Ignore GCC warning --------- Co-authored-by: Lioncash <mathew1800@gmail.com> Co-authored-by: Liam <byteslice@airmail.cc>master
parent
15ea0c6336
commit
2b20082581
@ -1,168 +0,0 @@
|
|||||||
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
|
|
||||||
// Licensed under GPLv2 or any later version
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <vector>
|
|
||||||
#include "common/common_types.h"
|
|
||||||
|
|
||||||
// defined in Version.cpp
|
|
||||||
extern const char* scm_rev_git_str;
|
|
||||||
|
|
||||||
// On disk format:
|
|
||||||
// header{
|
|
||||||
// u32 'DCAC';
|
|
||||||
// u32 version; // svn_rev
|
|
||||||
// u16 sizeof(key_type);
|
|
||||||
// u16 sizeof(value_type);
|
|
||||||
//}
|
|
||||||
|
|
||||||
// key_value_pair{
|
|
||||||
// u32 value_size;
|
|
||||||
// key_type key;
|
|
||||||
// value_type[value_size] value;
|
|
||||||
//}
|
|
||||||
|
|
||||||
template <typename K, typename V>
|
|
||||||
class LinearDiskCacheReader {
|
|
||||||
public:
|
|
||||||
virtual void Read(const K& key, const V* value, u32 value_size) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Dead simple unsorted key-value store with append functionality.
|
|
||||||
// No random read functionality, all reading is done in OpenAndRead.
|
|
||||||
// Keys and values can contain any characters, including \0.
|
|
||||||
//
|
|
||||||
// Suitable for caching generated shader bytecode between executions.
|
|
||||||
// Not tuned for extreme performance but should be reasonably fast.
|
|
||||||
// Does not support keys or values larger than 2GB, which should be reasonable.
|
|
||||||
// Keys must have non-zero length; values can have zero length.
|
|
||||||
|
|
||||||
// K and V are some POD type
|
|
||||||
// K : the key type
|
|
||||||
// V : value array type
|
|
||||||
template <typename K, typename V>
|
|
||||||
class LinearDiskCache {
|
|
||||||
public:
|
|
||||||
// return number of read entries
|
|
||||||
u32 OpenAndRead(const char* filename, LinearDiskCacheReader<K, V>& reader) {
|
|
||||||
using std::ios_base;
|
|
||||||
|
|
||||||
// close any currently opened file
|
|
||||||
Close();
|
|
||||||
m_num_entries = 0;
|
|
||||||
|
|
||||||
// try opening for reading/writing
|
|
||||||
OpenFStream(m_file, filename, ios_base::in | ios_base::out | ios_base::binary);
|
|
||||||
|
|
||||||
m_file.seekg(0, std::ios::end);
|
|
||||||
std::fstream::pos_type end_pos = m_file.tellg();
|
|
||||||
m_file.seekg(0, std::ios::beg);
|
|
||||||
std::fstream::pos_type start_pos = m_file.tellg();
|
|
||||||
std::streamoff file_size = end_pos - start_pos;
|
|
||||||
|
|
||||||
if (m_file.is_open() && ValidateHeader()) {
|
|
||||||
// good header, read some key/value pairs
|
|
||||||
K key;
|
|
||||||
|
|
||||||
std::vector<V> value;
|
|
||||||
u32 value_size;
|
|
||||||
u32 entry_number;
|
|
||||||
|
|
||||||
std::fstream::pos_type last_pos = m_file.tellg();
|
|
||||||
|
|
||||||
while (Read(&value_size)) {
|
|
||||||
std::streamoff next_extent =
|
|
||||||
(last_pos - start_pos) + sizeof(value_size) + value_size;
|
|
||||||
if (next_extent > file_size)
|
|
||||||
break;
|
|
||||||
|
|
||||||
value.clear();
|
|
||||||
value.resize(value_size);
|
|
||||||
|
|
||||||
// read key/value and pass to reader
|
|
||||||
if (Read(&key) && Read(value.data(), value_size) && Read(&entry_number) &&
|
|
||||||
entry_number == m_num_entries + 1) {
|
|
||||||
reader.Read(key, value.data(), value_size);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_num_entries++;
|
|
||||||
last_pos = m_file.tellg();
|
|
||||||
}
|
|
||||||
m_file.seekp(last_pos);
|
|
||||||
m_file.clear();
|
|
||||||
|
|
||||||
value.clear();
|
|
||||||
return m_num_entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
// failed to open file for reading or bad header
|
|
||||||
// close and recreate file
|
|
||||||
Close();
|
|
||||||
m_file.open(filename, ios_base::out | ios_base::trunc | ios_base::binary);
|
|
||||||
WriteHeader();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sync() {
|
|
||||||
m_file.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Close() {
|
|
||||||
if (m_file.is_open())
|
|
||||||
m_file.close();
|
|
||||||
// clear any error flags
|
|
||||||
m_file.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Appends a key-value pair to the store.
|
|
||||||
void Append(const K& key, const V* value, u32 value_size) {
|
|
||||||
// TODO: Should do a check that we don't already have "key"? (I think each caller does that
|
|
||||||
// already.)
|
|
||||||
Write(&value_size);
|
|
||||||
Write(&key);
|
|
||||||
Write(value, value_size);
|
|
||||||
m_num_entries++;
|
|
||||||
Write(&m_num_entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void WriteHeader() {
|
|
||||||
Write(&m_header);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ValidateHeader() {
|
|
||||||
char file_header[sizeof(Header)];
|
|
||||||
|
|
||||||
return (Read(file_header, sizeof(Header)) &&
|
|
||||||
!memcmp((const char*)&m_header, file_header, sizeof(Header)));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename D>
|
|
||||||
bool Write(const D* data, u32 count = 1) {
|
|
||||||
return m_file.write((const char*)data, count * sizeof(D)).good();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename D>
|
|
||||||
bool Read(const D* data, u32 count = 1) {
|
|
||||||
return m_file.read((char*)data, count * sizeof(D)).good();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Header {
|
|
||||||
Header() : id(*(u32*)"DCAC"), key_t_size(sizeof(K)), value_t_size(sizeof(V)) {
|
|
||||||
std::memcpy(ver, scm_rev_git_str, 40);
|
|
||||||
}
|
|
||||||
|
|
||||||
const u32 id;
|
|
||||||
const u16 key_t_size, value_t_size;
|
|
||||||
char ver[40];
|
|
||||||
|
|
||||||
} m_header;
|
|
||||||
|
|
||||||
std::fstream m_file;
|
|
||||||
u32 m_num_entries;
|
|
||||||
};
|
|
@ -1,48 +0,0 @@
|
|||||||
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
|
|
||||||
// Licensed under GPLv2 or any later version
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#else
|
|
||||||
#include <cerrno>
|
|
||||||
#include <cstring>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "common/common_funcs.h"
|
|
||||||
|
|
||||||
// Generic function to get last error message.
|
|
||||||
// Call directly after the command or use the error num.
|
|
||||||
// This function might change the error code.
|
|
||||||
std::string GetLastErrorMsg() {
|
|
||||||
#ifdef _WIN32
|
|
||||||
LPSTR err_str;
|
|
||||||
|
|
||||||
DWORD res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
||||||
nullptr, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
||||||
reinterpret_cast<LPSTR>(&err_str), 1, nullptr);
|
|
||||||
if (!res) {
|
|
||||||
return "(FormatMessageA failed to format error)";
|
|
||||||
}
|
|
||||||
std::string ret(err_str);
|
|
||||||
LocalFree(err_str);
|
|
||||||
return ret;
|
|
||||||
#else
|
|
||||||
char err_str[255];
|
|
||||||
#if (defined(__GLIBC__) || __ANDROID_API__ >= 23) && \
|
|
||||||
(_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600))
|
|
||||||
// Thread safe (GNU-specific)
|
|
||||||
const char* str = strerror_r(errno, err_str, sizeof(err_str));
|
|
||||||
return std::string(str);
|
|
||||||
#else
|
|
||||||
// Thread safe (XSI-compliant)
|
|
||||||
int second_err = strerror_r(errno, err_str, sizeof(err_str));
|
|
||||||
if (second_err != 0) {
|
|
||||||
return "(strerror_r failed to format error)";
|
|
||||||
}
|
|
||||||
return std::string(err_str);
|
|
||||||
#endif // GLIBC etc.
|
|
||||||
#endif // _WIN32
|
|
||||||
}
|
|
Loading…
Reference in New Issue