GSdx: a few minor changes, please check if I wrapped the new pthread things correctly

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5019 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gabest11 2011-12-27 09:15:35 +00:00
parent 3aa3b1caf6
commit 25072b99c7
10 changed files with 298 additions and 203 deletions

View File

@ -2002,8 +2002,6 @@ GSOffset::~GSOffset()
list<uint32>* GSOffset::GetPages(const GSVector4i& rect, GSVector4i* bbox) list<uint32>* GSOffset::GetPages(const GSVector4i& rect, GSVector4i* bbox)
{ {
GSAutoLock lock(&m_lock);
GSVector2i bs = (bp & 31) == 0 ? GSLocalMemory::m_psm[psm].pgs : GSLocalMemory::m_psm[psm].bs; GSVector2i bs = (bp & 31) == 0 ? GSLocalMemory::m_psm[psm].pgs : GSLocalMemory::m_psm[psm].bs;
GSVector4i r = rect.ralign<Align_Outside>(bs); GSVector4i r = rect.ralign<Align_Outside>(bs);

View File

@ -30,8 +30,6 @@
class GSOffset : public GSAlignedClass<32> class GSOffset : public GSAlignedClass<32>
{ {
GSCritSec m_lock; // GetPages could be called from multiple threads
hash_map<uint64, list<uint32>*> m_cache; hash_map<uint64, list<uint32>*> m_cache;
public: public:

View File

@ -163,6 +163,9 @@ void GSRasterizer::Draw(shared_ptr<GSRasterizerData> data)
uint64 ticks = __rdtsc() - start; uint64 ticks = __rdtsc() - start;
_InterlockedExchangeAdd(&data->ticks, ticks);
_InterlockedExchangeAdd(&data->pixels, m_pixels);
m_ds->EndDraw(data->frame, ticks, m_pixels); m_ds->EndDraw(data->frame, ticks, m_pixels);
} }

View File

@ -41,6 +41,11 @@ public:
uint64 frame; uint64 frame;
void* param; void* param;
// drawing stats
volatile long ticks;
volatile long pixels;
GSRasterizerData() GSRasterizerData()
: scissor(GSVector4i::zero()) : scissor(GSVector4i::zero())
, bbox(GSVector4i::zero()) , bbox(GSVector4i::zero())
@ -51,6 +56,8 @@ public:
, syncpoint(false) , syncpoint(false)
, frame(0) , frame(0)
, param(NULL) , param(NULL)
, ticks(0)
, pixels(0)
{ {
} }

View File

@ -166,7 +166,19 @@ void GSRendererSW::Draw()
{ {
if(m_dump) m_dump.Object(m_vertices, m_count, m_vt.m_primclass); if(m_dump) m_dump.Object(m_vertices, m_count, m_vt.m_primclass);
shared_ptr<GSRasterizerData> data(new GSRasterizerData2(this)); GSVector4i scissor = GSVector4i(m_context->scissor.in);
GSVector4i bbox = GSVector4i(m_vt.m_min.p.floor().xyxy(m_vt.m_max.p.ceil()));
scissor.z = std::min<int>(scissor.z, (int)m_context->FRAME.FBW * 64); // TODO: find a game that overflows and check which one is the right behaviour
GSVector4i r = bbox.rintersect(scissor);
list<uint32>* fb_pages = m_context->offset.fb->GetPages(r);
list<uint32>* zb_pages = m_context->offset.zb->GetPages(r);
GSRasterizerData2* data2 = new GSRasterizerData2(this, fb_pages, zb_pages);
shared_ptr<GSRasterizerData> data(data2);
GSScanlineGlobalData* gd = (GSScanlineGlobalData*)data->param; GSScanlineGlobalData* gd = (GSScanlineGlobalData*)data->param;
@ -175,9 +187,8 @@ void GSRendererSW::Draw()
return; return;
} }
data->scissor = GSVector4i(m_context->scissor.in); data->scissor = scissor;
data->scissor.z = std::min<int>(data->scissor.z, (int)m_context->FRAME.FBW * 64); // TODO: find a game that overflows and check which one is the right behaviour data->bbox = bbox;
data->bbox = GSVector4i(m_vt.m_min.p.floor().xyxy(m_vt.m_max.p.ceil()));
data->primclass = m_vt.m_primclass; data->primclass = m_vt.m_primclass;
data->vertices = (GSVertexSW*)_aligned_malloc(sizeof(GSVertexSW) * m_count, 16); // TODO: detach m_vertices and reallocate later? data->vertices = (GSVertexSW*)_aligned_malloc(sizeof(GSVertexSW) * m_count, 16); // TODO: detach m_vertices and reallocate later?
memcpy(data->vertices, m_vertices, sizeof(GSVertexSW) * m_count); // TODO: m_vt.Update fetches all the vertices already, could also store them here memcpy(data->vertices, m_vertices, sizeof(GSVertexSW) * m_count); // TODO: m_vt.Update fetches all the vertices already, could also store them here
@ -185,11 +196,6 @@ void GSRendererSW::Draw()
data->solidrect = gd->sel.IsSolidRect(); data->solidrect = gd->sel.IsSolidRect();
data->frame = m_perfmon.GetFrame(); data->frame = m_perfmon.GetFrame();
GSVector4i r = data->bbox.rintersect(data->scissor);
list<uint32>* fb_pages = m_context->offset.fb->GetPages(r);
list<uint32>* zb_pages = m_context->offset.zb->GetPages(r);
// //
if(gd->sel.fwrite) if(gd->sel.fwrite)
@ -202,7 +208,7 @@ void GSRendererSW::Draw()
m_tc->InvalidatePages(zb_pages, m_context->offset.zb->psm); m_tc->InvalidatePages(zb_pages, m_context->offset.zb->psm);
} }
// // set data->syncpoint
if(m_fzb != m_context->offset.fzb) if(m_fzb != m_context->offset.fzb)
{ {
@ -220,7 +226,12 @@ void GSRendererSW::Draw()
{ {
for(list<uint32>::iterator i = fb_pages->begin(); i != fb_pages->end(); i++) for(list<uint32>::iterator i = fb_pages->begin(); i != fb_pages->end(); i++)
{ {
if(m_fzb_pages[*i] & 0xffff0000) data->syncpoint = true; // already used as a z-buffer if(m_fzb_pages[*i] & 0xffff0000) // already used as a z-buffer
{
data->syncpoint = true;
break;
}
} }
} }
} }
@ -231,20 +242,21 @@ void GSRendererSW::Draw()
{ {
for(list<uint32>::iterator i = zb_pages->begin(); i != zb_pages->end(); i++) for(list<uint32>::iterator i = zb_pages->begin(); i != zb_pages->end(); i++)
{ {
if(m_fzb_pages[*i] & 0x0000ffff) data->syncpoint = true; // already used as a frame buffer if(m_fzb_pages[*i] & 0x0000ffff) // already used as a frame buffer
{
data->syncpoint = true;
break;
}
} }
} }
} }
if(gd->sel.fwrite) //
{
UseTargetPages(fb_pages, 0);
}
if(gd->sel.zwrite) data2->UseTargetPages();
{
UseTargetPages(zb_pages, 1); //
}
if(s_dump) if(s_dump)
{ {
@ -304,8 +316,17 @@ void GSRendererSW::Draw()
m_rl->Queue(data); m_rl->Queue(data);
} }
// TODO: m_perfmon.Put(GSPerfMon::Prim, stats.prims); int prims = 0;
// TODO: m_perfmon.Put(GSPerfMon::Fillrate, stats.pixels);
switch(data->primclass)
{
case GS_POINT_CLASS: prims = data->count; break;
case GS_LINE_CLASS: prims = data->count / 2; break;
case GS_TRIANGLE_CLASS: prims = data->count / 3; break;
case GS_SPRITE_CLASS: prims = data->count / 2; break;
}
m_perfmon.Put(GSPerfMon::Prim, prims);
/* /*
if(0)//stats.ticks > 5000000) if(0)//stats.ticks > 5000000)
@ -329,15 +350,6 @@ void GSRendererSW::Sync(int reason)
// NOTE: m_fzb_pages is refcounted, zeroing is done automatically // NOTE: m_fzb_pages is refcounted, zeroing is done automatically
#ifdef _DEBUG
for(size_t i = 0; i < countof(m_fzb_pages); i++)
{
ASSERT(m_fzb_pages[i] == 0);
}
#endif
memset(m_tex_pages, 0, sizeof(m_tex_pages)); memset(m_tex_pages, 0, sizeof(m_tex_pages));
} }

View File

@ -30,14 +30,16 @@ class GSRendererSW : public GSRendererT<GSVertexSW>
class GSRasterizerData2 : public GSRasterizerData class GSRasterizerData2 : public GSRasterizerData
{ {
GSRendererSW* m_parent; GSRendererSW* m_parent;
GSOffset* m_fb; const list<uint32>* m_fb_pages;
GSOffset* m_zb; const list<uint32>* m_zb_pages;
bool m_using_pages;
public: public:
GSRasterizerData2(GSRendererSW* parent) GSRasterizerData2(GSRendererSW* parent, const list<uint32>* fb_pages, const list<uint32>* zb_pages)
: m_parent(parent) : m_parent(parent)
, m_fb(parent->m_context->offset.fb) , m_fb_pages(fb_pages)
, m_zb(parent->m_context->offset.zb) , m_zb_pages(zb_pages)
, m_using_pages(false)
{ {
GSScanlineGlobalData* gd = (GSScanlineGlobalData*)_aligned_malloc(sizeof(GSScanlineGlobalData), 32); GSScanlineGlobalData* gd = (GSScanlineGlobalData*)_aligned_malloc(sizeof(GSScanlineGlobalData), 32);
@ -51,24 +53,54 @@ class GSRendererSW : public GSRendererT<GSVertexSW>
virtual ~GSRasterizerData2() virtual ~GSRasterizerData2()
{ {
ReleaseTargetPages();
GSScanlineGlobalData* gd = (GSScanlineGlobalData*)param; GSScanlineGlobalData* gd = (GSScanlineGlobalData*)param;
GSVector4i r = bbox.rintersect(scissor);
if(gd->sel.fwrite)
{
m_parent->ReleaseTargetPages(m_fb->GetPages(r), 0);
}
if(gd->sel.zwrite)
{
m_parent->ReleaseTargetPages(m_zb->GetPages(r), 1);
}
if(gd->clut) _aligned_free(gd->clut); if(gd->clut) _aligned_free(gd->clut);
if(gd->dimx) _aligned_free(gd->dimx); if(gd->dimx) _aligned_free(gd->dimx);
_aligned_free(gd); _aligned_free(gd);
m_parent->m_perfmon.Put(GSPerfMon::Fillrate, pixels);
}
void UseTargetPages()
{
if(m_using_pages) {ASSERT(0); return;}
GSScanlineGlobalData* gd = (GSScanlineGlobalData*)param;
if(gd->sel.fwrite)
{
m_parent->UseTargetPages(m_fb_pages, 0);
}
if(gd->sel.zwrite)
{
m_parent->UseTargetPages(m_zb_pages, 1);
}
m_using_pages = true;
}
void ReleaseTargetPages()
{
if(!m_using_pages) {ASSERT(0); return;}
GSScanlineGlobalData* gd = (GSScanlineGlobalData*)param;
if(gd->sel.fwrite)
{
m_parent->ReleaseTargetPages(m_fb_pages, 0);
}
if(gd->sel.zwrite)
{
m_parent->ReleaseTargetPages(m_zb_pages, 1);
}
m_using_pages = false;
} }
}; };

View File

@ -592,7 +592,11 @@ void GSState::ApplyTEX0(int i, GIFRegTEX0& TEX0)
bool wt = m_mem.m_clut.WriteTest(TEX0, m_env.TEXCLUT); bool wt = m_mem.m_clut.WriteTest(TEX0, m_env.TEXCLUT);
if(wt || PRIM->CTXT == i && TEX0 != m_env.CTXT[i].TEX0) // clut loading already covered with WriteTest, for drawing only have to check CPSM and CSA (MGS3 intro skybox would be drawn piece by piece without this)
uint64 mask = 0x1f78001c3fffffffull; // TBP0 TBW PSM TW TCC TFX CPSM CSA
if(wt || PRIM->CTXT == i && ((TEX0.u64 ^ m_env.CTXT[i].TEX0.u64) & mask))
{ {
Flush(); Flush();
} }
@ -743,7 +747,9 @@ template<int i> void GSState::GIFRegHandlerTEX2(const GIFReg* RESTRICT r)
// TFX, TCC, TH, TW, TBW, and TBP0 // TFX, TCC, TH, TW, TBW, and TBP0
uint64 mask = 0xFFFFFFE003F00000ull; // TEX2 bits uint64 mask = 0xFFFFFFE003F00000ull; // TEX2 bits
GIFRegTEX0 TEX0; GIFRegTEX0 TEX0;
TEX0.u64 = (m_env.CTXT[i].TEX0.u64 & ~mask) | (r->u64 & mask); TEX0.u64 = (m_env.CTXT[i].TEX0.u64 & ~mask) | (r->u64 & mask);
ApplyTEX0(i, TEX0); ApplyTEX0(i, TEX0);

View File

@ -22,6 +22,44 @@
#include "stdafx.h" #include "stdafx.h"
#include "GSThread.h" #include "GSThread.h"
#ifdef _WINDOWS
InitializeConditionVariablePtr pInitializeConditionVariable;
WakeConditionVariablePtr pWakeConditionVariable;
WakeAllConditionVariablePtr pWakeAllConditionVariable;
SleepConditionVariableSRWPtr pSleepConditionVariableSRW;
InitializeSRWLockPtr pInitializeSRWLock;;
AcquireSRWLockExclusivePtr pAcquireSRWLockExclusive;
ReleaseSRWLockExclusivePtr pReleaseSRWLockExclusive;
class InitCondVar
{
HMODULE m_kernel32;
public:
InitCondVar()
{
m_kernel32 = LoadLibrary("kernel32.dll"); // should not call LoadLibrary from DllMain, but kernel32.dll is the only one guaranteed to be loaded already
pInitializeConditionVariable = (InitializeConditionVariablePtr)GetProcAddress(m_kernel32, "InitializeConditionVariable");
pWakeConditionVariable = (WakeConditionVariablePtr)GetProcAddress(m_kernel32, "WakeConditionVariable");
pWakeAllConditionVariable = (WakeAllConditionVariablePtr)GetProcAddress(m_kernel32, "WakeAllConditionVariable");
pSleepConditionVariableSRW = (SleepConditionVariableSRWPtr)GetProcAddress(m_kernel32, "SleepConditionVariableSRW");
pInitializeSRWLock = (InitializeSRWLockPtr)GetProcAddress(m_kernel32, "InitializeSRWLock");
pAcquireSRWLockExclusive = (AcquireSRWLockExclusivePtr)GetProcAddress(m_kernel32, "AcquireSRWLockExclusive");
pReleaseSRWLockExclusive = (ReleaseSRWLockExclusivePtr)GetProcAddress(m_kernel32, "ReleaseSRWLockExclusive");
}
virtual ~InitCondVar()
{
FreeLibrary(m_kernel32);
}
};
static InitCondVar s_icv;
#endif
GSThread::GSThread() GSThread::GSThread()
{ {
#ifdef _WINDOWS #ifdef _WINDOWS

View File

@ -23,6 +23,22 @@
#ifdef _WINDOWS #ifdef _WINDOWS
typedef void (WINAPI * InitializeConditionVariablePtr)(CONDITION_VARIABLE* ConditionVariable);
typedef void (WINAPI * WakeConditionVariablePtr)(CONDITION_VARIABLE* ConditionVariable);
typedef void (WINAPI * WakeAllConditionVariablePtr)(CONDITION_VARIABLE* ConditionVariable);
typedef void (WINAPI * SleepConditionVariableSRWPtr)(CONDITION_VARIABLE* ConditionVariable, SRWLOCK* SRWLock, DWORD dwMilliseconds, ULONG Flags);
typedef void (WINAPI * InitializeSRWLockPtr)(SRWLOCK* SRWLock);
typedef void (WINAPI * AcquireSRWLockExclusivePtr)(SRWLOCK* SRWLock);
typedef void (WINAPI * ReleaseSRWLockExclusivePtr)(SRWLOCK* SRWLock);
extern InitializeConditionVariablePtr pInitializeConditionVariable;
extern WakeConditionVariablePtr pWakeConditionVariable;
extern WakeAllConditionVariablePtr pWakeAllConditionVariable;
extern SleepConditionVariableSRWPtr pSleepConditionVariableSRW;
extern InitializeSRWLockPtr pInitializeSRWLock;;
extern AcquireSRWLockExclusivePtr pAcquireSRWLockExclusive;
extern ReleaseSRWLockExclusivePtr pReleaseSRWLockExclusive;
class GSThread class GSThread
{ {
DWORD m_ThreadId; DWORD m_ThreadId;
@ -68,6 +84,32 @@ public:
bool Wait() {return WaitForSingleObject(m_hEvent, INFINITE) == WAIT_OBJECT_0;} bool Wait() {return WaitForSingleObject(m_hEvent, INFINITE) == WAIT_OBJECT_0;}
}; };
class GSCondVarLock
{
SRWLOCK m_lock;
public:
GSCondVarLock() {pInitializeSRWLock(&m_lock);}
void Lock() {pAcquireSRWLockExclusive(&m_lock);}
void Unlock() {pReleaseSRWLockExclusive(&m_lock);}
operator SRWLOCK* () {return &m_lock;}
};
class GSCondVar
{
CONDITION_VARIABLE m_cv;
public:
GSCondVar() {pInitializeConditionVariable(&m_cv);}
void Set() {pWakeConditionVariable(&m_cv);}
void Wait(GSCondVarLock& lock) {pSleepConditionVariableSRW(&m_cv, lock, INFINITE, 0);}
operator CONDITION_VARIABLE* () {return &m_cv;}
};
#else #else
#include <pthread.h> #include <pthread.h>
@ -128,6 +170,34 @@ public:
bool Wait() {return sem_wait(&m_sem) == 0;} bool Wait() {return sem_wait(&m_sem) == 0;}
}; };
class GSCondVarLock
{
pthread_mutex_t m_lock;
public:
GSCondVarLock() {pthread_mutex_init(&m_lock, NULL);}
virtual ~GSCondVarLock() {pthread_mutex_destroy(&m_lock);}
void Lock() {pthread_mutex_lock(&m_lock);}
void Unlock() {pthread_mutex_unlock(&m_lock);}
operator pthread_mutex_t* () {return &m_lock;}
};
class GSCondVar
{
pthread_cond_t m_cv;
public:
GSCondVar() {pthread_cond_init(&m_cv);}
virtual ~GSCondVar() {pthread_cond_destroy(&m_cv);}
void Set() {pthread_cond_signal(&m_cv);}
void Wait(GSCondVarLock& lock) {pthread_cond_wait(&m_cv, lock);}
operator pthread_cond_t* () {return &m_cv;}
};
#endif #endif
class GSAutoLock class GSAutoLock
@ -167,42 +237,21 @@ protected:
queue<T> m_queue; queue<T> m_queue;
volatile bool m_exit; volatile bool m_exit;
struct {GSCritSec lock; GSEvent notempty; volatile long count;} m_ev; struct {GSCritSec lock; GSEvent notempty; volatile long count;} m_ev;
#ifdef _WINDOWS struct {GSCondVar notempty, empty; GSCondVarLock lock; bool available;} m_cv;
struct {SRWLOCK lock; CONDITION_VARIABLE notempty, empty; bool available;} m_cv;
HMODULE m_kernel32;
typedef void (WINAPI * InitializeConditionVariablePtr)(CONDITION_VARIABLE* ConditionVariable);
typedef void (WINAPI * WakeConditionVariablePtr)(CONDITION_VARIABLE* ConditionVariable);
typedef void (WINAPI * WakeAllConditionVariablePtr)(CONDITION_VARIABLE* ConditionVariable);
typedef void (WINAPI * SleepConditionVariableSRWPtr)(CONDITION_VARIABLE* ConditionVariable, SRWLOCK* SRWLock, DWORD dwMilliseconds, ULONG Flags);
typedef void (WINAPI * InitializeSRWLockPtr)(SRWLOCK* SRWLock);
typedef void (WINAPI * AcquireSRWLockExclusivePtr)(SRWLOCK* SRWLock);
typedef void (WINAPI * ReleaseSRWLockExclusivePtr)(SRWLOCK* SRWLock);
InitializeConditionVariablePtr pInitializeConditionVariable;
WakeConditionVariablePtr pWakeConditionVariable;
WakeAllConditionVariablePtr pWakeAllConditionVariable;
SleepConditionVariableSRWPtr pSleepConditionVariableSRW;
InitializeSRWLockPtr pInitializeSRWLock;;
AcquireSRWLockExclusivePtr pAcquireSRWLockExclusive;
ReleaseSRWLockExclusivePtr pReleaseSRWLockExclusive;
#elif defined(_LINUX)
struct {pthread_mutex_t lock; pthread_cond_t notempty, empty; bool available;} m_cv;
#endif
void ThreadProc() void ThreadProc()
{ {
if(m_cv.available) if(m_cv.available)
{ {
#ifdef _WINDOWS m_cv.lock.Lock();
pAcquireSRWLockExclusive(&m_cv.lock);
while(true) while(true)
{ {
while(m_queue.empty()) while(m_queue.empty())
{ {
pSleepConditionVariableSRW(&m_cv.notempty, &m_cv.lock, INFINITE, 0); m_cv.notempty.Wait(m_cv.lock);
if(m_exit) {pReleaseSRWLockExclusive(&m_cv.lock); return;} if(m_exit) {m_cv.lock.Unlock(); return;}
} }
{ {
@ -210,51 +259,20 @@ protected:
T item = m_queue.front(); T item = m_queue.front();
pReleaseSRWLockExclusive(&m_cv.lock); m_cv.lock.Unlock();
Process(item); Process(item);
pAcquireSRWLockExclusive(&m_cv.lock); m_cv.lock.Lock();
m_queue.pop(); m_queue.pop();
} }
if(m_queue.empty()) if(m_queue.empty())
{ {
pWakeConditionVariable(&m_cv.empty); m_cv.empty.Set();
} }
} }
#elif defined(_LINUX)
pthread_mutex_lock(&m_cv.lock);
while(true)
{
while(m_queue.empty())
{
pthread_cond_wait(&m_cv.notempty, &m_cv.lock);
if(m_exit) {pthread_mutex_unlock(&m_cv.lock); return;}
}
{
// NOTE: this is scoped because we must make sure the last item is no longer around when Wait detects an empty queue
T item = m_queue.front();
pthread_mutex_unlock(&m_cv.lock);
Process(item);
pthread_mutex_lock(&m_cv.lock);
m_queue.pop();
}
if(m_queue.empty())
{
pthread_cond_signal(&m_cv.empty);
}
}
#endif
} }
else else
{ {
@ -302,33 +320,12 @@ public:
#ifdef _WINDOWS #ifdef _WINDOWS
m_cv.available = false; m_cv.available = pInitializeConditionVariable != NULL;
m_kernel32 = LoadLibrary("kernel32.dll");
pInitializeConditionVariable = (InitializeConditionVariablePtr)GetProcAddress(m_kernel32, "InitializeConditionVariable");
pWakeConditionVariable = (WakeConditionVariablePtr)GetProcAddress(m_kernel32, "WakeConditionVariable");
pWakeAllConditionVariable = (WakeAllConditionVariablePtr)GetProcAddress(m_kernel32, "WakeAllConditionVariable");
pSleepConditionVariableSRW = (SleepConditionVariableSRWPtr)GetProcAddress(m_kernel32, "SleepConditionVariableSRW");
pInitializeSRWLock = (InitializeSRWLockPtr)GetProcAddress(m_kernel32, "InitializeSRWLock");
pAcquireSRWLockExclusive = (AcquireSRWLockExclusivePtr)GetProcAddress(m_kernel32, "AcquireSRWLockExclusive");
pReleaseSRWLockExclusive = (ReleaseSRWLockExclusivePtr)GetProcAddress(m_kernel32, "ReleaseSRWLockExclusive");
if(pInitializeConditionVariable != NULL)
{
pInitializeSRWLock(&m_cv.lock);
pInitializeConditionVariable(&m_cv.notempty);
pInitializeConditionVariable(&m_cv.empty);
m_cv.available = true;
}
#elif defined(_LINUX) #elif defined(_LINUX)
m_cv.available = true;
// FIXME attribute m_cv.available = true;
pthread_cond_init(&m_cv.notempty, NULL);
pthread_cond_init(&m_cv.empty, NULL);
pthread_mutex_init(&m_cv.lock, NULL);
#endif #endif
CreateThread(); CreateThread();
@ -338,32 +335,14 @@ public:
{ {
m_exit = true; m_exit = true;
if(m_cv.available) if(m_cv.available)
{ {
#ifdef _WINDOWS m_cv.notempty.Set();
pWakeConditionVariable(&m_cv.notempty);
#elif defined(_LINUX)
pthread_cond_signal(&m_cv.notempty);
pthread_mutex_destroy(&m_cv.lock);
pthread_cond_destroy(&m_cv.notempty);
pthread_cond_destroy(&m_cv.empty);
#endif
} }
else else
{ {
m_ev.notempty.Set(); m_ev.notempty.Set();
} }
#ifdef _WINDOWS
if(m_kernel32 != NULL)
{
FreeLibrary(m_kernel32); // lol, decrement the refcount anyway
}
#endif
} }
int GetCount() const int GetCount() const
@ -373,31 +352,18 @@ public:
virtual void Push(const T& item) virtual void Push(const T& item)
{ {
if(m_cv.available) if(m_cv.available)
{ {
#ifdef _WINDOWS m_cv.lock.Lock();
pAcquireSRWLockExclusive(&m_cv.lock);
m_queue.push(item); m_queue.push(item);
pReleaseSRWLockExclusive(&m_cv.lock); m_cv.lock.Unlock();
pWakeConditionVariable(&m_cv.notempty); m_cv.notempty.Set();
#elif defined(_LINUX)
pthread_mutex_lock(&m_cv.lock);
m_queue.push(item);
pthread_mutex_unlock(&m_cv.lock);
pthread_cond_signal(&m_cv.notempty);
#endif
} }
else else
{ {
GSAutoLock l(&m_ev.lock); GSAutoLock l(&m_ev.lock);
m_queue.push(item); m_queue.push(item);
@ -412,36 +378,22 @@ public:
virtual void Wait() virtual void Wait()
{ {
if(m_cv.available) if(m_cv.available)
{ {
#ifdef _WINDOWS m_cv.lock.Lock();
pAcquireSRWLockExclusive(&m_cv.lock);
while(!m_queue.empty()) while(!m_queue.empty())
{ {
pSleepConditionVariableSRW(&m_cv.empty, &m_cv.lock, INFINITE, 0); m_cv.empty.Wait(m_cv.lock);
} }
pReleaseSRWLockExclusive(&m_cv.lock); m_cv.lock.Unlock();
#elif defined(_LINUX)
pthread_mutex_lock(&m_cv.lock);
while(!m_queue.empty())
{
pthread_cond_wait(&m_cv.empty, &m_cv.lock);
}
pthread_mutex_unlock(&m_cv.lock);
#endif
} }
else else
{ {
// NOTE: it is the safest to have our own counter because m_queue.pop() might decrement its own before the last item runs out of its scope and gets destroyed (implementation dependent) // NOTE: it is the safest to have our own counter because m_queue.pop() might decrement its own before the last item runs out of its scope and gets destroyed (implementation dependent)
while(m_ev.count > 0) _mm_pause(); while(m_ev.count > 0) _mm_pause();
} }
m_count++; m_count++;

View File

@ -71,6 +71,17 @@
#endif #endif
// put these into vc9/common7/ide/usertype.dat to have them highlighted
typedef unsigned char uint8;
typedef signed char int8;
typedef unsigned short uint16;
typedef signed short int16;
typedef unsigned int uint32;
typedef signed int int32;
typedef unsigned long long uint64;
typedef signed long long int64;
// stdc // stdc
#include <stddef.h> #include <stddef.h>
@ -115,6 +126,57 @@ using namespace std;
using namespace stdext; using namespace stdext;
// hashing algoritms at: http://www.cris.com/~Ttwang/tech/inthash.htm
// default hash_compare does ldiv and other crazy stuff to reduce speed
template<> class hash_compare<uint32>
{
public:
enum {bucket_size = 1};
size_t operator()(uint32 key) const
{
key += ~(key << 15);
key ^= (key >> 10);
key += (key << 3);
key ^= (key >> 6);
key += ~(key << 11);
key ^= (key >> 16);
return (size_t)key;
}
bool operator()(uint32 a, uint32 b) const
{
return a < b;
}
};
template<> class hash_compare<uint64>
{
public:
enum {bucket_size = 1};
size_t operator()(uint64 key) const
{
key += ~(key << 32);
key ^= (key >> 22);
key += ~(key << 13);
key ^= (key >> 8);
key += (key << 3);
key ^= (key >> 15);
key += ~(key << 27);
key ^= (key >> 31);
return (size_t)key;
}
bool operator()(uint64 a, uint64 b) const
{
return a < b;
}
};
#define vsnprintf _vsnprintf #define vsnprintf _vsnprintf
#define snprintf _snprintf #define snprintf _snprintf
@ -171,19 +233,6 @@ struct aligned_free_object {template<class T> void operator()(T& p) {_aligned_fr
struct aligned_free_first {template<class T> void operator()(T& p) {_aligned_free(p.first);}}; struct aligned_free_first {template<class T> void operator()(T& p) {_aligned_free(p.first);}};
struct aligned_free_second {template<class T> void operator()(T& p) {_aligned_free(p.second);}}; struct aligned_free_second {template<class T> void operator()(T& p) {_aligned_free(p.second);}};
// syntactic sugar
// put these into vc9/common7/ide/usertype.dat to have them highlighted
typedef unsigned char uint8;
typedef signed char int8;
typedef unsigned short uint16;
typedef signed short int16;
typedef unsigned int uint32;
typedef signed int int32;
typedef unsigned long long uint64;
typedef signed long long int64;
#define countof(a) (sizeof(a) / sizeof(a[0])) #define countof(a) (sizeof(a) / sizeof(a[0]))
#define ALIGN_STACK(n) __aligned(int, n) __dummy; #define ALIGN_STACK(n) __aligned(int, n) __dummy;