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:
parent
19763f8973
commit
a211895e28
@ -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)
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user