Use std::invoke_result_t

Also simplify idm code
This commit is contained in:
Nekotekina 2018-09-05 15:10:37 +03:00
parent d750e955c3
commit 99ffc3fca9
3 changed files with 49 additions and 87 deletions

View file

@ -209,7 +209,7 @@ public:
} }
// Wait until pred(). Abortable, may throw. // Wait until pred(). Abortable, may throw.
template<typename F, typename RT = std::result_of_t<F()>> template<typename F, typename RT = std::invoke_result_t<F>>
static inline RT wait(F&& pred) static inline RT wait(F&& pred)
{ {
while (true) while (true)

View file

@ -271,7 +271,7 @@ template<typename T, T Func>
ppu_static_function* ppu_module_manager::registered<T, Func>::info = nullptr; ppu_static_function* ppu_module_manager::registered<T, Func>::info = nullptr;
// Call specified function directly if LLE is not available, call LLE equivalent in callback style otherwise // Call specified function directly if LLE is not available, call LLE equivalent in callback style otherwise
template<typename T, T Func, typename... Args, typename RT = std::result_of_t<T(Args...)>> template<typename T, T Func, typename... Args, typename RT = std::invoke_result_t<T, Args...>>
inline RT ppu_execute_function_or_callback(ppu_thread& ppu, Args&&... args) inline RT ppu_execute_function_or_callback(ppu_thread& ppu, Args&&... args)
{ {
vm::ptr<RT(Args...)> func = vm::cast(*ppu_module_manager::find_static_function<T, Func>().export_addr); vm::ptr<RT(Args...)> func = vm::cast(*ppu_module_manager::find_static_function<T, Func>().export_addr);

View file

@ -376,7 +376,7 @@ public:
} }
// Add a new ID for an object returned by provider() // Add a new ID for an object returned by provider()
template <typename T, typename Made = T, typename F, typename = std::result_of_t<F()>> template <typename T, typename Made = T, typename F, typename = std::invoke_result_t<F>>
static inline u32 import(F&& provider) static inline u32 import(F&& provider)
{ {
if (auto pair = create_id<T, Made>(std::forward<F>(provider))) if (auto pair = create_id<T, Made>(std::forward<F>(provider)))
@ -417,32 +417,32 @@ public:
} }
// Check the ID, access object under shared lock // Check the ID, access object under shared lock
template <typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(Get&)>, typename = std::enable_if_t<std::is_void<FRT>::value>> template <typename T, typename Get = T, typename F, typename FRT = std::invoke_result_t<F, Get&>>
static inline Get* check(u32 id, F&& func, int = 0) static inline auto check(u32 id, F&& func)
{ {
reader_lock lock(id_manager::g_mutex); reader_lock lock(id_manager::g_mutex);
if (const auto ptr = check_unlocked<T, Get>(id)) if (const auto ptr = check_unlocked<T, Get>(id))
{
if constexpr (!std::is_void_v<FRT>)
{
return return_pair<Get*, FRT>{ptr, func(*ptr)};
}
else
{ {
func(*ptr); func(*ptr);
return ptr; return ptr;
} }
return nullptr;
} }
// Check the ID, access object under reader lock, propagate return value if constexpr (!std::is_void_v<FRT>)
template <typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(Get&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>>
static inline return_pair<Get*, FRT> check(u32 id, F&& func)
{ {
reader_lock lock(id_manager::g_mutex); return return_pair<Get*, FRT>{nullptr};
}
if (const auto ptr = check_unlocked<T, Get>(id)) else
{ {
return {ptr, func(*ptr)}; return static_cast<Get*>(nullptr);
} }
return {nullptr};
} }
// Get the object without locking (can be called from other method) // Get the object without locking (can be called from other method)
@ -476,45 +476,29 @@ public:
} }
// Get the object, access object under reader lock // Get the object, access object under reader lock
template <typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(Get&)>, typename = std::enable_if_t<std::is_void<FRT>::value>> template <typename T, typename Get = T, typename F, typename FRT = std::invoke_result_t<F, Get&>>
static inline auto get(u32 id, F&& func, int = 0) static inline std::conditional_t<std::is_void_v<FRT>, std::shared_ptr<Get>, return_pair<Get, FRT>> get(u32 id, F&& func)
{ {
using result_type = std::shared_ptr<Get>;
reader_lock lock(id_manager::g_mutex); reader_lock lock(id_manager::g_mutex);
const auto found = find_id<T, Get>(id); const auto found = find_id<T, Get>(id);
if (UNLIKELY(found == nullptr)) if (UNLIKELY(found == nullptr))
{ {
return result_type{nullptr}; return {nullptr};
} }
const auto ptr = static_cast<Get*>(found->second.get()); const auto ptr = static_cast<Get*>(found->second.get());
if constexpr (std::is_void_v<FRT>)
{
func(*ptr); func(*ptr);
return {found->second, ptr};
return result_type{found->second, ptr};
} }
else
// Get the object, access object under reader lock, propagate return value
template <typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(Get&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>>
static inline auto get(u32 id, F&& func)
{ {
using result_type = return_pair<Get, FRT>; return {{found->second, ptr}, func(*ptr)};
reader_lock lock(id_manager::g_mutex);
const auto found = find_id<T, Get>(id);
if (UNLIKELY(found == nullptr))
{
return result_type{nullptr};
} }
const auto ptr = static_cast<Get*>(found->second.get());
return result_type{{found->second, ptr}, func(*ptr)};
} }
// Access all objects of specified type. Returns the number of objects processed. // Access all objects of specified type. Returns the number of objects processed.
@ -615,63 +599,41 @@ public:
} }
// Remove the ID after accessing the object under writer lock, return the object and propagate return value // Remove the ID after accessing the object under writer lock, return the object and propagate return value
template <typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(Get&)>, typename = std::enable_if_t<std::is_void<FRT>::value>> template <typename T, typename Get = T, typename F, typename FRT = std::invoke_result_t<F, Get&>>
static inline auto withdraw(u32 id, F&& func, int = 0) static inline std::conditional_t<std::is_void_v<FRT>, std::shared_ptr<Get>, return_pair<Get, FRT>> withdraw(u32 id, F&& func)
{ {
using result_type = std::shared_ptr<Get>; std::unique_lock lock(id_manager::g_mutex);
std::shared_ptr<void> ptr;
{
std::lock_guard lock(id_manager::g_mutex);
if (const auto found = find_id<T, Get>(id))
{
func(*static_cast<Get*>(found->second.get()));
ptr = std::move(found->second);
}
else
{
return result_type{nullptr};
}
}
id_manager::on_stop<Get>::func(static_cast<Get*>(ptr.get()));
return result_type{ptr, static_cast<Get*>(ptr.get())};
}
// Conditionally remove the ID (if return value evaluates to false) after accessing the object under writer lock, return the object and propagate return value
template <typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(Get&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>>
static inline auto withdraw(u32 id, F&& func)
{
using result_type = return_pair<Get, FRT>;
std::shared_ptr<void> ptr;
FRT ret;
{
std::lock_guard lock(id_manager::g_mutex);
if (const auto found = find_id<T, Get>(id)) if (const auto found = find_id<T, Get>(id))
{ {
const auto _ptr = static_cast<Get*>(found->second.get()); const auto _ptr = static_cast<Get*>(found->second.get());
ret = func(*_ptr); if constexpr (std::is_void_v<FRT>)
if (ret)
{ {
return result_type{{found->second, _ptr}, std::move(ret)}; func(*_ptr);
} std::shared_ptr<void> ptr = std::move(found->second);
lock.unlock();
ptr = std::move(found->second); id_manager::on_stop<Get>::func(static_cast<Get*>(ptr.get()));
return {ptr, static_cast<Get*>(ptr.get())};
} }
else else
{ {
return result_type{nullptr}; FRT ret = func(*_ptr);
if (ret)
{
// If return value evaluates to true, don't delete the object (error code)
return {{found->second, _ptr}, std::move(ret)};
}
std::shared_ptr<void> ptr = std::move(found->second);
lock.unlock();
id_manager::on_stop<Get>::func(static_cast<Get*>(ptr.get()));
return {{ptr, static_cast<Get*>(ptr.get())}, std::move(ret)};
} }
} }
id_manager::on_stop<Get>::func(static_cast<Get*>(ptr.get())); return {nullptr};
return result_type{{ptr, static_cast<Get*>(ptr.get())}, std::move(ret)};
} }
}; };