refcnt.h removed

This commit is contained in:
Nekotekina 2015-05-25 21:12:53 +03:00
parent 24278e0eca
commit 98aee31c5a
8 changed files with 39 additions and 240 deletions

View file

@ -397,7 +397,7 @@ s32 sceKernelCreateEventFlag(vm::psv::ptr<const char> pName, u32 attr, u32 initP
{
sceLibKernel.Error("sceKernelCreateEventFlag(pName=*0x%x, attr=0x%x, initPattern=0x%x, pOptParam=*0x%x)", pName, attr, initPattern, pOptParam);
if (s32 id = g_psv_ef_list.add(new psv_event_flag_t(pName.get_ptr(), attr, initPattern), 0))
if (s32 id = g_psv_ef_list.create(pName.get_ptr(), attr, initPattern))
{
return id;
}
@ -461,7 +461,7 @@ s32 sceKernelCreateSema(vm::psv::ptr<const char> pName, u32 attr, s32 initCount,
{
sceLibKernel.Error("sceKernelCreateSema(pName=*0x%x, attr=0x%x, initCount=%d, maxCount=%d, pOptParam=*0x%x)", pName, attr, initCount, maxCount, pOptParam);
if (s32 id = g_psv_sema_list.add(new psv_sema_t(pName.get_ptr(), attr, initCount, maxCount), 0))
if (s32 id = g_psv_sema_list.create(pName.get_ptr(), attr, initCount, maxCount))
{
return id;
}
@ -473,7 +473,7 @@ s32 sceKernelDeleteSema(s32 semaId)
{
sceLibKernel.Error("sceKernelDeleteSema(semaId=0x%x)", semaId);
ref_t<psv_sema_t> sema = g_psv_sema_list.get(semaId);
const auto sema = g_psv_sema_list.get(semaId);
if (!sema)
{
@ -502,7 +502,7 @@ s32 sceKernelWaitSema(s32 semaId, s32 needCount, vm::psv::ptr<u32> pTimeout)
{
sceLibKernel.Error("sceKernelWaitSema(semaId=0x%x, needCount=%d, pTimeout=*0x%x)", semaId, needCount, pTimeout);
ref_t<psv_sema_t> sema = g_psv_sema_list.get(semaId);
const auto sema = g_psv_sema_list.get(semaId);
if (!sema)
{
@ -545,7 +545,7 @@ s32 sceKernelCreateMutex(vm::psv::ptr<const char> pName, u32 attr, s32 initCount
{
sceLibKernel.Error("sceKernelCreateMutex(pName=*0x%x, attr=0x%x, initCount=%d, pOptParam=*0x%x)", pName, attr, initCount, pOptParam);
if (s32 id = g_psv_mutex_list.add(new psv_mutex_t(pName.get_ptr(), attr, initCount), 0))
if (s32 id = g_psv_mutex_list.create(pName.get_ptr(), attr, initCount))
{
return id;
}
@ -646,7 +646,7 @@ s32 sceKernelCreateCond(vm::psv::ptr<const char> pName, u32 attr, s32 mutexId, v
{
sceLibKernel.Error("sceKernelCreateCond(pName=*0x%x, attr=0x%x, mutexId=0x%x, pOptParam=*0x%x)", pName, attr, mutexId, pOptParam);
if (s32 id = g_psv_cond_list.add(new psv_cond_t(pName.get_ptr(), attr, mutexId), 0))
if (s32 id = g_psv_cond_list.create(pName.get_ptr(), attr, mutexId))
{
return id;
}

View file

@ -21,18 +21,12 @@ union psv_uid_t
}
};
template<typename T, u32 type>
template<typename T, u32 uid_class>
class psv_object_list_t // Class for managing object data
{
public:
typedef refcounter_t<T> rc_type;
typedef ref_t<T> ref_type;
static const u32 max = 0x8000;
private:
std::array<rc_type, max> m_data;
std::array<std::shared_ptr<T>, 0x8000> m_data;
std::atomic<u32> m_hint; // guessing next free position
std::mutex m_mutex;
void error(s32 uid)
{
@ -45,17 +39,8 @@ public:
{
}
psv_object_list_t(const psv_object_list_t&) = delete;
psv_object_list_t(psv_object_list_t&&) = delete;
psv_object_list_t& operator =(const psv_object_list_t&) = delete;
psv_object_list_t& operator =(psv_object_list_t&&) = delete;
public:
static const u32 uid_class = type;
// check if UID is potentially valid (will return true even if the object doesn't exist)
bool check(s32 uid)
inline static bool check(s32 uid)
{
const psv_uid_t id = psv_uid_t::make(uid);
@ -64,29 +49,35 @@ public:
}
// share object with UID specified
ref_type get(s32 uid)
__forceinline std::shared_ptr<T> get(s32 uid)
{
if (!check(uid))
{
return ref_type();
return nullptr;
}
return &m_data[psv_uid_t::make(uid).number];
std::lock_guard<std::mutex> lock(m_mutex);
return m_data[psv_uid_t::make(uid).number];
}
ref_type operator [](s32 uid)
__forceinline std::shared_ptr<T> operator [](s32 uid)
{
return get(uid);
return this->get(uid);
}
// generate UID for newly created object (will return zero if the limit exceeded)
s32 add(T* data, s32 error_code)
// create new object and generate UID for it, or do nothing and return zero (if limit reached)
template<typename... Args> s32 create(Args&&... args)
{
std::lock_guard<std::mutex> lock(m_mutex);
for (u32 i = 0, j = m_hint; i < m_data.size(); i++, j = (j + 1) % m_data.size())
{
// find an empty position and copy the pointer
if (m_data[j].try_set(data))
if (!m_data[j])
{
m_data[j] = std::make_shared<T>(args...); // construct object with specified arguments
m_hint = (j + 1) % m_data.size(); // guess next position
psv_uid_t id = psv_uid_t::make(1); // make UID
@ -97,8 +88,7 @@ public:
}
}
delete data;
return error_code;
return 0;
}
// remove object with specified UID
@ -109,19 +99,29 @@ public:
return false;
}
std::lock_guard<std::mutex> lock(m_mutex);
const u32 pos = psv_uid_t::make(uid).number;
m_hint = std::min<u32>(pos, m_hint);
return m_data[pos].try_remove();
if (!m_data[pos])
{
return false;
}
m_data[pos].reset();
return true;
}
// remove all objects
void clear()
{
std::lock_guard<std::mutex> lock(m_mutex);
for (auto& v : m_data)
{
v.try_remove();
v.reset();
}
m_hint = 0;

View file

@ -1,196 +0,0 @@
#pragma once
#include "atomic.h"
// run endless loop for debugging
__forceinline static void deadlock()
{
while (true)
{
std::this_thread::yield();
}
}
template<typename T>
class ref_t;
template<typename T>
class refcounter_t // non-relocateable "smart" pointer with ref counter
{
public:
typedef T type, * p_type;
typedef refcounter_t<T> rc_type;
// counter > 0, ptr != nullptr : object exists and shared
// counter > 0, ptr == nullptr : object exists and shared, but not owned by refcounter_t
// counter == 0, ptr != nullptr : object exists and not shared
// counter == 0, ptr == nullptr : object doesn't exist
// counter < 0 : bad state, used to provoke error for debugging
struct sync_var_t
{
s64 counter;
p_type ptr;
};
private:
atomic_le_t<sync_var_t> m_var;
friend class ref_t<T>;
// try to share object (increment counter), returns nullptr if doesn't exist or cannot be shared
__forceinline p_type ref_inc()
{
p_type out_ptr;
m_var.atomic_op([&out_ptr](sync_var_t& v)
{
assert(v.counter >= 0);
if ((out_ptr = v.ptr))
{
v.counter++;
}
});
return out_ptr;
}
// try to release previously shared object (decrement counter), returns true if should be deleted
__forceinline bool ref_dec()
{
bool do_delete;
m_var.atomic_op([&do_delete](sync_var_t& v)
{
assert(v.counter > 0);
do_delete = !--v.counter && !v.ptr;
});
return do_delete;
}
public:
refcounter_t()
{
// initialize ref counter
m_var.write_relaxed({ 0, nullptr });
}
~refcounter_t()
{
// set bad state
auto ref = m_var.exchange({ -1, nullptr });
// finalize
if (ref.counter)
{
deadlock();
}
else if (ref.ptr)
{
delete ref.ptr;
}
}
refcounter_t(const rc_type& right) = delete;
refcounter_t(rc_type&& right_rv) = delete;
rc_type& operator =(const rc_type& right) = delete;
rc_type& operator =(rc_type&& right_rv) = delete;
public:
// try to set new object (if it doesn't exist)
bool try_set(p_type ptr)
{
return m_var.compare_and_swap_test({ 0, nullptr }, { 0, ptr });
}
// try to remove object (if exists)
bool try_remove()
{
bool out_res;
p_type out_ptr;
m_var.atomic_op([&out_res, &out_ptr](sync_var_t& v)
{
out_res = (out_ptr = v.ptr);
if (v.counter)
{
out_ptr = nullptr;
}
v.ptr = nullptr;
});
if (out_ptr)
{
delete out_ptr;
}
return out_res;
}
};
template<typename T>
class ref_t
{
public:
typedef T type, * p_type;
typedef refcounter_t<T> * rc_type;
private:
rc_type m_rc;
p_type m_ptr;
public:
ref_t()
: m_rc(nullptr)
, m_ptr(nullptr)
{
}
ref_t(rc_type rc)
: m_rc(rc)
, m_ptr(rc->ref_inc())
{
}
~ref_t()
{
if (m_ptr && m_rc->ref_dec())
{
delete m_ptr;
}
}
ref_t(const ref_t& right) = delete;
ref_t(ref_t&& right_rv)
: m_rc(right_rv.m_rc)
, m_ptr(right_rv.m_ptr)
{
right_rv.m_rc = nullptr;
right_rv.m_ptr = nullptr;
}
ref_t& operator =(const ref_t& right) = delete;
ref_t& operator =(ref_t&& right_rv) = delete;
public:
T& operator *() const
{
return *m_ptr;
}
T* operator ->() const
{
return m_ptr;
}
explicit operator bool() const
{
return m_ptr;
}
};

View file

@ -30,7 +30,7 @@ struct cond_t
: mutex(mutex)
, name(name)
, signaled(0)
, waiters(0)
//, waiters(0)
{
}
};

View file

@ -32,7 +32,7 @@ struct lwcond_t
: name(name)
, signaled1(0)
, signaled2(0)
, waiters(0)
//, waiters(0)
{
}
};

View file

@ -418,7 +418,6 @@
<ClInclude Include="Emu\Memory\Memory.h" />
<ClInclude Include="Emu\Memory\MemoryBlock.h" />
<ClInclude Include="Emu\Memory\atomic.h" />
<ClInclude Include="Emu\Memory\refcnt.h" />
<ClInclude Include="Emu\RSX\CgBinaryProgram.h" />
<ClInclude Include="Emu\RSX\Common\FragmentProgramDecompiler.h" />
<ClInclude Include="Emu\RSX\Common\ProgramStateCache.h" />

View file

@ -1543,9 +1543,6 @@
<ClInclude Include="Emu\Memory\atomic.h">
<Filter>Emu\Memory</Filter>
</ClInclude>
<ClInclude Include="Emu\Memory\refcnt.h">
<Filter>Emu\Memory</Filter>
</ClInclude>
<ClInclude Include="Emu\SysCalls\lv2\sys_fs.h">
<Filter>Emu\SysCalls\lv2</Filter>
</ClInclude>

View file

@ -61,7 +61,6 @@ template<typename T> __forceinline T align(const T addr, int align)
#include "Utilities/StrFmt.h"
#include "Emu/Memory/atomic.h"
#include "Emu/Memory/refcnt.h"
#define _PRGNAME_ "RPCS3"
#define _PRGVER_ "0.0.0.5"