1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 02:32:36 +01:00

shared_ptr.hpp: use for fs::virtual_device

Add new constructors for single_ptr and shared_ptr.
Change virtual device prefix format.
This commit is contained in:
Nekotekina 2021-04-12 16:39:48 +03:00
parent 19763f8973
commit a211895e28
3 changed files with 122 additions and 48 deletions

View File

@ -206,11 +206,11 @@ namespace fs
{ {
mutable shared_mutex m_mutex{}; mutable shared_mutex m_mutex{};
std::unordered_map<std::string, std::shared_ptr<device_base>> m_map{}; std::unordered_map<std::string, shared_ptr<device_base>> m_map{};
public: public:
std::shared_ptr<device_base> get_device(const std::string& path); shared_ptr<device_base> get_device(const std::string& path);
std::shared_ptr<device_base> set_device(const std::string& name, const std::shared_ptr<device_base>&); shared_ptr<device_base> set_device(const std::string& name, shared_ptr<device_base>);
}; };
static device_manager& get_device_manager() static device_manager& get_device_manager()
@ -275,48 +275,112 @@ namespace fs
{ {
} }
device_base::device_base()
: fs_prefix(fmt::format("/vfsv0_%s%s_", fmt::base57(reinterpret_cast<u64>(this)), fmt::base57(utils::get_unique_tsc())))
{
}
device_base::~device_base() device_base::~device_base()
{ {
} }
bool device_base::remove_dir(const std::string&)
{
g_tls_error = error::readonly;
return false;
}
bool device_base::create_dir(const std::string&)
{
g_tls_error = error::readonly;
return false;
}
bool device_base::rename(const std::string&, const std::string&)
{
g_tls_error = error::readonly;
return false;
}
bool device_base::remove(const std::string&)
{
g_tls_error = error::readonly;
return false;
}
bool device_base::trunc(const std::string&, u64)
{
g_tls_error = error::readonly;
return false;
}
bool device_base::utime(const std::string&, s64, s64)
{
g_tls_error = error::readonly;
return false;
}
} }
std::shared_ptr<fs::device_base> fs::device_manager::get_device(const std::string& path) shared_ptr<fs::device_base> fs::device_manager::get_device(const std::string& path)
{ {
reader_lock lock(m_mutex); reader_lock lock(m_mutex);
const auto found = m_map.find(path.substr(0, path.find_first_of('/', 2))); const usz prefix = path.find_first_of('_', 7) + 1;
if (found == m_map.end()) const auto found = m_map.find(path.substr(prefix, path.find_first_of('/', 1) - prefix));
if (found == m_map.end() || !path.starts_with(found->second->fs_prefix))
{ {
return nullptr; return null_ptr;
} }
return found->second; return found->second;
} }
std::shared_ptr<fs::device_base> fs::device_manager::set_device(const std::string& name, const std::shared_ptr<device_base>& device) shared_ptr<fs::device_base> fs::device_manager::set_device(const std::string& name, shared_ptr<device_base> device)
{ {
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
return m_map[name] = device; if (device)
{
// Adding
if (auto [it, ok] = m_map.try_emplace(name, std::move(device)); ok)
{
return it->second;
}
g_tls_error = error::exist;
}
else
{
// Removing
if (auto found = m_map.find(name); found != m_map.end())
{
device = std::move(found->second);
m_map.erase(found);
return device;
}
g_tls_error = error::noent;
}
return null_ptr;
} }
std::shared_ptr<fs::device_base> fs::get_virtual_device(const std::string& path) shared_ptr<fs::device_base> fs::get_virtual_device(const std::string& path)
{ {
// Every virtual device path must have "//" at the beginning // Every virtual device path must have specific name at the beginning
if (path.starts_with("//")) if (path.starts_with("/vfsv0_") && path.size() >= 8 + 22 && path[29] == '_' && path.find_first_of('/', 1) > 29)
{ {
return get_device_manager().get_device(path); return get_device_manager().get_device(path);
} }
return nullptr; return null_ptr;
} }
std::shared_ptr<fs::device_base> fs::set_virtual_device(const std::string& name, const std::shared_ptr<device_base>& device) shared_ptr<fs::device_base> fs::set_virtual_device(const std::string& name, shared_ptr<device_base> device)
{ {
ensure(name.starts_with("//") && name[2] != '/'); return get_device_manager().set_device(name, std::move(device));
return get_device_manager().set_device(name, device);
} }
std::string fs::get_parent_dir(const std::string& path) std::string fs::get_parent_dir(const std::string& path)

