after walking trough micrsoft document, threads and many many test. i changed the mutex
and thread implementation:
i tested it at the moment just only on 2 machine. the dual core computer and my single
core application. i need held for testing many other's because it's very low level, and if the implementation isn't good, we walk into troubles. but the performance is much better no only on the dual core computer.
can you watch may changes ( mark be // ADI begin // adi end or only // ADI )
if you feel good, happy with the changes i will prepare a propre clean implemation
for release 1.1. (other's are also wellcome to test it)
regards
/adegli
2006/6/26, Adrian Egli <[EMAIL PROTECTED]>:
thanks robert,
at the moment i try to locate the real bottleneck. i know your changes ref/unref, but i don't feel that this would be the bottle neck i have at the moment. but i will try the cvs version. hopply it would run much faster.
i will inform you as soon as i have locate the bottleneck. if we have to make some changes, we can discuss it further.
adegli2006/6/26, Robert Osfield < [EMAIL PROTECTED]>:If its the mutex lock/unlock instread Referenced:ref()/unref() that is
cause a bottlneck then try the CVS version of the OSG, it doesn't used
thread safe ref/unref() as widely as it did before, reducing the
overhead of running multi-threaded signifincantly.
On 6/25/06, Adrian Egli < [EMAIL PROTECTED]> wrote:
>
>
> ---------- Forwarded message ----------
> From: Niall Douglas < [EMAIL PROTECTED] >
> Date: 24.06.2006 17:25
> Subject: Re: [Foxgui-users] Performance Issue : SceneView / FoxToolkit /
> OpenThreads / cURL
> To: [EMAIL PROTECTED]
>
> On 24 Jun 2006 at 14:38, Adrian Egli wrote:
>
> > hi i guess microsoft has changed something in the kernel32.dll
> >
> > if i lock the resource with while and try lock it runs much much much
> better
>
> Looks to me like you need spin counts on your mutexs. Either use a
> spincounting critical section, or else use QMutex from TnFOX
> ( http://www.nedprod.com/TnFOX/ ). You will find QMutex is several
> dozen times faster than anything windows provides for you (and the
> version in SVN even works on all architectures, though it's much
> faster on x86 or x64).
>
> Cheers,
> Niall
>
>
>
>
> Using Tomcat but need to do more? Need to support web services, security?
> Get stuff done quickly with pre-integrated technology to make your job
> easier
> Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
> http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
> _______________________________________________
> Foxgui-users mailing list
> [EMAIL PROTECTED]
> https://lists.sourceforge.net/lists/listinfo/foxgui-users
>
> _______________________________________________
> osg-users mailing list
> [email protected]
> http://openscenegraph.net/mailman/listinfo/osg-users
> http://www.openscenegraph.org/
>
>
_______________________________________________
osg-users mailing list
[email protected]
http://openscenegraph.net/mailman/listinfo/osg-users
http://www.openscenegraph.org/
// // OpenThread library, Copyright (C) 2002 - 2003 The Open Thread Group // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //
//
// Win32Thread.c++
// ~~~~~~~~~~~
#include <memory>
#include <string>
#include <iostream>
#if defined(_MSC_VER) && (_MSC_VER < 1300)
#ifdef __SGI_STL
using std::size_t;
#endif
#else
using std::size_t;
#endif
#if defined(_MSC_VER)
#pragma warning( disable : 4996 )
#endif
#include "Win32ThreadPrivateData.h"
struct Win32ThreadCanceled{};
using namespace OpenThreads;
DWORD OpenThreads::cooperativeWait(HANDLE waitHandle, unsigned long timeout){
Thread* current = Thread::CurrentThread();
DWORD dwResult ;
if(current)
{
HANDLE cancelHandle = static_cast<Win32ThreadPrivateData*>(current->getImplementation())->cancelEvent.get();
HANDLE handleSet[2] = {waitHandle, cancelHandle};
dwResult = WaitForMultipleObjects(2,handleSet,FALSE,timeout);
if(dwResult == WAIT_OBJECT_0 + 1 ) throw Win32ThreadCanceled();
}
else
{
dwResult = WaitForSingleObject(waitHandle,timeout);
}
return dwResult;
}
Win32ThreadPrivateData::TlsHolder Win32ThreadPrivateData::TLS;
Win32ThreadPrivateData::~Win32ThreadPrivateData()
{
}
const std::string OPENTHREAD_VERSION_STRING = "OpenThread v1.2preAlpha, WindowThreads (Public Implementation)";
//-----------------------------------------------------------------------------
// Initialize thread master priority level
//
Thread::ThreadPriority Thread::s_masterThreadPriority = Thread::THREAD_PRIORITY_DEFAULT;
bool Thread::s_isInitialized = false;
//-----------------------------------------------------------------------------
// Class to support some static methods necessary for pthread's to work
// correctly.
//
namespace OpenThreads {
class ThreadPrivateActions {
//-------------------------------------------------------------------------
// We're friendly to Thread, so it can issue the methods.
//
friend class Thread;
private:
//-------------------------------------------------------------------------
// Win32Threads standard start routine.
//
static unsigned long __stdcall StartThread(void *data) {
Thread *thread = static_cast<Thread *>(data);
Win32ThreadPrivateData *pd =
static_cast<Win32ThreadPrivateData *>(thread->_prvData);
TlsSetValue(Win32ThreadPrivateData::TLS.ID ,data);
//---------------------------------------------------------------------
// Set the proper scheduling priorities
//
SetThreadSchedulingParams(thread);
pd->isRunning = true;
try{
thread->run();
}
catch(Win32ThreadCanceled&)
{
// thread is canceled do cleanup
try {
thread->cancelCleanup();
} catch(...) { }
}
catch(...)
{
// abnormal termination but must be caught in win32 anyway
}
pd->isRunning = false;
return 0;
};
//-------------------------------------------------------------------------
// Print information related to thread schduling parameters.
//
static void PrintThreadSchedulingInfo(Thread *thread) {
Win32ThreadPrivateData *pd =
static_cast<Win32ThreadPrivateData *>(thread->_prvData);
std::cout<<"Thread "<< thread <<" priority : ";
switch(thread->getSchedulePriority()) {
case Thread::THREAD_PRIORITY_MAX:
std::cout<<"MAXIMAL"<<std::endl;
break;
case Thread::THREAD_PRIORITY_HIGH:
std::cout<<"HIGH"<<std::endl;
break;
case Thread::THREAD_PRIORITY_DEFAULT:
case Thread::THREAD_PRIORITY_NOMINAL:
std::cout<<"NORMAL"<<std::endl;
break;
case Thread::THREAD_PRIORITY_LOW:
std::cout<<"LOW"<<std::endl;
break;
case Thread::THREAD_PRIORITY_MIN:
std::cout<<"MINIMAL"<<std::endl;
break;
}
}
//--------------------------------------------------------------------------
// Set thread scheduling parameters.
// Note that time-critical priority is ommited :
// 1) It's not sensible thing to do
// 2) there's no enum for that in Thread interface
// Also, on Windows, effective thread priority is :
// process priority (manipulated with Get/SetProrityClass) + thread priority (here).
//
//
static int SetThreadSchedulingParams(Thread *thread) {
Win32ThreadPrivateData *pd =
static_cast<Win32ThreadPrivateData *>(thread->_prvData);
int prio = THREAD_PRIORITY_NORMAL;
switch(thread->getSchedulePriority()) {
case Thread::THREAD_PRIORITY_MAX:
prio = THREAD_PRIORITY_HIGHEST;
break;
case Thread::THREAD_PRIORITY_HIGH:
prio = THREAD_PRIORITY_ABOVE_NORMAL;
break;
case Thread::THREAD_PRIORITY_NOMINAL:
prio = THREAD_PRIORITY_NORMAL;
break;
case Thread::THREAD_PRIORITY_LOW:
prio = THREAD_PRIORITY_BELOW_NORMAL;
break;
case Thread::THREAD_PRIORITY_MIN:
prio = THREAD_PRIORITY_IDLE;
break;
}
int status = SetThreadPriority( pd->tid.get(), prio);
if(getenv("OUTPUT_THREADLIB_SCHEDULING_INFO") != 0)
PrintThreadSchedulingInfo(thread);
return status!=0;
};
};
};
Thread* Thread::CurrentThread()
{
return (Thread* )TlsGetValue(Win32ThreadPrivateData::TLS.ID);
};
//----------------------------------------------------------------------------
//
// Description: Set the concurrency level (no-op)
//
// Use static public
//
int Thread::SetConcurrency(int) {
return -1;
};
//----------------------------------------------------------------------------
//
// Description: Get the concurrency level
//
// Use static public
//
int Thread::GetConcurrency() {
return -1;
};
//----------------------------------------------------------------------------
//
// Decription: Constructor
//
// Use: public.
//
Thread::Thread() {
// there's no need for this
// if(!s_isInitialized) Init();
Win32ThreadPrivateData *pd = new Win32ThreadPrivateData();
pd->stackSize = 0;
pd->isRunning = false;
pd->cancelMode = 0;
pd->uniqueId = 0;
pd->threadPriority = Thread::THREAD_PRIORITY_DEFAULT;
pd->threadPolicy = Thread::THREAD_SCHEDULE_DEFAULT;
pd->detached = false;
pd->cancelEvent.set(CreateEvent(NULL,TRUE,FALSE,NULL));
_prvData = static_cast<void *>(pd);
pd->_win32_HandleHolder = NULL; // ADI
}
//----------------------------------------------------------------------------
//
// Decription: Destructor
//
// Use: public.
//
Thread::~Thread() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *>(_prvData);
// ADI BEGIN
if ( pd->_win32_HandleHolder )
CloseHandle(pd->_win32_HandleHolder);
// ADI END
if(pd->isRunning) {
std::cout<<"Error: Thread "<<this<<" still running in destructor"<<std::endl;
pd->cancelMode = 0;
cancel();
}
delete pd;
}
//-----------------------------------------------------------------------------
//
// Description: Initialize Threading
//
// Use: public.
//
void Thread::Init() {
// if(s_isInitialized) return;
// s_masterThreadPriority = Thread::THREAD_PRIORITY_DEFAULT;
s_isInitialized = true;
}
//-----------------------------------------------------------------------------
//
// Description: Get a unique identifier for this thread.
//
// Use: public
//
int Thread::getThreadId() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
return pd->uniqueId;
}
//-----------------------------------------------------------------------------
//
// Description: Get the thread's process id
//
// Use: public
//
int Thread::getProcessId() {
return (int) GetCurrentProcessId();
}
//-----------------------------------------------------------------------------
//
// Description: Determine if the thread is running
//
// Use: public
//
bool Thread::isRunning() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
return pd->isRunning;
}
//-----------------------------------------------------------------------------
//
// Description: Start the thread.
//
// Use: public
//
int Thread::start() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
//-------------------------------------------------------------------------
// Prohibit the stack size from being changed.
// (bb 5/13/2005) it acctualy doesn't matter.
// 1) usually setStackSize()/start() sequence iz serialized.
// 2) if not than we're in trouble anyway - nothing is protected
// pd->stackSizeLocked = true;
unsigned long ID;
pd->tid.set( CreateThread(NULL,pd->stackSize,ThreadPrivateActions::StartThread,static_cast<void *>(this),0,&ID));
pd->uniqueId = (int)ID;
if(!pd->tid) {
return -1;
}
return 0;
}
int Thread::startThread()
{ return start(); }
//-----------------------------------------------------------------------------
//
// Description: Join the thread.
//
// Use: public
//
int Thread::join() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
if( pd->detached )
return -1; // cannot wait for detached ;
if( WaitForSingleObject(pd->tid.get(),INFINITE) != WAIT_OBJECT_0)
return -1 ;
return 0;
}
int Thread::detach()
{
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
pd->detached = true;
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Cancel the thread.
//
// Use: public
//
int Thread::cancel()
{
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
if (pd->isRunning)
{
if( pd->cancelMode == 2 )
return -1;
// signal all interested parties that we are going to exit
SetEvent(pd->cancelEvent.get());
// cancelMode == 1 (asynch)-> kill em
// cancelMode == 0 (deffered) -> wait a little then kill em
// if( (pd->cancelMode == 1) || (WaitForSingleObject(pd->tid,INFINITE)!=WAIT_OBJECT_0) )
if( pd->cancelMode == 1 )
{
// did not terminate cleanly force termination
pd->isRunning = false;
return TerminateThread(pd->tid.get(),(DWORD)-1);
}
}
return 0;
}
int Thread::testCancel()
{
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
if(WaitForSingleObject(pd->cancelEvent.get(),0) != WAIT_OBJECT_0) return 0;
if(pd->cancelMode == 2)
return 0;
DWORD curr = GetCurrentThreadId();
if( pd->uniqueId != (int)curr )
return -1;
// pd->isRunning = false;
// ExitThread(0);
throw Win32ThreadCanceled();
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Disable cancelibility
//
// Use: public
//
int Thread::setCancelModeDisable() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
pd->cancelMode = 2;
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: set the thread to cancel immediately
//
// Use: public
//
int Thread::setCancelModeAsynchronous() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
pd->cancelMode = 1;
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: set the thread to cancel at the next convienent point.
//
// Use: public
//
int Thread::setCancelModeDeferred() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
pd->cancelMode = 0;
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's schedule priority (if able)
//
// Use: public
//
int Thread::setSchedulePriority(ThreadPriority priority) {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
pd->threadPriority = priority;
if(pd->isRunning)
return ThreadPrivateActions::SetThreadSchedulingParams(this);
else
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Get the thread's schedule priority (if able)
//
// Use: public
//
int Thread::getSchedulePriority() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
return pd->threadPriority;
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's scheduling policy (if able)
//
// Use: public
//
int Thread::setSchedulePolicy(ThreadPolicy policy) {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
pd->threadPolicy = policy;
if(pd->isRunning)
return ThreadPrivateActions::SetThreadSchedulingParams(this);
else
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's scheduling policy (if able)
//
// Use: public
//
int Thread::getSchedulePolicy() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
return pd->threadPolicy;
}
//-----------------------------------------------------------------------------
//
// Description: Set the thread's desired stack size
//
// Use: public
//
int Thread::setStackSize(size_t stackSize) {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
if(pd->isRunning) return 13; // cannot set stack size of running thread return EACESS
pd->stackSize = stackSize;
return 0;
}
//-----------------------------------------------------------------------------
//
// Description: Get the thread's stack size.
//
// Use: public
//
size_t Thread::getStackSize() {
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
return pd->stackSize;
}
//-----------------------------------------------------------------------------
//
// Description: set processor affinity for the thread
//
// Use: public
//
int Thread::setProcessorAffinity( unsigned int cpunum )
{
Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData);
DWORD affinityMask = 0x1 << cpunum ; // thread affinity mask
DWORD res =
SetThreadAffinityMask
(
pd->tid.get(), // handle to thread
affinityMask // thread affinity mask
);
/*
This one is funny.
This is "non-mandatory" affinity , winows will try to use dwIdealProcessor
whenever possible ( when Bill's account is over 50B, maybe :-) ).
DWORD SetThreadIdealProcessor(
HANDLE hThread, // handle to the thread
DWORD dwIdealProcessor // ideal processor number
);
*/
// return value 1 means call is ignored ( 9x/ME/SE )
if( res == 1 ) return -1;
// return value 0 is failure
return (res == 0) ? GetLastError() : 0 ;
}
//-----------------------------------------------------------------------------
//
// Description: Print the thread's scheduling information to stdout.
//
// Use: public
//
void Thread::printSchedulingInfo() {
ThreadPrivateActions::PrintThreadSchedulingInfo(this);
}
//-----------------------------------------------------------------------------
//
// Description: Yield the processor
//
// Use: protected
//
#if _WIN32_WINNT < 0x0400 // simulate
int SwitchToThread (void)
{
::Sleep(10);
return 0;
};
#endif
int Thread::YieldCurrentThread()
{
return SwitchToThread();
}
int Thread::microSleep(unsigned int microsec)
{
#if _WIN32_WINNT < 0x0400 // simulate
::Sleep(microsec/1000);
return 0;
#else
//ADI BEGIN
Thread* thread = CurrentThread();
if ( thread ) {
Win32ThreadPrivateData* win32ThreadPrivateData = static_cast<Win32ThreadPrivateData*>(thread->_prvData);
if ( ! win32ThreadPrivateData->_win32_HandleHolder ) win32ThreadPrivateData->_win32_HandleHolder = (void*)CreateWaitableTimer(NULL, TRUE, NULL);
HANDLE sleepTimer = win32ThreadPrivateData->_win32_HandleHolder;
if( !sleepTimer )return -1;
LARGE_INTEGER t; t.QuadPart= -(LONGLONG)microsec*10; // in 100ns units
// negative sign means relative,
if (!SetWaitableTimer(sleepTimer, &t, 0, NULL, NULL, 0)) return -1;
// Wait for the timer.
SwitchToThread();
if (WaitForSingleObject(sleepTimer, INFINITE) != WAIT_OBJECT_0) return -1;
return 0;
}
//ADI END
HandleHolder sleepTimer(CreateWaitableTimer(NULL, TRUE, NULL));
if( !sleepTimer )
return -1;
LARGE_INTEGER t;
t.QuadPart= -(LONGLONG)microsec*10; // in 100ns units
// negative sign means relative,
if (!SetWaitableTimer(sleepTimer.get(), &t, 0, NULL, NULL, 0))
{
return -1;
}
// Wait for the timer.
if (WaitForSingleObject(sleepTimer.get(), INFINITE) != WAIT_OBJECT_0)
{
return -1;
}
return 0;
#endif
}
//
// OpenThread library, Copyright (C) 2002 - 2003 The Open Thread Group
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//
// Win32Mutex.c++ - C++ Mutex class .
// The idea for it is borrowed from SGI STL
// It looks like it's hard to use win32 CRITICALL_SECTIONS withour introducing race
// conditions on InitializeCriticalSection() . So we use spin mutex here.
// ~~~~~~~~~~~~~~~~
//
#include <OpenThreads/Mutex>
// ADI BEGIN
#ifndef _WINDOWS_
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0400
#include <windows.h>
#endif
#include <OpenThreads/Thread>
// ADI END
#include "Win32MutexPrivateData.h"
using namespace OpenThreads;
Win32MutexPrivateData::~Win32MutexPrivateData()
{
}
template <int instance>
struct WIN32MutexSpin {
enum { __low_max = 30, __high_max = 1000 };
// Low if we suspect uniprocessor, high for multiprocessor.
static unsigned __max;
static unsigned __last;
};
template <int instance>
unsigned WIN32MutexSpin <instance>::__max = WIN32MutexSpin <instance>::__low_max;
template <int instance>
unsigned WIN32MutexSpin <instance>::__last = 0;
static void _S_nsec_sleep(int __log_nsec) {
if (__log_nsec <= 20) {
Sleep(0);
} else {
Sleep(1 << (__log_nsec - 20));
}
}
#if defined(_MSC_VER) && _MSC_VER <= 1300
template WIN32MutexSpin <0>;
#endif
//----------------------------------------------------------------------------
//
// Decription: Constructor
//
// Use: public.
//
Mutex::Mutex() {
Win32MutexPrivateData *pd = new Win32MutexPrivateData();
pd->mutex = 0;
_prvData = static_cast<void *>(pd);
}
//----------------------------------------------------------------------------
//
// Decription: Destructor
//
// Use: public.
//
Mutex::~Mutex() {
unlock();
delete static_cast<Win32MutexPrivateData*>(_prvData);
}
// ADI BEGIN
#include <list>
#include <iostream>
typedef std::list<HANDLE> THREAD_LIST;
THREAD_LIST _THREAD_LIST;
// ADI END
//----------------------------------------------------------------------------
//
// Decription: lock the mutex
//
// Use: public.
//
int Mutex::lock() {
//ADI BEGIN
if ( ! trylock() ) {
unsigned int tid = OpenThreads::Thread::CurrentThread()->getThreadId();
HANDLE t = OpenThreads::Thread::CurrentThread()->getImplementation();
_THREAD_LIST.push_back(t);
SuspendThread(t);
} else {
return 0;
}
while ( ! trylock() ) {
SwitchToThread();
}
return 0;
//ADI END
/*
Win32MutexPrivateData *pd =
static_cast<Win32MutexPrivateData*>(_prvData);
volatile unsigned long* lock = &pd->mutex;
// InterlockedExchange returns old value
// if old_value == 0 mutex wasn't locked , now it is
if( !InterlockedExchange((long*)lock, 1L)) {
return 0;
}
unsigned my_spin_max = WIN32MutexSpin<0>::__max;
unsigned my_last_spins = WIN32MutexSpin<0>::__last;
volatile unsigned junk = 17;
unsigned i;
for (i = 0; i < my_spin_max; i++) {
if (i < my_last_spins/2 || *lock) {
junk *= junk; junk *= junk;
junk *= junk; junk *= junk;
SwitchToThread(); // ADI
continue;
}
if (!InterlockedExchange((long*)lock, 1L)) {
// got it!
// Spinning worked. Thus we're probably not being scheduled
// against the other process with which we were contending.
// Thus it makes sense to spin longer the next time.
WIN32MutexSpin<0>::__last = i;
WIN32MutexSpin<0>::__max = WIN32MutexSpin<0>::__high_max;
return 0;
}
}
// We are probably being scheduled against the other process. Sleep.
WIN32MutexSpin<0>::__max = WIN32MutexSpin<0>::__low_max;
for (i = 0 ;; ++i) {
int __log_nsec = i + 6;
if (__log_nsec > 27) __log_nsec = 27;
if (!InterlockedExchange((long*)lock, 1L)) {
return 0;
}
_S_nsec_sleep(__log_nsec);
}
return -1;
*/
}
//----------------------------------------------------------------------------
//
// Decription: unlock the mutex
//
// Use: public.
//
int Mutex::unlock() {
Win32MutexPrivateData *pd =
static_cast<Win32MutexPrivateData*>(_prvData);
volatile unsigned long* lock = &pd->mutex;
*lock = 0;
// This is not sufficient on many multiprocessors, since
// writes to protected variables and the lock may be reordered.
//ADI BEGIN
if ( _THREAD_LIST.size() > 0 ) {
HANDLE t = _THREAD_LIST.front();
_THREAD_LIST.pop_front();
// std::cout << "ResumeThread:" << t << std::endl;
ResumeThread(t);
SwitchToThread();
}
//ADI END
return 0;
}
//----------------------------------------------------------------------------
//
// Decription: test if the mutex may be locked
//
// Use: public.
//
int Mutex::trylock() {
Win32MutexPrivateData *pd =
static_cast<Win32MutexPrivateData*>(_prvData);
volatile unsigned long* lock = &pd->mutex;
if( !InterlockedExchange((long*)lock, 1L)) {
return 1; // TRUE
}
return 0; // FALSE
}
Win32MutexPrivateData.cpp
Description: Binary data
_______________________________________________ osg-users mailing list [email protected] http://openscenegraph.net/mailman/listinfo/osg-users http://www.openscenegraph.org/
