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{};
std::unordered_map<std::string, std::shared_ptr<device_base>> m_map{};
std::unordered_map<std::string, shared_ptr<device_base>> m_map{};
public:
std::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> get_device(const std::string& path);
shared_ptr<device_base> set_device(const std::string& name, shared_ptr<device_base>);
};
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()
{
}
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);
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;
}
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);
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
if (path.starts_with("//"))
// Every virtual device path must have specific name at the beginning
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 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, device);
return get_device_manager().set_device(name, std::move(device));
}
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
#include "util/types.hpp"
#include "util/shared_ptr.hpp"
#include "bit_set.h"
#include <memory>
@ -124,16 +125,19 @@ namespace fs
// Virtual device
struct device_base
{
const std::string fs_prefix;
device_base();
virtual ~device_base();
virtual bool stat(const std::string& path, stat_t& info) = 0;
virtual bool statfs(const std::string& path, device_stat& info) = 0;
virtual bool remove_dir(const std::string& path) = 0;
virtual bool create_dir(const std::string& path) = 0;
virtual bool rename(const std::string& from, const std::string& to) = 0;
virtual bool remove(const std::string& path) = 0;
virtual bool trunc(const std::string& path, u64 length) = 0;
virtual bool utime(const std::string& path, s64 atime, s64 mtime) = 0;
virtual bool remove_dir(const std::string& path);
virtual bool create_dir(const std::string& path);
virtual bool rename(const std::string& from, const std::string& to);
virtual bool remove(const std::string& path);
virtual bool trunc(const std::string& path, u64 length);
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<dir_base> open_dir(const std::string& path) = 0;
@ -146,10 +150,10 @@ namespace fs
constexpr struct pod_tag_t{} pod_tag;
// 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)
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)
std::string get_parent_dir(const std::string& path);

View File

@ -135,8 +135,9 @@ namespace stx
constexpr shared_data() noexcept = default;
};
// Simplified unique pointer. Wwell, not simplified, std::unique_ptr is preferred.
// This one is shared_ptr counterpart, it has a control block with refs = 1.
// Simplified unique pointer. In some cases, std::unique_ptr is preferred.
// 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>
class single_ptr
{
@ -166,6 +167,14 @@ namespace stx
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
: m_ptr(r.m_ptr)
{
@ -189,6 +198,8 @@ namespace stx
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(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));
return r;
}
// Raw access for make_single()
auto& raw() noexcept
{
return m_ptr;
}
};
#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));
};
single_ptr<T> r;
if constexpr (std::is_array_v<T>)
{
r.raw() = +ptr->m_data;
}
else
{
r.raw() = &ptr->m_data;
}
return r;
return single_ptr<T>(*ptr, &ptr->m_data);
}
template <typename T, bool Init = true>
@ -396,9 +390,7 @@ namespace stx
}
};
single_ptr<T> r;
r.raw() = std::launder(arr);
return r;
return single_ptr<T>(*ptr, std::launder(arr));
}
#ifndef _MSC_VER
@ -437,6 +429,18 @@ namespace stx
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>>
shared_ptr(const shared_ptr<U>& r) noexcept
{
@ -485,6 +489,8 @@ namespace stx
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>>
shared_ptr& operator=(const shared_ptr<U>& r) noexcept
{