Hi Robert,

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.

adegli

2006/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

}

Attachment: Win32MutexPrivateData.cpp
Description: Binary data

_______________________________________________
osg-users mailing list
[email protected]
http://openscenegraph.net/mailman/listinfo/osg-users
http://www.openscenegraph.org/

Reply via email to