"
and a later post the same osg-submissions thread:
"it's been a while since I have made the changes but I think it was due to problems with static builds of OpenThreads on windows. I was using
OpenThreads in a communication/synchronisation library (without
OpenSceneGraph). It seems I forgot to post a small change in the CMakeLists file of OpenThreads. If a user turns DYNAMIC_OPENTHREADS to OFF (static build) OT_LIBRARY_STATIC will be defined in the Config.
Without these changes a windows user will always end up with a "__declspec(dllexport)" or "__declspec(dllimport)" which is a problem for static builds."
And another post from Blasius on this topic:
"I tested with VS2005 and VS2008. For 32 bit everything works as expected. For x64 and VS2008 I could successfully do the cmake-configure and then the compilation but I had occasional crashes of cmTryCompileExec.exe (during the cmake-configure phase) which seems to be a cmake bug. With VS2005 and 64bit cmake does not set _OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED although the interlocked functionality should be there. If I place the source snippet from the CHECK_CXX_SOURCE_RUNS macro to a separate sourcefile I can compile and run the resulting executable successfully. Forcing OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED (on VS2005/x64) reveals a bug in "intrin.h" which seems to be fixed in VS2008 but not in VS2005.
In case anyone is interested the lines:
__MACHINEI(unsigned char _interlockedbittestandset(long *a, long b))
__MACHINEI(unsigned char _interlockedbittestandreset(long *a, long b))
__MACHINEX64(unsigned char _interlockedbittestandset64(__int64 *a, __int64 b))
__MACHINEX64(unsigned char _interlockedbittestandreset64(__int64 *a, __int64 b))
should be changed to:
__MACHINEI(unsigned char _interlockedbittestandset(long volatile *a, long b))
__MACHINEI(unsigned char _interlockedbittestandreset(long volatile *a, long b))
__MACHINEX64(unsigned char _interlockedbittestandset64(__int64 volatile *a, __int64 b))
__MACHINEX64(unsigned char _interlockedbittestandreset64(__int64 volatile *a, __int64 b))
The worst thing that can happen is that interlocked funtionality is not detected during cmake-configure and the mutex fallback is used.
Which reminds me another small glitch in the Atomic header so I attached a corrected version.
Why is the OT_LIBRARY_STATIC added to the config file? It is not needed anywhere.
OT_LIBRARY_STATIC is needed if you are doing static-builds on Windows. See my previous post on that.
"
166 lines
4.0 KiB
C++
166 lines
4.0 KiB
C++
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
|
|
*
|
|
* This library is open source and may be redistributed and/or modified under
|
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
|
* (at your option) any later version. The full license is in LICENSE file
|
|
* included with this distribution, and on the openscenegraph.org website.
|
|
*
|
|
* 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
|
|
* OpenSceneGraph Public License for more details.
|
|
*/
|
|
|
|
//
|
|
//
|
|
// WIN32ConditionPrivateData.h - Private data structure for Condition
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
#ifndef _WIN32CONDITIONPRIVATEDATA_H_
|
|
#define _WIN32CONDITIONPRIVATEDATA_H_
|
|
|
|
#ifndef _WINDOWS_
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#define _WIN32_WINNT 0x0400
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#include <OpenThreads/ScopedLock>
|
|
|
|
#include "Win32ThreadPrivateData.h"
|
|
#include "HandleHolder.h"
|
|
|
|
#define InterlockedGet(x) InterlockedExchangeAdd(x,0)
|
|
|
|
namespace OpenThreads {
|
|
|
|
class Condition;
|
|
|
|
class Win32ConditionPrivateData {
|
|
public:
|
|
friend class Condition;
|
|
/// number of waiters.
|
|
long waiters_;
|
|
|
|
Win32ConditionPrivateData ()
|
|
:waiters_(0),
|
|
was_broadcast_(0),
|
|
sema_(CreateSemaphore(NULL,0,0x7fffffff,NULL)),
|
|
waiters_done_(CreateEvent(NULL,FALSE,FALSE,NULL))
|
|
{
|
|
}
|
|
|
|
~Win32ConditionPrivateData ();
|
|
|
|
inline int broadcast ()
|
|
{
|
|
int have_waiters = 0;
|
|
long w = InterlockedGet(&waiters_);
|
|
|
|
if (w > 0)
|
|
{
|
|
// we are broadcasting.
|
|
was_broadcast_ = 1;
|
|
have_waiters = 1;
|
|
}
|
|
|
|
int result = 0;
|
|
if (have_waiters)
|
|
{
|
|
// Wake up all the waiters.
|
|
ReleaseSemaphore(sema_.get(),waiters_,NULL);
|
|
|
|
cooperativeWait(waiters_done_.get(), INFINITE);
|
|
|
|
//end of broadcasting
|
|
was_broadcast_ = 0;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
inline int signal()
|
|
{
|
|
long w = InterlockedGet(&waiters_);
|
|
int have_waiters = w > 0;
|
|
|
|
int result = 0;
|
|
|
|
if (have_waiters)
|
|
{
|
|
if( !ReleaseSemaphore(sema_.get(),1,NULL) )
|
|
result = -1;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
inline int wait (Mutex& external_mutex, long timeout_ms)
|
|
{
|
|
|
|
// Prevent race conditions on the <waiters_> count.
|
|
InterlockedIncrement(&waiters_);
|
|
|
|
int result = 0;
|
|
|
|
ReverseScopedLock<Mutex> lock(external_mutex);
|
|
|
|
// wait in timeslices, giving testCancel() a change to
|
|
// exit the thread if requested.
|
|
try {
|
|
DWORD dwResult = cooperativeWait(sema_.get(), timeout_ms);
|
|
if(dwResult != WAIT_OBJECT_0)
|
|
result = (int)dwResult;
|
|
}
|
|
catch(...){
|
|
// thread is canceled in cooperative wait , do cleanup
|
|
InterlockedDecrement(&waiters_);
|
|
long w = InterlockedGet(&waiters_);
|
|
int last_waiter = was_broadcast_ && w == 0;
|
|
|
|
if (last_waiter) SetEvent(waiters_done_.get());
|
|
// rethrow
|
|
throw;
|
|
}
|
|
|
|
|
|
// We're ready to return, so there's one less waiter.
|
|
InterlockedDecrement(&waiters_);
|
|
long w = InterlockedGet(&waiters_);
|
|
int last_waiter = was_broadcast_ && w == 0;
|
|
|
|
if (result != -1 && last_waiter)
|
|
SetEvent(waiters_done_.get());
|
|
|
|
return result;
|
|
}
|
|
|
|
protected:
|
|
|
|
/// Serialize access to the waiters count.
|
|
/// Mutex waiters_lock_;
|
|
/// Queue up threads waiting for the condition to become signaled.
|
|
HandleHolder sema_;
|
|
/**
|
|
* An auto reset event used by the broadcast/signal thread to wait
|
|
* for the waiting thread(s) to wake up and get a chance at the
|
|
* semaphore.
|
|
*/
|
|
HandleHolder waiters_done_;
|
|
/// Keeps track of whether we were broadcasting or just signaling.
|
|
size_t was_broadcast_;
|
|
};
|
|
|
|
#undef InterlockedGet
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // !_WIN32CONDITIONPRIVATEDATA_H_
|
|
|
|
|
|
|