mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
3aa3b1caf6
commit
25072b99c7
|
@ -2002,8 +2002,6 @@ GSOffset::~GSOffset()
|
|||
|
||||
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;
|
||||
|
||||
GSVector4i r = rect.ralign<Align_Outside>(bs);
|
||||
|
|
|
@ -30,8 +30,6 @@
|
|||
|
||||
class GSOffset : public GSAlignedClass<32>
|
||||
{
|
||||
GSCritSec m_lock; // GetPages could be called from multiple threads
|
||||
|
||||
hash_map<uint64, list<uint32>*> m_cache;
|
||||
|
||||
public:
|
||||
|
|
|
@ -163,6 +163,9 @@ void GSRasterizer::Draw(shared_ptr<GSRasterizerData> data)
|
|||
|
||||
uint64 ticks = __rdtsc() - start;
|
||||
|
||||
_InterlockedExchangeAdd(&data->ticks, ticks);
|
||||
_InterlockedExchangeAdd(&data->pixels, m_pixels);
|
||||
|
||||
m_ds->EndDraw(data->frame, ticks, m_pixels);
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,11 @@ public:
|
|||
uint64 frame;
|
||||
void* param;
|
||||
|
||||
// drawing stats
|
||||
|
||||
volatile long ticks;
|
||||
volatile long pixels;
|
||||
|
||||
GSRasterizerData()
|
||||
: scissor(GSVector4i::zero())
|
||||
, bbox(GSVector4i::zero())
|
||||
|
@ -51,6 +56,8 @@ public:
|
|||
, syncpoint(false)
|
||||
, frame(0)
|
||||
, param(NULL)
|
||||
, ticks(0)
|
||||
, pixels(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -166,7 +166,19 @@ void GSRendererSW::Draw()
|
|||
{
|
||||
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;
|
||||
|
||||
|
@ -175,9 +187,8 @@ void GSRendererSW::Draw()
|
|||
return;
|
||||
}
|
||||
|
||||
data->scissor = GSVector4i(m_context->scissor.in);
|
||||
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 = GSVector4i(m_vt.m_min.p.floor().xyxy(m_vt.m_max.p.ceil()));
|
||||
data->scissor = scissor;
|
||||
data->bbox = bbox;
|
||||
data->primclass = m_vt.m_primclass;
|
||||
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
|
||||
|
@ -185,11 +196,6 @@ void GSRendererSW::Draw()
|
|||
data->solidrect = gd->sel.IsSolidRect();
|
||||
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)
|
||||
|
@ -202,7 +208,7 @@ void GSRendererSW::Draw()
|
|||
m_tc->InvalidatePages(zb_pages, m_context->offset.zb->psm);
|
||||
}
|
||||
|
||||
//
|
||||
// set data->syncpoint
|
||||
|
||||
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++)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
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)
|
||||
{
|
||||
UseTargetPages(zb_pages, 1);
|
||||
}
|
||||
data2->UseTargetPages();
|
||||
|
||||
//
|
||||
|
||||
if(s_dump)
|
||||
{
|
||||
|
@ -304,8 +316,17 @@ void GSRendererSW::Draw()
|
|||
m_rl->Queue(data);
|
||||
}
|
||||
|
||||
// TODO: m_perfmon.Put(GSPerfMon::Prim, stats.prims);
|
||||
// TODO: m_perfmon.Put(GSPerfMon::Fillrate, stats.pixels);
|
||||
int prims = 0;
|
||||
|
||||
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)
|
||||
|
@ -329,15 +350,6 @@ void GSRendererSW::Sync(int reason)
|
|||
|
||||
// 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));
|
||||
}
|
||||
|
||||
|
|
|
@ -30,14 +30,16 @@ class GSRendererSW : public GSRendererT<GSVertexSW>
|
|||
class GSRasterizerData2 : public GSRasterizerData
|
||||
{
|
||||
GSRendererSW* m_parent;
|
||||
GSOffset* m_fb;
|
||||
GSOffset* m_zb;
|
||||
const list<uint32>* m_fb_pages;
|
||||
const list<uint32>* m_zb_pages;
|
||||
bool m_using_pages;
|
||||
|
||||
public:
|
||||
GSRasterizerData2(GSRendererSW* parent)
|
||||
GSRasterizerData2(GSRendererSW* parent, const list<uint32>* fb_pages, const list<uint32>* zb_pages)
|
||||
: m_parent(parent)
|
||||
, m_fb(parent->m_context->offset.fb)
|
||||
, m_zb(parent->m_context->offset.zb)
|
||||
, m_fb_pages(fb_pages)
|
||||
, m_zb_pages(zb_pages)
|
||||
, m_using_pages(false)
|
||||
{
|
||||
GSScanlineGlobalData* gd = (GSScanlineGlobalData*)_aligned_malloc(sizeof(GSScanlineGlobalData), 32);
|
||||
|
||||
|
@ -51,24 +53,54 @@ class GSRendererSW : public GSRendererT<GSVertexSW>
|
|||
|
||||
virtual ~GSRasterizerData2()
|
||||
{
|
||||
ReleaseTargetPages();
|
||||
|
||||
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->dimx) _aligned_free(gd->dimx);
|
||||
|
||||
_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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -592,7 +592,11 @@ void GSState::ApplyTEX0(int i, GIFRegTEX0& TEX0)
|
|||
|
||||
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();
|
||||
}
|
||||
|
@ -743,7 +747,9 @@ template<int i> void GSState::GIFRegHandlerTEX2(const GIFReg* RESTRICT r)
|
|||
// TFX, TCC, TH, TW, TBW, and TBP0
|
||||
|
||||
uint64 mask = 0xFFFFFFE003F00000ull; // TEX2 bits
|
||||
|
||||
GIFRegTEX0 TEX0;
|
||||
|
||||
TEX0.u64 = (m_env.CTXT[i].TEX0.u64 & ~mask) | (r->u64 & mask);
|
||||
|
||||
ApplyTEX0(i, TEX0);
|
||||
|
|
|
@ -22,6 +22,44 @@
|
|||
#include "stdafx.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()
|
||||
{
|
||||
#ifdef _WINDOWS
|
||||
|
|
|
@ -23,6 +23,22 @@
|
|||
|
||||
#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
|
||||
{
|
||||
DWORD m_ThreadId;
|
||||
|
@ -68,6 +84,32 @@ public:
|
|||
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
|
||||
|
||||
#include <pthread.h>
|
||||
|
@ -128,6 +170,34 @@ public:
|
|||
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
|
||||
|
||||
class GSAutoLock
|
||||
|
@ -167,42 +237,21 @@ protected:
|
|||
queue<T> m_queue;
|
||||
volatile bool m_exit;
|
||||
struct {GSCritSec lock; GSEvent notempty; volatile long count;} m_ev;
|
||||
#ifdef _WINDOWS
|
||||
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
|
||||
struct {GSCondVar notempty, empty; GSCondVarLock lock; bool available;} m_cv;
|
||||
|
||||
void ThreadProc()
|
||||
{
|
||||
|
||||
if(m_cv.available)
|
||||
{
|
||||
#ifdef _WINDOWS
|
||||
pAcquireSRWLockExclusive(&m_cv.lock);
|
||||
m_cv.lock.Lock();
|
||||
|
||||
while(true)
|
||||
{
|
||||
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();
|
||||
|
||||
pReleaseSRWLockExclusive(&m_cv.lock);
|
||||
m_cv.lock.Unlock();
|
||||
|
||||
Process(item);
|
||||
|
||||
pAcquireSRWLockExclusive(&m_cv.lock);
|
||||
m_cv.lock.Lock();
|
||||
|
||||
m_queue.pop();
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -302,33 +320,12 @@ public:
|
|||
|
||||
#ifdef _WINDOWS
|
||||
|
||||
m_cv.available = false;
|
||||
|
||||
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;
|
||||
}
|
||||
m_cv.available = pInitializeConditionVariable != NULL;
|
||||
|
||||
#elif defined(_LINUX)
|
||||
m_cv.available = true;
|
||||
// FIXME attribute
|
||||
pthread_cond_init(&m_cv.notempty, NULL);
|
||||
pthread_cond_init(&m_cv.empty, NULL);
|
||||
pthread_mutex_init(&m_cv.lock, NULL);
|
||||
|
||||
m_cv.available = true;
|
||||
|
||||
#endif
|
||||
|
||||
CreateThread();
|
||||
|
@ -338,32 +335,14 @@ public:
|
|||
{
|
||||
m_exit = true;
|
||||
|
||||
|
||||
if(m_cv.available)
|
||||
{
|
||||
#ifdef _WINDOWS
|
||||
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
|
||||
m_cv.notempty.Set();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ev.notempty.Set();
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WINDOWS
|
||||
if(m_kernel32 != NULL)
|
||||
{
|
||||
FreeLibrary(m_kernel32); // lol, decrement the refcount anyway
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int GetCount() const
|
||||
|
@ -373,31 +352,18 @@ public:
|
|||
|
||||
virtual void Push(const T& item)
|
||||
{
|
||||
|
||||
if(m_cv.available)
|
||||
{
|
||||
#ifdef _WINDOWS
|
||||
pAcquireSRWLockExclusive(&m_cv.lock);
|
||||
|
||||
m_cv.lock.Lock();
|
||||
|
||||
m_queue.push(item);
|
||||
|
||||
pReleaseSRWLockExclusive(&m_cv.lock);
|
||||
m_cv.lock.Unlock();
|
||||
|
||||
pWakeConditionVariable(&m_cv.notempty);
|
||||
#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
|
||||
m_cv.notempty.Set();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
GSAutoLock l(&m_ev.lock);
|
||||
|
||||
m_queue.push(item);
|
||||
|
@ -412,36 +378,22 @@ public:
|
|||
|
||||
virtual void Wait()
|
||||
{
|
||||
|
||||
if(m_cv.available)
|
||||
{
|
||||
#ifdef _WINDOWS
|
||||
pAcquireSRWLockExclusive(&m_cv.lock);
|
||||
m_cv.lock.Lock();
|
||||
|
||||
while(!m_queue.empty())
|
||||
{
|
||||
pSleepConditionVariableSRW(&m_cv.empty, &m_cv.lock, INFINITE, 0);
|
||||
m_cv.empty.Wait(m_cv.lock);
|
||||
}
|
||||
|
||||
pReleaseSRWLockExclusive(&m_cv.lock);
|
||||
#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
|
||||
m_cv.lock.Unlock();
|
||||
}
|
||||
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)
|
||||
|
||||
while(m_ev.count > 0) _mm_pause();
|
||||
|
||||
}
|
||||
|
||||
m_count++;
|
||||
|
|
|
@ -71,6 +71,17 @@
|
|||
|
||||
#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
|
||||
|
||||
#include <stddef.h>
|
||||
|
@ -115,6 +126,57 @@ using namespace std;
|
|||
|
||||
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 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_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 ALIGN_STACK(n) __aligned(int, n) __dummy;
|
||||
|
|
Loading…
Reference in New Issue