View File

@ -1,6 +1,7 @@
#pragma once // No BOM and only basic ASCII in this header, or a neko will die #pragma once // No BOM and only basic ASCII in this header, or a neko will die
#include "util/types.hpp" #include "util/types.hpp"
#include "util/shared_ptr.hpp"
#include "bit_set.h" #include "bit_set.h"
#include <memory> #include <memory>
@ -124,16 +125,19 @@ namespace fs
// Virtual device // Virtual device
struct device_base struct device_base
{ {
const std::string fs_prefix;
device_base();
virtual ~device_base(); virtual ~device_base();
virtual bool stat(const std::string& path, stat_t& info) = 0; virtual bool stat(const std::string& path, stat_t& info) = 0;
virtual bool statfs(const std::string& path, device_stat& info) = 0; virtual bool statfs(const std::string& path, device_stat& info) = 0;
virtual bool remove_dir(const std::string& path) = 0; virtual bool remove_dir(const std::string& path);
virtual bool create_dir(const std::string& path) = 0; virtual bool create_dir(const std::string& path);
virtual bool rename(const std::string& from, const std::string& to) = 0; virtual bool rename(const std::string& from, const std::string& to);
virtual bool remove(const std::string& path) = 0; virtual bool remove(const std::string& path);
virtual bool trunc(const std::string& path, u64 length) = 0; virtual bool trunc(const std::string& path, u64 length);
virtual bool utime(const std::string& path, s64 atime, s64 mtime) = 0; virtual bool utime(const std::string& path, s64 atime, s64 mtime);
virtual std::unique_ptr<file_base> open(const std::string& path, bs_t<open_mode> mode) = 0; virtual std::unique_ptr<file_base> open(const std::string& path, bs_t<open_mode> mode) = 0;
virtual std::unique_ptr<dir_base> open_dir(const std::string& path) = 0; virtual std::unique_ptr<dir_base> open_dir(const std::string& path) = 0;
@ -146,10 +150,10 @@ namespace fs
constexpr struct pod_tag_t{} pod_tag; constexpr struct pod_tag_t{} pod_tag;
// Get virtual device for specified path (nullptr for real path) // Get virtual device for specified path (nullptr for real path)
std::shared_ptr<device_base> get_virtual_device(const std::string& path); shared_ptr<device_base> get_virtual_device(const std::string& path);
// Set virtual device with specified name (nullptr for deletion) // Set virtual device with specified name (nullptr for deletion)
std::shared_ptr<device_base> set_virtual_device(const std::string& root_name, const std::shared_ptr<device_base>&); shared_ptr<device_base> set_virtual_device(const std::string& name, shared_ptr<device_base> device);
// Try to get parent directory (returns empty string on failure) // Try to get parent directory (returns empty string on failure)
std::string get_parent_dir(const std::string& path); std::string get_parent_dir(const std::string& path);

View File

@ -135,8 +135,9 @@ namespace stx
constexpr shared_data() noexcept = default; constexpr shared_data() noexcept = default;
}; };
// Simplified unique pointer. Wwell, not simplified, std::unique_ptr is preferred. // Simplified unique pointer. In some cases, std::unique_ptr is preferred.
// This one is shared_ptr counterpart, it has a control block with refs = 1. // This one is shared_ptr counterpart, it has a control block with refs and deleter.
// It's trivially convertible to shared_ptr, and back if refs == 1.
template <typename T> template <typename T>
class single_ptr class single_ptr
{ {
@ -166,6 +167,14 @@ namespace stx
single_ptr(const single_ptr&) = delete; single_ptr(const single_ptr&) = delete;
// Default constructor or null_ptr should be used instead
[[deprecated("Use null_ptr")]] single_ptr(std::nullptr_t) = delete;
explicit single_ptr(shared_data<T>&, pointer ptr) noexcept
: m_ptr(ptr)
{
}
single_ptr(single_ptr&& r) noexcept single_ptr(single_ptr&& r) noexcept
: m_ptr(r.m_ptr) : m_ptr(r.m_ptr)
{ {
@ -189,6 +198,8 @@ namespace stx
single_ptr& operator=(const single_ptr&) = delete; single_ptr& operator=(const single_ptr&) = delete;
[[deprecated("Use null_ptr")]] single_ptr& operator=(std::nullptr_t) = delete;
single_ptr& operator=(single_ptr&& r) noexcept single_ptr& operator=(single_ptr&& r) noexcept
{ {
single_ptr(std::move(r)).swap(*this); single_ptr(std::move(r)).swap(*this);
@ -279,12 +290,6 @@ namespace stx
r.m_ptr = static_cast<decltype(r.m_ptr)>(std::exchange(m_ptr, nullptr)); r.m_ptr = static_cast<decltype(r.m_ptr)>(std::exchange(m_ptr, nullptr));
return r; return r;
} }
// Raw access for make_single()
auto& raw() noexcept
{
return m_ptr;
}
}; };
#ifndef _MSC_VER #ifndef _MSC_VER
@ -325,18 +330,7 @@ namespace stx
delete reinterpret_cast<shared_data<T>*>(reinterpret_cast<u64>(_this) - offsetof(shared_data<T>, m_ctr)); delete reinterpret_cast<shared_data<T>*>(reinterpret_cast<u64>(_this) - offsetof(shared_data<T>, m_ctr));
}; };
single_ptr<T> r; return single_ptr<T>(*ptr, &ptr->m_data);
if constexpr (std::is_array_v<T>)
{
r.raw() = +ptr->m_data;
}
else
{
r.raw() = &ptr->m_data;
}
return r;
} }
template <typename T, bool Init = true> template <typename T, bool Init = true>
@ -396,9 +390,7 @@ namespace stx
} }
}; };
single_ptr<T> r; return single_ptr<T>(*ptr, std::launder(arr));
r.raw() = std::launder(arr);
return r;
} }
#ifndef _MSC_VER #ifndef _MSC_VER
@ -437,6 +429,18 @@ namespace stx
d()->refs++; d()->refs++;
} }
// Default constructor or null_ptr constant should be used instead
[[deprecated("Use null_ptr")]] shared_ptr(std::nullptr_t) = delete;
// Not-so-aliasing constructor: emulates std::enable_shared_from_this without its overhead
explicit shared_ptr(T* _this) noexcept
: m_ptr(_this)
{
// Random checks which may fail on invalid pointer
ensure((reinterpret_cast<u64>(d()->destroy) - 0x10000) >> 47 == 0);
ensure((d()->refs++ - 1) >> 58 == 0);
}
template <typename U, typename = std::enable_if_t<is_same_ptr_cast_v<T, U> != same_ptr::no>> template <typename U, typename = std::enable_if_t<is_same_ptr_cast_v<T, U> != same_ptr::no>>
shared_ptr(const shared_ptr<U>& r) noexcept shared_ptr(const shared_ptr<U>& r) noexcept
{ {
@ -485,6 +489,8 @@ namespace stx
return *this; return *this;
} }
[[deprecated("Use null_ptr")]] shared_ptr& operator=(std::nullptr_t) = delete;
template <typename U, typename = std::enable_if_t<is_same_ptr_cast_v<T, U> != same_ptr::no>> template <typename U, typename = std::enable_if_t<is_same_ptr_cast_v<T, U> != same_ptr::no>>
shared_ptr& operator=(const shared_ptr<U>& r) noexcept shared_ptr& operator=(const shared_ptr<U>& r) noexcept
{ {