From a211895e2842c4dacc9e318d23829f3442ee1df8 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 12 Apr 2021 16:39:48 +0300 Subject: [PATCH] shared_ptr.hpp: use for fs::virtual_device Add new constructors for single_ptr and shared_ptr. Change virtual device prefix format. --- Utilities/File.cpp | 98 ++++++++++++++++++++++++++++++++------- Utilities/File.h | 20 ++++---- rpcs3/util/shared_ptr.hpp | 52 ++++++++++++--------- 3 files changed, 122 insertions(+), 48 deletions(-) diff --git a/Utilities/File.cpp b/Utilities/File.cpp index 3f58dc112b..5356dbe6c1 100644 --- a/Utilities/File.cpp +++ b/Utilities/File.cpp @@ -206,11 +206,11 @@ namespace fs { mutable shared_mutex m_mutex{}; - std::unordered_map> m_map{}; + std::unordered_map> m_map{}; public: - std::shared_ptr get_device(const std::string& path); - std::shared_ptr set_device(const std::string& name, const std::shared_ptr&); + shared_ptr get_device(const std::string& path); + shared_ptr set_device(const std::string& name, shared_ptr); }; 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(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_manager::get_device(const std::string& path) +shared_ptr 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_manager::set_device(const std::string& name, const std::shared_ptr& device) +shared_ptr fs::device_manager::set_device(const std::string& name, shared_ptr 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::get_virtual_device(const std::string& path) +shared_ptr 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::set_virtual_device(const std::string& name, const std::shared_ptr& device) +shared_ptr fs::set_virtual_device(const std::string& name, shared_ptr 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) diff --git a/Utilities/File.h b/Utilities/File.h index b8e8b92f91..8a9f3e1162 100644 --- a/Utilities/File.h +++ b/Utilities/File.h @@ -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 @@ -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 open(const std::string& path, bs_t mode) = 0; virtual std::unique_ptr 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 get_virtual_device(const std::string& path); + shared_ptr get_virtual_device(const std::string& path); // Set virtual device with specified name (nullptr for deletion) - std::shared_ptr set_virtual_device(const std::string& root_name, const std::shared_ptr&); + shared_ptr set_virtual_device(const std::string& name, shared_ptr device); // Try to get parent directory (returns empty string on failure) std::string get_parent_dir(const std::string& path); diff --git a/rpcs3/util/shared_ptr.hpp b/rpcs3/util/shared_ptr.hpp index b9fb144751..ad4cac258e 100644 --- a/rpcs3/util/shared_ptr.hpp +++ b/rpcs3/util/shared_ptr.hpp @@ -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 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&, 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(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*>(reinterpret_cast(_this) - offsetof(shared_data, m_ctr)); }; - single_ptr r; - - if constexpr (std::is_array_v) - { - r.raw() = +ptr->m_data; - } - else - { - r.raw() = &ptr->m_data; - } - - return r; + return single_ptr(*ptr, &ptr->m_data); } template @@ -396,9 +390,7 @@ namespace stx } }; - single_ptr r; - r.raw() = std::launder(arr); - return r; + return single_ptr(*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(d()->destroy) - 0x10000) >> 47 == 0); + ensure((d()->refs++ - 1) >> 58 == 0); + } + template != same_ptr::no>> shared_ptr(const shared_ptr& r) noexcept { @@ -485,6 +489,8 @@ namespace stx return *this; } + [[deprecated("Use null_ptr")]] shared_ptr& operator=(std::nullptr_t) = delete; + template != same_ptr::no>> shared_ptr& operator=(const shared_ptr& r) noexcept {