mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-10-06 00:30:10 -06:00
changed svn layout
git-svn-id: svn://ultimatepp.org/upp/trunk@281 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
commit
d2b54f7989
2872 changed files with 670392 additions and 0 deletions
447
uppsrc/Core/Mt.cpp
Normal file
447
uppsrc/Core/Mt.cpp
Normal file
|
|
@ -0,0 +1,447 @@
|
|||
#include "Core.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#ifdef _MULTITHREADED
|
||||
|
||||
static Mutex& sMutexLock()
|
||||
{
|
||||
static Mutex *section;
|
||||
if(!section) {
|
||||
static byte b[sizeof(Mutex)];
|
||||
section = new(b) Mutex;
|
||||
}
|
||||
return *section;
|
||||
}
|
||||
|
||||
INITBLOCK {
|
||||
sMutexLock();
|
||||
}
|
||||
|
||||
Thread::Thread()
|
||||
{
|
||||
sMutexLock();
|
||||
#ifdef PLATFORM_WIN32
|
||||
handle = 0;
|
||||
#endif
|
||||
#ifdef PLATFORM_POSIX
|
||||
handle = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Thread::Detach()
|
||||
{
|
||||
#if defined(PLATFORM_WIN32)
|
||||
if(handle) {
|
||||
CloseHandle(handle);
|
||||
handle = 0;
|
||||
}
|
||||
#elif defined(PLATFORM_POSIX)
|
||||
if(handle) {
|
||||
CHECK(!pthread_detach(handle));
|
||||
handle = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static Atomic sThreadCount;
|
||||
|
||||
#if defined(PLATFORM_WIN32) || defined(PLATFORM_POSIX)
|
||||
static
|
||||
#ifdef PLATFORM_WIN32
|
||||
#ifdef CPU_64
|
||||
unsigned int
|
||||
#else
|
||||
uintptr_t __stdcall
|
||||
#endif
|
||||
#else
|
||||
void *
|
||||
#endif
|
||||
sThreadRoutine(void *arg)
|
||||
{
|
||||
Callback *cb = (Callback *)arg;
|
||||
(*cb)();
|
||||
AtomicDec(sThreadCount);
|
||||
delete cb;
|
||||
#ifdef UPP_HEAP
|
||||
MemoryFreeThread();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool threadr;
|
||||
|
||||
bool Thread::IsST()
|
||||
{
|
||||
return !threadr;
|
||||
}
|
||||
|
||||
bool Thread::Run(Callback _cb)
|
||||
{
|
||||
AtomicInc(sThreadCount);
|
||||
threadr = true;
|
||||
Detach();
|
||||
Callback *cb = new Callback(_cb);
|
||||
#ifdef PLATFORM_WIN32
|
||||
unsigned thread_id;
|
||||
handle = (HANDLE)_beginthreadex(0, 0, sThreadRoutine, cb, 0, &thread_id);
|
||||
#endif
|
||||
#ifdef PLATFORM_POSIX
|
||||
if(pthread_create(&handle, 0, sThreadRoutine, cb))
|
||||
handle = 0;
|
||||
#endif
|
||||
return handle;
|
||||
}
|
||||
|
||||
int Thread::GetCount()
|
||||
{
|
||||
return ReadWithBarrier(sThreadCount);
|
||||
}
|
||||
|
||||
static Atomic sShutdown;
|
||||
|
||||
void Thread::ShutdownThreads()
|
||||
{
|
||||
AtomicInc(sShutdown);
|
||||
while(sThreadCount)
|
||||
Sleep(100);
|
||||
AtomicDec(sShutdown);
|
||||
}
|
||||
|
||||
bool Thread::IsShutdownThreads()
|
||||
{
|
||||
return sShutdown;
|
||||
}
|
||||
|
||||
int Thread::Wait()
|
||||
{
|
||||
if(!IsOpen())
|
||||
return -1;
|
||||
int out;
|
||||
#ifdef PLATFORM_WIN32
|
||||
dword exit;
|
||||
if(!GetExitCodeThread(handle, &exit))
|
||||
return -1;
|
||||
if(exit != STILL_ACTIVE)
|
||||
out = (int)exit;
|
||||
else
|
||||
{
|
||||
if(WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0)
|
||||
return Null;
|
||||
out = GetExitCodeThread(handle, &exit) ? int(exit) : int(Null);
|
||||
}
|
||||
Detach();
|
||||
#endif
|
||||
#ifdef PLATFORM_POSIX
|
||||
void *thread_return;
|
||||
if(pthread_join(handle, &thread_return))
|
||||
out = Null;
|
||||
else
|
||||
out = (int)(intptr_t)thread_return;
|
||||
handle = 0;
|
||||
#endif
|
||||
return out;
|
||||
}
|
||||
|
||||
void Thread::Priority(int percent)
|
||||
{
|
||||
ASSERT(IsOpen());
|
||||
#ifdef PLATFORM_WIN32
|
||||
int prior;
|
||||
if(percent <= 25)
|
||||
prior = THREAD_PRIORITY_LOWEST;
|
||||
else if(percent <= 75)
|
||||
prior = THREAD_PRIORITY_BELOW_NORMAL;
|
||||
else if(percent <= 125)
|
||||
prior = THREAD_PRIORITY_NORMAL;
|
||||
else if(percent <= 175)
|
||||
prior = THREAD_PRIORITY_ABOVE_NORMAL;
|
||||
else
|
||||
prior = THREAD_PRIORITY_HIGHEST;
|
||||
SetThreadPriority(handle, prior);
|
||||
#endif
|
||||
#ifdef PLATFORM_POSIX
|
||||
//!! todo
|
||||
#endif
|
||||
}
|
||||
|
||||
void Thread::Start(Callback cb)
|
||||
{
|
||||
Thread t;
|
||||
t.Run(cb);
|
||||
t.Detach();
|
||||
}
|
||||
|
||||
void Thread::Sleep(int msec)
|
||||
{
|
||||
#ifdef PLATFORM_WIN32
|
||||
::Sleep(msec);
|
||||
#endif
|
||||
#ifdef PLATFORM_POSIX
|
||||
timespec tval;
|
||||
tval.tv_sec = msec / 1000;
|
||||
tval.tv_nsec = (msec % 1000) * 1000000;
|
||||
nanosleep(&tval, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CPU_X86
|
||||
|
||||
#ifndef CPU_SSE2
|
||||
|
||||
static bool sSSE2 = false; //CPU_SSE2();
|
||||
|
||||
inline void ReadMemoryBarrier()
|
||||
{
|
||||
#ifdef CPU_AMD64
|
||||
#ifdef COMPILER_MSC
|
||||
_mm_lfence();
|
||||
#else
|
||||
__asm__("lfence");
|
||||
#endif
|
||||
#else
|
||||
if(sSSE2)
|
||||
#ifdef COMPILER_MSC
|
||||
__asm lfence;
|
||||
#else
|
||||
__asm__("lfence");
|
||||
#endif
|
||||
else {
|
||||
static Atomic x;
|
||||
AtomicInc(x);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void WriteMemoryBarrier() {
|
||||
#ifdef CPU_AMD64
|
||||
#ifdef COMPILER_MSC
|
||||
_mm_sfence();
|
||||
#else
|
||||
__asm__("sfence");
|
||||
#endif
|
||||
#else
|
||||
if(sSSE2)
|
||||
#ifdef COMPILER_MSC
|
||||
__asm sfence;
|
||||
#else
|
||||
__asm__("sfence");
|
||||
#endif
|
||||
else {
|
||||
static Atomic x;
|
||||
AtomicInc(x);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef flagPROFILEMT
|
||||
MtInspector *MtInspector::Dumi()
|
||||
{
|
||||
static MtInspector h(NULL);
|
||||
return &h;
|
||||
}
|
||||
|
||||
MtInspector::~MtInspector()
|
||||
{
|
||||
if(name)
|
||||
RLOG("Mutex " << name << '(' << number << ") " << blocked << "/" << locked <<
|
||||
" = " << Sprintf("%.4f", locked ? (double)blocked / locked : 0) << " blocked/locked times");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
|
||||
void Semaphore::Release()
|
||||
{
|
||||
ReleaseSemaphore(handle, 1, NULL);
|
||||
}
|
||||
|
||||
void Semaphore::Wait()
|
||||
{
|
||||
WaitForSingleObject(handle, INFINITE);
|
||||
}
|
||||
|
||||
Semaphore::Semaphore()
|
||||
{
|
||||
handle = CreateSemaphore(NULL, 0, INT_MAX, NULL);
|
||||
}
|
||||
|
||||
Semaphore::~Semaphore()
|
||||
{
|
||||
CloseHandle(handle);
|
||||
}
|
||||
|
||||
Mutex& sMutexLock();
|
||||
|
||||
|
||||
typedef BOOL (WINAPI *TEC)(LPCRITICAL_SECTION lpCriticalSection);
|
||||
|
||||
static TEC sTec;
|
||||
|
||||
bool Mutex::TryEnter()
|
||||
{
|
||||
if(!sTec) {
|
||||
if(HMODULE hDLL = LoadLibrary("Kernel32"))
|
||||
sTec = (TEC) GetProcAddress(hDLL, "TryEnterCriticalSection");
|
||||
}
|
||||
/* TODO! TryEntery0
|
||||
#ifdef flagPROFILEMT
|
||||
bool b = (*sTec)(§ion);
|
||||
mti->blocked += b;
|
||||
return b;
|
||||
#else
|
||||
*/
|
||||
return (*sTec)(§ion);
|
||||
//#endif
|
||||
}
|
||||
|
||||
/* Win32 RWMutex implementation by Chris Thomasson, cristom@comcast.net */
|
||||
|
||||
void RWMutex::EnterWrite()
|
||||
{
|
||||
EnterCriticalSection ( &m_wrlock );
|
||||
LONG count = InterlockedExchangeAdd(&m_count, -LONG_MAX);
|
||||
if(count < LONG_MAX)
|
||||
if(InterlockedExchangeAdd ( &m_rdwake, LONG_MAX - count ) + LONG_MAX - count )
|
||||
WaitForSingleObject ( m_wrwset, INFINITE );
|
||||
}
|
||||
|
||||
void RWMutex::LeaveWrite()
|
||||
{
|
||||
LONG count = InterlockedExchangeAdd ( &m_count, LONG_MAX );
|
||||
if (count < 0)
|
||||
ReleaseSemaphore ( m_rdwset, count * -1, 0 );
|
||||
LeaveCriticalSection ( &m_wrlock );
|
||||
}
|
||||
|
||||
void RWMutex::EnterRead()
|
||||
{
|
||||
LONG count = InterlockedDecrement ( &m_count );
|
||||
if(count < 0)
|
||||
WaitForSingleObject ( m_rdwset, INFINITE );
|
||||
}
|
||||
|
||||
void RWMutex::LeaveRead()
|
||||
{
|
||||
LONG count = InterlockedIncrement ( &m_count );
|
||||
if ( count < 1 )
|
||||
if ( ! InterlockedDecrement ( &m_rdwake ) )
|
||||
SetEvent ( m_wrwset );
|
||||
}
|
||||
|
||||
RWMutex::RWMutex()
|
||||
: m_count ( LONG_MAX ),
|
||||
m_rdwake ( 0 ),
|
||||
m_wrwset ( CreateEvent ( 0, FALSE, FALSE, 0 ) ),
|
||||
m_rdwset ( CreateSemaphore ( 0, 0, LONG_MAX, 0 ) )
|
||||
{
|
||||
InitializeCriticalSection ( &m_wrlock );
|
||||
}
|
||||
|
||||
RWMutex::~RWMutex()
|
||||
{
|
||||
DeleteCriticalSection ( &m_wrlock );
|
||||
CloseHandle ( m_rdwset );
|
||||
CloseHandle ( m_wrwset );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_POSIX
|
||||
|
||||
Mutex::Mutex()
|
||||
{
|
||||
pthread_mutexattr_t mutex_attr[1];
|
||||
pthread_mutexattr_init(mutex_attr);
|
||||
pthread_mutexattr_settype(mutex_attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(mutex, mutex_attr);
|
||||
#ifdef flagPROFILEMT
|
||||
mti = MtInspector::Dumi();
|
||||
#endif
|
||||
}
|
||||
|
||||
RWMutex::RWMutex()
|
||||
{
|
||||
pthread_rwlock_init(rwlock, NULL);
|
||||
}
|
||||
|
||||
RWMutex::~RWMutex()
|
||||
{
|
||||
pthread_rwlock_destroy(rwlock);
|
||||
}
|
||||
|
||||
/*
|
||||
Event::Event()
|
||||
{
|
||||
pthread_mutex_init(mutex, NULL);
|
||||
pthread_cond_init(cond, NULL);
|
||||
}
|
||||
|
||||
Event::~Event()
|
||||
{
|
||||
pthread_mutex_destroy(mutex);
|
||||
pthread_cond_destroy(cond);
|
||||
}
|
||||
|
||||
void Event::Wait()
|
||||
{
|
||||
pthread_mutex_lock(mutex);
|
||||
pthread_cond_wait(cond, mutex);
|
||||
pthread_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
void Event::Go()
|
||||
{
|
||||
pthread_cond_signal(cond);
|
||||
}
|
||||
*/
|
||||
void Semaphore::Release()
|
||||
{
|
||||
sem_post(&sem);
|
||||
}
|
||||
|
||||
void Semaphore::Wait()
|
||||
{
|
||||
sem_wait(&sem);
|
||||
}
|
||||
|
||||
Semaphore::Semaphore()
|
||||
{
|
||||
sem_init(&sem, 0, 0);
|
||||
}
|
||||
|
||||
Semaphore::~Semaphore()
|
||||
{
|
||||
sem_destroy(&sem);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void StaticMutex::Initialize()
|
||||
{
|
||||
Mutex::Lock __(sMutexLock());
|
||||
if(!ReadWithBarrier(section))
|
||||
BarrierWrite(section, new(buffer) Mutex);
|
||||
}
|
||||
|
||||
void StaticRWMutex::Initialize()
|
||||
{
|
||||
Mutex::Lock __(sMutexLock());
|
||||
if(!ReadWithBarrier(rw))
|
||||
BarrierWrite(rw, new(buffer) RWMutex);
|
||||
}
|
||||
|
||||
void StaticSemaphore::Initialize()
|
||||
{
|
||||
Mutex::Lock __(sMutexLock());
|
||||
if(!ReadWithBarrier(semaphore))
|
||||
BarrierWrite(semaphore, new(buffer) Semaphore);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
Loading…
Reference in a new issue