From 594095a3634202f625d264e590448fcadc9d2a49 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Wed, 31 Aug 2011 23:44:06 +0200 Subject: [PATCH 01/11] Introduce quaternion finite difference method. This implements a function for the quaternion implementation that computes the angular velocity that matches an explicit euler step that propagates from a starting quaternion orientation to a destination quaternion orientation. --- simgear/math/SGMathTest.cxx | 41 +++++++++++++++++++++++++++--- simgear/math/SGQuat.hxx | 50 +++++++++++++++++++++++++++++++------ 2 files changed, 81 insertions(+), 10 deletions(-) diff --git a/simgear/math/SGMathTest.cxx b/simgear/math/SGMathTest.cxx index 415a4d59..ef1f5074 100644 --- a/simgear/math/SGMathTest.cxx +++ b/simgear/math/SGMathTest.cxx @@ -23,6 +23,7 @@ #include #include "SGMath.hxx" +#include "sg_random.h" template bool @@ -198,6 +199,34 @@ QuatTest(void) return true; } +template +bool +QuatDerivativeTest(void) +{ + for (unsigned i = 0; i < 100; ++i) { + // Generate the test case: + // Give a lower bound to the distance, so avoid testing cancelation + T dt = T(0.01) + sg_random(); + // Start with orientation o0, angular velocity av and a random stepsize + SGQuat o0 = SGQuat::fromEulerDeg(T(360)*sg_random(), T(360)*sg_random(), T(360)*sg_random()); + SGVec3 av(sg_random(), sg_random(), sg_random()); + // Do one euler step and renormalize + SGQuat o1 = normalize(o0 + dt*o0.derivative(av)); + + // Check if we can restore the angular velocity + SGVec3 av2 = SGQuat::forwardDifferenceVelocity(o0, o1, dt); + if (!equivalent(av, av2)) + return false; + + // Test with the equivalent orientation + o1 = -o1; + av2 = SGQuat::forwardDifferenceVelocity(o0, o1, dt); + if (!equivalent(av, av2)) + return false; + } + return true; +} + template bool MatrixTest(void) @@ -273,17 +302,17 @@ GeodesyTest(void) // uses examples from Williams aviation formulary SGGeoc lax = SGGeoc::fromRadM(-2.066470, 0.592539, 10.0); SGGeoc jfk = SGGeoc::fromRadM(-1.287762, 0.709186, 10.0); - + double distNm = SGGeodesy::distanceRad(lax, jfk) * SG_RAD_TO_NM; std::cout << "distance is " << distNm << std::endl; if (0.5 < fabs(distNm - 2144)) // 2144 nm return false; - + double crsDeg = SGGeodesy::courseRad(lax, jfk) * SG_RADIANS_TO_DEGREES; std::cout << "course is " << crsDeg << std::endl; if (0.5 < fabs(crsDeg - 66)) // 66 degrees return false; - + SGGeoc adv; SGGeodesy::advanceRadM(lax, crsDeg * SG_DEGREES_TO_RADIANS, 100 * SG_NM_TO_METER, adv); std::cout << "lon:" << adv.getLongitudeRad() << ", lat:" << adv.getLatitudeRad() << std::endl; @@ -298,6 +327,8 @@ GeodesyTest(void) int main(void) { + sg_srandom(17); + // Do vector tests if (!Vec3Test()) return EXIT_FAILURE; @@ -309,6 +340,10 @@ main(void) return EXIT_FAILURE; if (!QuatTest()) return EXIT_FAILURE; + if (!QuatDerivativeTest()) + return EXIT_FAILURE; + if (!QuatDerivativeTest()) + return EXIT_FAILURE; // Do matrix tests if (!MatrixTest()) diff --git a/simgear/math/SGQuat.hxx b/simgear/math/SGQuat.hxx index 256ddb28..9449c914 100644 --- a/simgear/math/SGQuat.hxx +++ b/simgear/math/SGQuat.hxx @@ -230,7 +230,7 @@ public: T absv1 = fabs(v(0)); T absv2 = fabs(v(1)); T absv3 = fabs(v(2)); - + SGVec3 axis; if (absv2 < absv1 && absv3 < absv1) { T quot = v(1)/v(0); @@ -279,7 +279,7 @@ public: xRad = 0; else xRad = atan2(num, den); - + T tmp = 2*(x()*z() - w()*y()); if (tmp <= -1) yRad = T(0.5)*SGMisc::pi(); @@ -287,8 +287,8 @@ public: yRad = -T(0.5)*SGMisc::pi(); else yRad = -asin(tmp); - - num = 2*(x()*y() + w()*z()); + + num = 2*(x()*y() + w()*z()); den = sqrQW + sqrQX - sqrQY - sqrQZ; if (fabs(den) <= SGLimits::min() && fabs(num) <= SGLimits::min()) @@ -323,7 +323,7 @@ public: T sAng = sin(angle); if (fabs(sAng) <= SGLimits::min()) axis = SGVec3(1, 0, 0); - else + else axis = (rNrm/sAng)*imag(*this); angle *= 2; } @@ -449,10 +449,46 @@ public: deriv.x() = T(0.5)*( w()*angVel(0) - z()*angVel(1) + y()*angVel(2)); deriv.y() = T(0.5)*( z()*angVel(0) + w()*angVel(1) - x()*angVel(2)); deriv.z() = T(0.5)*(-y()*angVel(0) + x()*angVel(1) + w()*angVel(2)); - + return deriv; } + /// Return the angular velocity w that makes q0 translate to q1 using + /// an explicit euler step with stepsize h. + /// That is, look for an w where + /// q1 = normalize(q0 + h*q0.derivative(w)) + static SGVec3 + forwardDifferenceVelocity(const SGQuat& q0, const SGQuat& q1, const T& h) + { + // Let D_q0*w = q0.derivative(w), D_q0 the above 4x3 matrix. + // Then D_q0^t*D_q0 = 0.25*Id and D_q0*q0 = 0. + // Let lambda be a nonzero normailzation factor, then + // q1 = normalize(q0 + h*q0.derivative(w)) + // can be rewritten + // lambda*q1 = q0 + h*D_q0*w. + // Multiply left by the transpose D_q0^t and reorder gives + // 4*lambda/h*D_q0^t*q1 = w. + // Now compute lambda by substitution of w into the original + // equation + // lambda*q1 = q0 + 4*lambda*D_q0*D_q0^t*q1, + // multiply by q1^t from the left + // lambda* = + 4*lambda* + // and solving for lambda gives + // lambda = /(1 - 4*). + + // The transpose of the derivative matrix + // the 0.5 factor is handled below + // also note that the initializer uses x, y, z, w instead of w, x, y, z + SGQuat d0(q0.w(), q0.z(), -q0.y(), -q0.x()); + SGQuat d1(-q0.z(), q0.w(), q0.x(), -q0.y()); + SGQuat d2(q0.y(), -q0.x(), q0.w(), -q0.z()); + // 2*D_q0^t*q1 + SGVec3 Dq(dot(d0, q1), dot(d1, q1), dot(d2, q1)); + // Like above, but take into account that Dq = 2*D_q0^t*q1 + T lambda = dot(q0, q1)/(T(1) - dot(Dq, Dq)); + return (2*lambda/h)*Dq; + } + private: // Private because it assumes normalized inputs. @@ -478,7 +514,7 @@ private: // Now our assumption of angles <= 90 deg comes in play. // For that reason, we know that cos05ang is not zero. - // It is even more, we can see from the above formula that + // It is even more, we can see from the above formula that // sqrt(0.5) < cos05ang. From ceac7b46fc932a78fdbdfc2b0094b28ee716f757 Mon Sep 17 00:00:00 2001 From: Dmitry Marakasov Date: Thu, 1 Sep 2011 22:53:59 +0400 Subject: [PATCH 02/11] Fix bashisms in configure.ac --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 81bae41e..09caad86 100644 --- a/configure.ac +++ b/configure.ac @@ -398,7 +398,7 @@ case "${host}" in esac -if test "$OPENAL_OK" == "no" -a "x$enable_headless" != "xyes"; then +if test "$OPENAL_OK" = "no" -a "x$enable_headless" != "xyes"; then echo echo "You *must* have the openal library installed on your system to build" echo "SimGear!" @@ -409,7 +409,7 @@ if test "$OPENAL_OK" == "no" -a "x$enable_headless" != "xyes"; then exit fi -if test "$ALUT_OK" == "no" -a "x$enable_headless" != "xyes"; then +if test "$ALUT_OK" = "no" -a "x$enable_headless" != "xyes"; then echo echo "You *must* have the alut library installed on your system to build" echo "SimGear!" From 059db643bc6e543f665bfbe053ff9f35ada32a6d Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Thu, 1 Sep 2011 18:19:09 +0200 Subject: [PATCH 03/11] Reimplement SGThread and friends. Reimplement the threading stuff using either pthreads or win32 threads. These simple classes should help us to stay osg independent for simgears core classes. --- projects/VC90/SimGear.vcproj | 8 + simgear/threads/SGThread.cxx | 479 ++++++++++++++++++++++++++++------- simgear/threads/SGThread.hxx | 217 ++-------------- 3 files changed, 427 insertions(+), 277 deletions(-) diff --git a/projects/VC90/SimGear.vcproj b/projects/VC90/SimGear.vcproj index 34aa5752..077af7ae 100644 --- a/projects/VC90/SimGear.vcproj +++ b/projects/VC90/SimGear.vcproj @@ -1487,6 +1487,14 @@ RelativePath="..\..\simgear\threads\SGQueue.hxx" > + + + + +// SGThread - Simple pthread class wrappers. +// +// Written by Bernie Bright, started April 2001. +// +// Copyright (C) 2001 Bernard Bright - bbright@bigpond.net.au +// Copyright (C) 2011 Mathias Froehlich +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// -#if defined(_MSC_VER) || defined(__MINGW32__) -# include -#else -# if defined ( sgi ) && !defined( __GNUC__ ) - // This works around a bug triggered when using MipsPro 7.4.1 - // and (at least) IRIX 6.5.20 -# include -# endif -# include -#endif -#if _MSC_VER >= 1300 -# include +#ifdef HAVE_CONFIG_H +# include #endif +#include + #include "SGThread.hxx" -void* -start_handler( void* arg ) +#ifdef _WIN32 + +///////////////////////////////////////////////////////////////////////////// +/// win32 threads +///////////////////////////////////////////////////////////////////////////// + +#include +#include + +struct SGThread::PrivateData { + PrivateData() : + _handle(INVALID_HANDLE_VALUE) + { + } + ~PrivateData() + { + if (_handle == INVALID_HANDLE_VALUE) + return; + CloseHandle(_handle); + _handle = INVALID_HANDLE_VALUE; + } + + static DWORD WINAPI start_routine(LPVOID data) + { + SGThread* thread = reinterpret_cast(data); + thread->run(); + return 0; + } + + bool start(SGThread& thread) + { + if (_handle != INVALID_HANDLE_VALUE) + return false; + _handle = CreateThread(0, 0, start_routine, &thread, 0, 0); + if (_handle == INVALID_HANDLE_VALUE) + return false; + return true; + } + + void join() + { + if (_handle == INVALID_HANDLE_VALUE) + return; + DWORD ret = WaitForSingleObject(_handle, 0); + if (ret != WAIT_OBJECT_0) + return; + CloseHandle(_handle); + _handle = INVALID_HANDLE_VALUE; + } + + HANDLE _handle; +}; + +struct SGMutex::PrivateData { + PrivateData() + { + InitializeCriticalSection((LPCRITICAL_SECTION)&_criticalSection); + } + + ~PrivateData() + { + DeleteCriticalSection((LPCRITICAL_SECTION)&_criticalSection); + } + + void lock(void) + { + EnterCriticalSection((LPCRITICAL_SECTION)&_criticalSection); + } + + void unlock(void) + { + LeaveCriticalSection((LPCRITICAL_SECTION)&_criticalSection); + } + + CRITICAL_SECTION _criticalSection; +}; + +struct SGWaitCondition::PrivateData { + ~PrivateData(void) + { + // The waiters list should be empty anyway + _mutex.lock(); + while (!_pool.empty()) { + CloseHandle(_pool.front()); + _pool.pop_front(); + } + _mutex.unlock(); + } + + void signal(void) + { + _mutex.lock(); + if (!_waiters.empty()) + SetEvent(_waiters.back()); + _mutex.unlock(); + } + + void broadcast(void) + { + _mutex.lock(); + for (std::list::iterator i = _waiters.begin(); i != _waiters.end(); ++i) + SetEvent(*i); + _mutex.unlock(); + } + + bool wait(SGMutex::PrivateData& externalMutex, DWORD msec) + { + _mutex.lock(); + if (_pool.empty()) + _waiters.push_front(CreateEvent(NULL, FALSE, FALSE, NULL)); + else + _waiters.splice(_waiters.begin(), _pool, _pool.begin()); + std::list::iterator i = _waiters.begin(); + _mutex.unlock(); + + externalMutex.unlock(); + + DWORD result = WaitForSingleObject(*i, msec); + + externalMutex.lock(); + + _mutex.lock(); + if (result != WAIT_OBJECT_0) + result = WaitForSingleObject(*i, 0); + _pool.splice(_pool.begin(), _waiters, i); + _mutex.unlock(); + + return result == WAIT_OBJECT_0; + } + + void wait(SGMutex::PrivateData& externalMutex) + { + wait(externalMutex, INFINITE); + } + + // Protect the list of waiters + SGMutex::PrivateData _mutex; + + std::list _waiters; + std::list _pool; +}; + +#else +///////////////////////////////////////////////////////////////////////////// +/// posix threads +///////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +struct SGThread::PrivateData { + PrivateData() : + _started(false) + { + } + ~PrivateData() + { + // If we are still having a started thread and nobody waited, + // now detach ... + if (!_started) + return; + pthread_detach(_thread); + } + + static void *start_routine(void* data) + { + SGThread* thread = reinterpret_cast(data); + thread->run(); + return 0; + } + + bool start(SGThread& thread) + { + if (_started) + return false; + + int ret = pthread_create(&_thread, 0, start_routine, &thread); + if (0 != ret) + return false; + + _started = true; + return true; + } + + void join() + { + if (!_started) + return; + + pthread_join(_thread, 0); + _started = false; + } + + pthread_t _thread; + bool _started; +}; + +struct SGMutex::PrivateData { + PrivateData() + { + int err = pthread_mutex_init(&_mutex, 0); + assert(err == 0); + (void)err; + } + + ~PrivateData() + { + int err = pthread_mutex_destroy(&_mutex); + assert(err == 0); + (void)err; + } + + void lock(void) + { + int err = pthread_mutex_lock(&_mutex); + assert(err == 0); + (void)err; + } + + void unlock(void) + { + int err = pthread_mutex_unlock(&_mutex); + assert(err == 0); + (void)err; + } + + pthread_mutex_t _mutex; +}; + +struct SGWaitCondition::PrivateData { + PrivateData(void) + { + int err = pthread_cond_init(&_condition, NULL); + assert(err == 0); + (void)err; + } + ~PrivateData(void) + { + int err = pthread_cond_destroy(&_condition); + assert(err == 0); + (void)err; + } + + void signal(void) + { + int err = pthread_cond_signal(&_condition); + assert(err == 0); + (void)err; + } + + void broadcast(void) + { + int err = pthread_cond_broadcast(&_condition); + assert(err == 0); + (void)err; + } + + void wait(SGMutex::PrivateData& mutex) + { + int err = pthread_cond_wait(&_condition, &mutex._mutex); + assert(err == 0); + (void)err; + } + + bool wait(SGMutex::PrivateData& mutex, unsigned msec) + { + struct timespec ts; +#ifdef HAVE_CLOCK_GETTIME + if (0 != clock_gettime(CLOCK_REALTIME, &ts)) + return false; +#else + struct timeval tv; + if (0 != gettimeofday(&tv, NULL)) + return false; + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; +#endif + + ts.tv_nsec += 1000000*(msec % 1000); + if (1000000000 <= ts.tv_nsec) { + ts.tv_nsec -= 1000000000; + ts.tv_sec += 1; + } + ts.tv_sec += msec / 1000; + + int evalue = pthread_cond_timedwait(&_condition, &mutex._mutex, &ts); + if (evalue == 0) + return true; + + assert(evalue == ETIMEDOUT); + return false; + } + + pthread_cond_t _condition; +}; + +#endif + +SGThread::SGThread() : + _privateData(new PrivateData) { - SGThread* thr = static_cast(arg); - thr->run(); - return 0; +} + +SGThread::~SGThread() +{ + delete _privateData; + _privateData = 0; +} + +bool +SGThread::start() +{ + return _privateData->start(*this); } void -SGThread::set_cancel( cancel_t mode ) +SGThread::join() { - switch (mode) - { - case CANCEL_DISABLE: - pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, 0 ); - break; - case CANCEL_DEFERRED: - pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, 0 ); - pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, 0 ); - break; - case CANCEL_IMMEDIATE: - pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, 0 ); - pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, 0 ); - break; - default: - break; - } + _privateData->join(); +} + +SGMutex::SGMutex() : + _privateData(new PrivateData) +{ +} + +SGMutex::~SGMutex() +{ + delete _privateData; + _privateData = 0; +} + +void +SGMutex::lock() +{ + _privateData->lock(); +} + +void +SGMutex::unlock() +{ + _privateData->unlock(); +} + +SGWaitCondition::SGWaitCondition() : + _privateData(new PrivateData) +{ +} + +SGWaitCondition::~SGWaitCondition() +{ + delete _privateData; + _privateData = 0; +} + +void +SGWaitCondition::wait(SGMutex& mutex) +{ + _privateData->wait(*mutex._privateData); } bool -SGMutex::trylock() +SGWaitCondition::wait(SGMutex& mutex, unsigned msec) { - int status = pthread_mutex_lock( &mutex ); - if (status == EBUSY) - { - return false; - } - assert( status == 0 ); - return true; + return _privateData->wait(*mutex._privateData, msec); } -#if defined(_MSC_VER) || defined(__MINGW32__) -int gettimeofday(struct timeval* tp, void* tzp) { - LARGE_INTEGER t; - - if(QueryPerformanceCounter(&t)) { - /* hardware supports a performance counter */ - LARGE_INTEGER f; - QueryPerformanceFrequency(&f); - tp->tv_sec = t.QuadPart/f.QuadPart; - tp->tv_usec = ((float)t.QuadPart/f.QuadPart*1000*1000) - - (tp->tv_sec*1000*1000); - } else { - /* hardware doesn't support a performance counter, so get the - time in a more traditional way. */ - DWORD t; - t = timeGetTime(); - tp->tv_sec = t / 1000; - tp->tv_usec = t % 1000; - } - - /* 0 indicates that the call succeeded. */ - return 0; -} -#endif - -bool -SGPthreadCond::wait( SGMutex& mutex, unsigned long ms ) +void +SGWaitCondition::signal() { - struct timeval now; - ::gettimeofday( &now, 0 ); - - // Wait time is now + ms milliseconds - unsigned int sec = ms / 1000; - unsigned int nsec = (ms % 1000) * 1000; - struct timespec abstime; - abstime.tv_sec = now.tv_sec + sec; - abstime.tv_nsec = now.tv_usec*1000 + nsec; - - int status = pthread_cond_timedwait( &cond, &mutex.mutex, &abstime ); - if (status == ETIMEDOUT) - { - return false; - } - - assert( status == 0 ); - return true; + _privateData->signal(); } +void +SGWaitCondition::broadcast() +{ + _privateData->broadcast(); +} diff --git a/simgear/threads/SGThread.hxx b/simgear/threads/SGThread.hxx index 477ca458..7f3a651a 100644 --- a/simgear/threads/SGThread.hxx +++ b/simgear/threads/SGThread.hxx @@ -3,6 +3,7 @@ // Written by Bernie Bright, started April 2001. // // Copyright (C) 2001 Bernard Bright - bbright@bigpond.net.au +// Copyright (C) 2011 Mathias Froehlich // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -18,41 +19,18 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // -// $Id$ #ifndef SGTHREAD_HXX_INCLUDED #define SGTHREAD_HXX_INCLUDED 1 #include -#include -#include -#include - -class SGThread; - -extern "C" { - void* start_handler( void* ); -}; - /** * Encapsulate generic threading methods. * Users derive a class from SGThread and implement the run() member function. */ -class SGThread -{ +class SGThread { public: - /** - * SGThread cancelation modes. - */ - enum cancel_t - { - CANCEL_DISABLE = 0, - CANCEL_DEFERRED, - CANCEL_IMMEDIATE - }; -public: - /** * Create a new thread object. * When a SGThread object is created it does not begin execution @@ -62,18 +40,9 @@ public: /** * Start the underlying thread of execution. - * @param cpu An optional parameter to specify on which CPU to run this - * thread (only supported on IRIX at this time). * @return Pthread error code if execution fails, otherwise returns 0. */ - int start( unsigned cpu = 0 ); - - /** - * Sends a cancellation request to the underlying thread. The target - * thread will either ignore the request, honor it immediately or defer - * it until it reaches a cancellation point. - */ - void cancel(); + bool start(); /** * Suspends the exection of the calling thread until this thread @@ -89,82 +58,31 @@ protected: */ virtual ~SGThread(); - /** - * Set the threads cancellation mode. - * @param mode The required cancellation mode. - */ - void set_cancel( cancel_t mode ); - /** * All threads execute by deriving the run() method of SGThread. * If this function terminates then the thread also terminates. */ virtual void run() = 0; -private: - - /** - * Pthread thread identifier. - */ - pthread_t tid; - - friend void* start_handler( void* ); - private: // Disable copying. - SGThread( const SGThread& ); - SGThread& operator=( const SGThread& ); + SGThread(const SGThread&); + SGThread& operator=(const SGThread&); + + struct PrivateData; + PrivateData* _privateData; + + friend struct PrivateData; }; -inline -SGThread::SGThread() -{ -} - -inline -SGThread::~SGThread() -{ -} - -inline int -SGThread::start( unsigned cpu ) -{ - int status = pthread_create( &tid, 0, start_handler, this ); - assert( status == 0 ); - (void)status; -#if defined( sgi ) - if ( !status && !cpu ) - pthread_setrunon_np( cpu ); -#endif - return status; -} - -inline void -SGThread::join() -{ - int status = pthread_join( tid, 0 ); - assert( status == 0 ); - (void)status; -} - -inline void -SGThread::cancel() -{ - int status = pthread_cancel( tid ); - assert( status == 0 ); - (void)status; -} +class SGWaitCondition; /** * A mutex is used to protect a section of code such that at any time * only a single thread can execute the code. */ -class SGMutex -{ - friend class SGPthreadCond; - +class SGMutex { public: - /** * Create a new mutex. * Under Linux this is a 'fast' mutex. @@ -186,86 +104,46 @@ public: * mutex is already locked and owned by the calling thread, the calling * thread is suspended until the mutex is unlocked, effectively causing * the calling thread to deadlock. - * - * @see SGMutex::trylock */ void lock(); - /** - * Try to lock the mutex for the current thread. Behaves like lock except - * that it doesn't block the calling thread. - * @return true if mutex was successfully locked, otherwise false. - * @see SGMutex::lock - */ - bool trylock(); - /** * Unlock this mutex. * It is assumed that the mutex is locked and owned by the calling thread. */ void unlock(); -protected: +private: + struct PrivateData; + PrivateData* _privateData; - /** - * Pthread mutex. - */ - pthread_mutex_t mutex; + friend class SGWaitCondition; }; -inline SGMutex::SGMutex() -{ - int status = pthread_mutex_init( &mutex, 0 ); - assert( status == 0 ); - (void)status; -} - -inline SGMutex::~SGMutex() -{ - int status = pthread_mutex_destroy( &mutex ); - assert( status == 0 ); - (void)status; -} - -inline void SGMutex::lock() -{ - int status = pthread_mutex_lock( &mutex ); - assert( status == 0 ); - (void)status; -} - -inline void SGMutex::unlock() -{ - int status = pthread_mutex_unlock( &mutex ); - assert( status == 0 ); - (void)status; -} - /** - * A condition variable is a synchronization device that allows threads to + * A condition variable is a synchronization device that allows threads to * suspend execution until some predicate on shared data is satisfied. * A condition variable is always associated with a mutex to avoid race - * conditions. + * conditions. */ -class SGPthreadCond -{ +class SGWaitCondition { public: /** * Create a new condition variable. */ - SGPthreadCond(); + SGWaitCondition(); /** * Destroy the condition object. */ - ~SGPthreadCond(); + ~SGWaitCondition(); /** * Wait for this condition variable to be signaled. * * @param SGMutex& reference to a locked mutex. */ - void wait( SGMutex& ); + void wait(SGMutex&); /** * Wait for this condition variable to be signaled for at most @@ -274,9 +152,9 @@ public: * @param mutex reference to a locked mutex. * @param ms milliseconds to wait for a signal. * - * @return + * @return */ - bool wait( SGMutex& mutex, unsigned long ms ); + bool wait(SGMutex& mutex, unsigned msec); /** * Wake one thread waiting on this condition variable. @@ -294,50 +172,11 @@ public: private: // Disable copying. - SGPthreadCond(const SGPthreadCond& ); - SGPthreadCond& operator=(const SGPthreadCond& ); + SGWaitCondition(const SGWaitCondition&); + SGWaitCondition& operator=(const SGWaitCondition&); -private: - - /** - * The Pthread conditon variable. - */ - pthread_cond_t cond; + struct PrivateData; + PrivateData* _privateData; }; -inline SGPthreadCond::SGPthreadCond() -{ - int status = pthread_cond_init( &cond, 0 ); - assert( status == 0 ); - (void)status; -} - -inline SGPthreadCond::~SGPthreadCond() -{ - int status = pthread_cond_destroy( &cond ); - assert( status == 0 ); - (void)status; -} - -inline void SGPthreadCond::signal() -{ - int status = pthread_cond_signal( &cond ); - assert( status == 0 ); - (void)status; -} - -inline void SGPthreadCond::broadcast() -{ - int status = pthread_cond_broadcast( &cond ); - assert( status == 0 ); - (void)status; -} - -inline void SGPthreadCond::wait( SGMutex& mutex ) -{ - int status = pthread_cond_wait( &cond, &mutex.mutex ); - assert( status == 0 ); - (void)status; -} - #endif /* SGTHREAD_HXX_INCLUDED */ From 08003ceba99b6c81441896a5c60c14bd2352bce5 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Thu, 1 Sep 2011 21:00:48 +0200 Subject: [PATCH 04/11] Revert to simgears thread support. For all source directories outside of simgear/scene, which really depends very hard on osg, avoid using osg classes. This should reenable the use of some basic and scenegraph independent parts of simgear without the the need for osg. --- simgear/io/CMakeLists.txt | 25 +++---- simgear/io/raw_socket.cxx | 110 ++++++++++++++++-------------- simgear/structure/StringTable.cxx | 5 +- simgear/structure/StringTable.hxx | 4 +- simgear/structure/commands.cxx | 13 ++-- simgear/structure/commands.hxx | 5 +- simgear/threads/SGQueue.hxx | 69 +++++++++---------- 7 files changed, 117 insertions(+), 114 deletions(-) diff --git a/simgear/io/CMakeLists.txt b/simgear/io/CMakeLists.txt index 2cdb1d5a..9613e4b9 100644 --- a/simgear/io/CMakeLists.txt +++ b/simgear/io/CMakeLists.txt @@ -2,7 +2,7 @@ include (SimGearComponent) -set(HEADERS +set(HEADERS iochannel.hxx lowlevel.hxx raw_socket.hxx @@ -18,7 +18,7 @@ set(HEADERS HTTPRequest.hxx ) -set(SOURCES +set(SOURCES iochannel.cxx lowlevel.cxx raw_socket.cxx @@ -37,19 +37,20 @@ set(SOURCES simgear_component(io io "${SOURCES}" "${HEADERS}") add_executable(test_sock socktest.cxx) -target_link_libraries(test_sock sgio sgstructure sgdebug ${OPENTHREADS_LIBRARY}) +target_link_libraries(test_sock sgio sgstructure sgthreads sgdebug + ${CMAKE_THREAD_LIBS_INIT} + ${RT_LIBRARY}) add_executable(test_http test_HTTP.cxx) -target_link_libraries(test_http - sgio sgstructure sgtiming sgmisc sgdebug - ${RT_LIBRARY} - ${OPENTHREADS_LIBRARY}) +target_link_libraries(test_http + sgio sgstructure sgthreads sgtiming sgmisc sgdebug + ${CMAKE_THREAD_LIBS_INIT} + ${RT_LIBRARY}) add_test(http ${EXECUTABLE_OUTPUT_PATH}/test_http) add_executable(httpget httpget.cxx) -target_link_libraries(httpget - sgio sgstructure sgtiming sgmisc sgdebug - ${RT_LIBRARY} - ${OPENTHREADS_LIBRARY}) - \ No newline at end of file +target_link_libraries(httpget + sgio sgstructure sgthreads sgtiming sgmisc sgdebug + ${CMAKE_THREAD_LIBS_INIT} + ${RT_LIBRARY}) diff --git a/simgear/io/raw_socket.cxx b/simgear/io/raw_socket.cxx index b849bddc..cf7b20f7 100644 --- a/simgear/io/raw_socket.cxx +++ b/simgear/io/raw_socket.cxx @@ -1,20 +1,20 @@ /* simgear::Socket, adapted from PLIB Socket by James Turner Copyright (C) 2010 James Turner - + PLIB - A Suite of Portable Game Libraries Copyright (C) 1998,2002 Steve Baker - + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. - + You should have received a copy of the GNU Library 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 @@ -47,7 +47,7 @@ # include # include # include -# include +# include # include # include # include @@ -61,40 +61,43 @@ #include #include - -#include -#include -#include +#include namespace { -class Resolver : public OpenThreads::Thread +class Resolver : public SGThread { public: static Resolver* instance() { if (!static_instance) { - OpenThreads::Thread::Init(); - static_instance = new Resolver; atexit(&Resolver::cleanup); static_instance->start(); } - + return static_instance; } - + static void cleanup() { - static_instance->cancel(); + static_instance->shutdown(); + static_instance->join(); } - - Resolver() + + Resolver() : + _done(false) { - // take the lock initially, thread will wait upon it once running - _lock.lock(); } - + + void shutdown() + { + _lock.lock(); + _done = true; + _wait.signal(); + _lock.unlock(); + } + simgear::IPAddress* lookup(const string& host) { simgear::IPAddress* result = NULL; @@ -109,7 +112,7 @@ public: _lock.unlock(); return result; } - + simgear::IPAddress* lookupSync(const string& host) { simgear::IPAddress* result = NULL; @@ -140,31 +143,33 @@ protected: */ virtual void run() { - while (true) { - _wait.wait(&_lock); + _lock.lock(); + while (!_done) { AddressCache::iterator it; - + for (it = _cache.begin(); it != _cache.end(); ++it) { if (it->second == NULL) { string h = it->first; - + _lock.unlock(); simgear::IPAddress* addr = new simgear::IPAddress; // may take seconds or even minutes! lookupHost(h.c_str(), *addr); _lock.lock(); - + // cahce may have changed while we had the lock released - // so iterators may be invalid: restart the traversal it = _cache.begin(); _cache[h] = addr; } // of found un-resolved entry - } // of un-resolved address iteration + } // of un-resolved address iteration + _wait.wait(_lock); } // of thread run loop + _lock.unlock(); } private: static Resolver* static_instance; - + /** * The actual synchronous, blocking host lookup function * do *not* call this with any locks (mutexs) held, since depending @@ -177,7 +182,7 @@ private: memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; bool ok = false; - + struct addrinfo* result0 = NULL; int err = getaddrinfo(host, NULL, &hints, &result0); if (err) { @@ -205,21 +210,22 @@ private: freeaddrinfo(result0); return ok; } - - OpenThreads::Mutex _lock; - OpenThreads::Condition _wait; - + + SGMutex _lock; + SGWaitCondition _wait; + typedef std::map AddressCache; AddressCache _cache; + bool _done; }; Resolver* Resolver::static_instance = NULL; - + } // of anonymous namespace namespace simgear { - + IPAddress::IPAddress ( const char* host, int port ) { set ( host, port ) ; @@ -266,18 +272,18 @@ void IPAddress::set ( const char* host, int port ) addr->sin_addr.s_addr = INADDR_ANY; return; } - + if (strcmp(host, "") == 0) { addr->sin_addr.s_addr = INADDR_BROADCAST; return; } - + // check the cache IPAddress* cached = Resolver::instance()->lookupSync(host); if (cached) { memcpy(addr, cached->getAddr(), cached->getAddrLen()); } - + addr->sin_port = htons (port); // fix up port after getaddrinfo } @@ -289,12 +295,12 @@ IPAddress::~IPAddress() } bool IPAddress::lookupNonblocking(const char* host, IPAddress& addr) -{ +{ IPAddress* cached = Resolver::instance()->lookup(host); if (!cached) { return false; } - + addr = *cached; return true; } @@ -313,9 +319,9 @@ const char* IPAddress::getHost () const return buf; } -unsigned int IPAddress::getIP () const -{ - return addr->sin_addr.s_addr; +unsigned int IPAddress::getIP () const +{ + return addr->sin_addr.s_addr; } unsigned int IPAddress::getPort() const @@ -328,9 +334,9 @@ void IPAddress::setPort(int port) addr->sin_port = htons(port); } -unsigned int IPAddress::getFamily () const -{ - return addr->sin_family; +unsigned int IPAddress::getFamily () const +{ + return addr->sin_family; } const char* IPAddress::getLocalHost () @@ -371,7 +377,7 @@ struct sockaddr* IPAddress::getAddr() const addr = (struct sockaddr_in*) malloc(sizeof(struct sockaddr_in)); memset(addr, 0, sizeof(struct sockaddr_in)); } - + return (struct sockaddr*) addr; } @@ -456,7 +462,7 @@ void Socket::setBroadcast ( bool broadcast ) } else { result = ::setsockopt( handle, SOL_SOCKET, SO_BROADCAST, NULL, 0 ); } - + if ( result < 0 ) { throw sg_exception("Socket::setBroadcast failed"); } @@ -476,7 +482,7 @@ int Socket::bind ( const char* host, int port ) } #endif - // 224.0.0.0 - 239.255.255.255 are multicast + // 224.0.0.0 - 239.255.255.255 are multicast // Usage of 239.x.x.x is recommended for local scope // Reference: http://tools.ietf.org/html/rfc5771 if( ntohl(addr.getIP()) >= 0xe0000000 && ntohl(addr.getIP()) <= 0xefffffff ) { @@ -486,7 +492,7 @@ int Socket::bind ( const char* host, int port ) a.sin_addr.S_un.S_addr = INADDR_ANY; a.sin_family = AF_INET; a.sin_port = htons(port); - + if( (result = ::bind(handle,(const sockaddr*)&a,sizeof(a))) < 0 ) { SG_LOG(SG_IO, SG_ALERT, "bind(any:" << port << ") failed. Errno " << errno << " (" << strerror(errno) << ")"); return result; @@ -636,7 +642,7 @@ int Socket::select ( Socket** reads, Socket** writes, int timeout ) { fd_set r,w; int retval; - + FD_ZERO (&r); FD_ZERO (&w); @@ -674,7 +680,7 @@ int Socket::select ( Socket** reads, Socket** writes, int timeout ) // It bothers me that select()'s first argument does not appear to // work as advertised... [it hangs like this if called with // anything less than FD_SETSIZE, which seems wasteful?] - + // Note: we ignore the 'exception' fd_set - I have never had a // need to use it. The name is somewhat misleading - the only // thing I have ever seen it used for is to detect urgent data - diff --git a/simgear/structure/StringTable.cxx b/simgear/structure/StringTable.cxx index 81afc69b..5dba1848 100644 --- a/simgear/structure/StringTable.cxx +++ b/simgear/structure/StringTable.cxx @@ -1,6 +1,6 @@ #include "StringTable.hxx" -#include +#include namespace simgear { @@ -8,8 +8,7 @@ using namespace std; const string* StringTable::insert(const string& str) { - using namespace OpenThreads; - ScopedLock lock(_mutex); + SGGuard lock(_mutex); StringContainer::iterator it = _strings.insert(str).first; return &*it; } diff --git a/simgear/structure/StringTable.hxx b/simgear/structure/StringTable.hxx index 9e5700d3..8f5d010a 100644 --- a/simgear/structure/StringTable.hxx +++ b/simgear/structure/StringTable.hxx @@ -3,7 +3,7 @@ #include -#include +#include #include #include #include @@ -21,7 +21,7 @@ class StringTable { const std::string* insert(const std::string& str); private: - OpenThreads::Mutex _mutex; + SGMutex _mutex; StringContainer _strings; }; } diff --git a/simgear/structure/commands.cxx b/simgear/structure/commands.cxx index fd67ae4f..6b4b11ea 100644 --- a/simgear/structure/commands.cxx +++ b/simgear/structure/commands.cxx @@ -11,13 +11,12 @@ #include #include -#include -#include - #include "commands.hxx" #include #include +#include +#include #include @@ -36,7 +35,7 @@ SGCommandMgr::~SGCommandMgr () // no-op } -OpenThreads::Mutex SGCommandMgr::_instanceMutex; +SGMutex SGCommandMgr::_instanceMutex; SGCommandMgr* SGCommandMgr::instance() @@ -45,7 +44,7 @@ SGCommandMgr::instance() if (mgr.get()) return mgr.get(); - OpenThreads::ScopedLock lock(_instanceMutex); + SGGuard lock(_instanceMutex); if (mgr.get()) return mgr.get(); @@ -85,8 +84,8 @@ SGCommandMgr::execute (const std::string &name, const SGPropertyNode * arg) cons command_t command = getCommand(name); if (command == 0) return false; - - + + try { return (*command)(arg); } catch (sg_exception& e) { diff --git a/simgear/structure/commands.hxx b/simgear/structure/commands.hxx index 3f8a248f..09f1c1bc 100644 --- a/simgear/structure/commands.hxx +++ b/simgear/structure/commands.hxx @@ -17,8 +17,7 @@ #include #include -#include - +#include #include #include @@ -107,7 +106,7 @@ private: typedef std::map command_map; command_map _commands; - static OpenThreads::Mutex _instanceMutex; + static SGMutex _instanceMutex; }; diff --git a/simgear/threads/SGQueue.hxx b/simgear/threads/SGQueue.hxx index bcdda1d3..37122c5a 100644 --- a/simgear/threads/SGQueue.hxx +++ b/simgear/threads/SGQueue.hxx @@ -5,9 +5,8 @@ #include #include -#include -#include -#include +#include "SGGuard.hxx" +#include "SGThread.hxx" /** * SGQueue defines an interface for a FIFO. @@ -66,7 +65,7 @@ public: protected: /** - * + * */ std::queue fifo; }; @@ -74,7 +73,7 @@ protected: /** * A simple thread safe queue. All access functions are guarded with a mutex. */ -template +template class SGLockedQueue : public SGQueue { public: @@ -95,7 +94,7 @@ public: * @return bool True if queue is empty, otherwisr false. */ virtual bool empty() { - OpenThreads::ScopedLock g(mutex); + SGGuard g(mutex); return this->fifo.empty(); } @@ -105,7 +104,7 @@ public: * @param T object to add. */ virtual void push( const T& item ) { - OpenThreads::ScopedLock g(mutex); + SGGuard g(mutex); this->fifo.push( item ); } @@ -115,7 +114,7 @@ public: * @return T next available object. */ virtual T front() { - OpenThreads::ScopedLock g(mutex); + SGGuard g(mutex); assert( ! this->fifo.empty() ); T item = this->fifo.front(); return item; @@ -127,7 +126,7 @@ public: * @return T next available object. */ virtual T pop() { - OpenThreads::ScopedLock g(mutex); + SGGuard g(mutex); //if (fifo.empty()) throw NoSuchElementException(); assert( ! this->fifo.empty() ); // if (fifo.empty()) @@ -146,7 +145,7 @@ public: * @return size_t size of queue. */ virtual size_t size() { - OpenThreads::ScopedLock g(mutex); + SGGuard g(mutex); return this->fifo.size(); } @@ -155,7 +154,7 @@ private: /** * Mutex to serialise access. */ - SGLOCK mutex; + SGMutex mutex; private: // Prevent copying. @@ -182,10 +181,10 @@ public: ~SGBlockingQueue() {} /** - * + * */ virtual bool empty() { - OpenThreads::ScopedLock g(mutex); + SGGuard g(mutex); return this->fifo.empty(); } @@ -195,7 +194,7 @@ public: * @param T object to add. */ virtual void push( const T& item ) { - OpenThreads::ScopedLock g(mutex); + SGGuard g(mutex); this->fifo.push( item ); not_empty.signal(); } @@ -207,7 +206,7 @@ public: * @return T next available object. */ virtual T front() { - OpenThreads::ScopedLock g(mutex); + SGGuard g(mutex); assert(this->fifo.empty() != true); //if (fifo.empty()) throw ?? @@ -223,10 +222,10 @@ public: * @return T next available object. */ virtual T pop() { - OpenThreads::ScopedLock g(mutex); + SGGuard g(mutex); while (this->fifo.empty()) - not_empty.wait(&mutex); + not_empty.wait(mutex); assert(this->fifo.empty() != true); //if (fifo.empty()) throw ?? @@ -242,7 +241,7 @@ public: * @return size_t size of queue. */ virtual size_t size() { - OpenThreads::ScopedLock g(mutex); + SGGuard g(mutex); return this->fifo.size(); } @@ -251,12 +250,12 @@ private: /** * Mutex to serialise access. */ - OpenThreads::Mutex mutex; + SGMutex mutex; /** * Condition to signal when queue not empty. */ - OpenThreads::Condition not_empty; + SGWaitCondition not_empty; private: // Prevent copying. @@ -284,18 +283,18 @@ public: ~SGBlockingDeque() {} /** - * + * */ virtual void clear() { - OpenThreads::ScopedLock g(mutex); + SGGuard g(mutex); this->queue.clear(); } - + /** - * + * */ virtual bool empty() { - OpenThreads::ScopedLock g(mutex); + SGGuard g(mutex); return this->queue.empty(); } @@ -305,7 +304,7 @@ public: * @param T object to add. */ virtual void push_front( const T& item ) { - OpenThreads::ScopedLock g(mutex); + SGGuard g(mutex); this->queue.push_front( item ); not_empty.signal(); } @@ -316,7 +315,7 @@ public: * @param T object to add. */ virtual void push_back( const T& item ) { - OpenThreads::ScopedLock g(mutex); + SGGuard g(mutex); this->queue.push_back( item ); not_empty.signal(); } @@ -328,7 +327,7 @@ public: * @return T next available object. */ virtual T front() { - OpenThreads::ScopedLock g(mutex); + SGGuard g(mutex); assert(this->queue.empty() != true); //if (queue.empty()) throw ?? @@ -344,10 +343,10 @@ public: * @return T next available object. */ virtual T pop_front() { - OpenThreads::ScopedLock g(mutex); + SGGuard g(mutex); while (this->queue.empty()) - not_empty.wait(&mutex); + not_empty.wait(mutex); assert(this->queue.empty() != true); //if (queue.empty()) throw ?? @@ -364,10 +363,10 @@ public: * @return T next available object. */ virtual T pop_back() { - OpenThreads::ScopedLock g(mutex); + SGGuard g(mutex); while (this->queue.empty()) - not_empty.wait(&mutex); + not_empty.wait(mutex); assert(this->queue.empty() != true); //if (queue.empty()) throw ?? @@ -383,7 +382,7 @@ public: * @return size_t size of queue. */ virtual size_t size() { - OpenThreads::ScopedLock g(mutex); + SGGuard g(mutex); return this->queue.size(); } @@ -392,12 +391,12 @@ private: /** * Mutex to serialise access. */ - OpenThreads::Mutex mutex; + SGMutex mutex; /** * Condition to signal when queue not empty. */ - OpenThreads::Condition not_empty; + SGWaitCondition not_empty; private: // Prevent copying. From 1305e1642581bbbd1ff8b6380da0a999df32d61c Mon Sep 17 00:00:00 2001 From: James Turner Date: Wed, 7 Sep 2011 16:54:28 +0100 Subject: [PATCH 05/11] Work (in progress) on CPack packaging for SimGear --- CMakeLists.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 49916a08..055f915c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,18 @@ string(STRIP ${versionFile} SIMGEAR_VERSION) #packaging SET(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/COPYING") SET(CPACK_RESOURCE_FILE_README "${PROJECT_SOURCE_DIR}/README") +SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Simulation support libraries for FlightGear and related projects") +SET(CPACK_PACKAGE_VENDOR "The FlightGear project") +SET(CPACK_GENERATOR "TBZ2") +SET(CPACK_INSTALL_CMAKE_PROJECTS ${CMAKE_CURRENT_BINARY_DIR};SimGear;ALL;/) + +# split version string into components, note CMAKE_MATCH_0 is the entire regexp match +string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" CPACK_PACKAGE_VERSION ${SIMGEAR_VERSION} ) +set(CPACK_PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1}) +set(CPACK_PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2}) +set(CPACK_PACKAGE_VERSION_PATCH ${CMAKE_MATCH_3}) + +message(STATUS "version is ${CPACK_PACKAGE_VERSION_MAJOR} dot ${CPACK_PACKAGE_VERSION_MINOR} dot ${CPACK_PACKAGE_VERSION_PATCH}") # We have some custom .cmake scripts not in the official distribution. set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMakeModules;${CMAKE_MODULE_PATH}") From 35a449c7d07f82b41fdcbb78b7ee26b0dbc54564 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Wed, 7 Sep 2011 18:37:02 +0200 Subject: [PATCH 06/11] Update the automake based build system to the last changes. --- simgear/Makefile.am | 4 ++-- simgear/io/Makefile.am | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/simgear/Makefile.am b/simgear/Makefile.am index c1e24ed7..d4a9b605 100644 --- a/simgear/Makefile.am +++ b/simgear/Makefile.am @@ -31,6 +31,7 @@ SUBDIRS_ALWAYS = \ bucket \ ephemeris \ $(HLA_DIR) \ + $(SGTHREAD_DIR) \ io \ magvar \ math \ @@ -43,8 +44,7 @@ SUBDIRS_ALWAYS = \ SUBDIRS = $(SUBDIRS_ALWAYS) \ $(compatibility_DIR) \ $(METAR_DIRS) \ - $(SG_EXTRA_DIRS) \ - $(SGTHREAD_DIR) + $(SG_EXTRA_DIRS) DIST_SUBDIRS = $(SUBDIRS_ALWAYS) compatibility scene sound screen environment threads diff --git a/simgear/io/Makefile.am b/simgear/io/Makefile.am index e0086d86..5595e0ee 100644 --- a/simgear/io/Makefile.am +++ b/simgear/io/Makefile.am @@ -41,6 +41,7 @@ tcp_server_SOURCES = tcp_server.cxx tcp_server_LDADD = \ libsgio.a \ $(top_builddir)/simgear/structure/libsgstructure.a \ + $(top_builddir)/simgear/threads/libsgthreads.a \ $(top_builddir)/simgear/debug/libsgdebug.a \ $(top_builddir)/simgear/bucket/libsgbucket.a \ $(top_builddir)/simgear/misc/libsgmisc.a \ @@ -54,6 +55,7 @@ tcp_client_SOURCES = tcp_client.cxx tcp_client_LDADD = \ libsgio.a \ $(top_builddir)/simgear/structure/libsgstructure.a \ + $(top_builddir)/simgear/threads/libsgthreads.a \ $(top_builddir)/simgear/debug/libsgdebug.a \ $(top_builddir)/simgear/bucket/libsgbucket.a \ $(top_builddir)/simgear/misc/libsgmisc.a \ @@ -67,6 +69,7 @@ socktest_SOURCES = socktest.cxx socktest_LDADD = \ libsgio.a \ $(top_builddir)/simgear/structure/libsgstructure.a \ + $(top_builddir)/simgear/threads/libsgthreads.a \ $(top_builddir)/simgear/debug/libsgdebug.a \ $(top_builddir)/simgear/bucket/libsgbucket.a \ $(top_builddir)/simgear/misc/libsgmisc.a \ @@ -80,6 +83,7 @@ lowtest_SOURCES = lowtest.cxx lowtest_LDADD = \ libsgio.a \ $(top_builddir)/simgear/structure/libsgstructure.a \ + $(top_builddir)/simgear/threads/libsgthreads.a \ $(top_builddir)/simgear/debug/libsgdebug.a \ $(top_builddir)/simgear/bucket/libsgbucket.a \ $(top_builddir)/simgear/misc/libsgmisc.a \ @@ -89,6 +93,7 @@ decode_binobj_SOURCES = decode_binobj.cxx decode_binobj_LDADD = \ libsgio.a \ + $(top_builddir)/simgear/threads/libsgthreads.a \ $(top_builddir)/simgear/debug/libsgdebug.a \ $(top_builddir)/simgear/bucket/libsgbucket.a \ $(top_builddir)/simgear/misc/libsgmisc.a \ From b5a4a5537063327f0a327d920bd48515cef44ce5 Mon Sep 17 00:00:00 2001 From: James Turner Date: Wed, 7 Sep 2011 19:58:26 +0100 Subject: [PATCH 07/11] Cmake Windows tweaks. --- CMakeLists.txt | 2 +- simgear/threads/CMakeLists.txt | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 055f915c..de222a92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -157,7 +157,7 @@ if(WIN32) # SET(WARNING_FLAGS "${WARNING_FLAGS} /wd${warning}") # endforeach(warning) - set(MSVC_FLAGS "-DWIN32 -DNOMINMAX -D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS -D__CRT_NONSTDC_NO_WARNINGS") + set(MSVC_FLAGS "-DWIN32 -DNOMINMAX -D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS -D__CRT_NONSTDC_NO_WARNINGS /wd4996") endif(MSVC) # assumed on Windows diff --git a/simgear/threads/CMakeLists.txt b/simgear/threads/CMakeLists.txt index 9eb4d540..5258be8f 100644 --- a/simgear/threads/CMakeLists.txt +++ b/simgear/threads/CMakeLists.txt @@ -5,10 +5,5 @@ set(HEADERS SGQueue.hxx SGThread.hxx) - -if (MSVC) - install (FILES ${HEADERS} DESTINATION include/simgear/threads) -else (MSVC) - set(SOURCES SGThread.cxx) - simgear_component(threads threads "${SOURCES}" "${HEADERS}") -endif(MSVC) +set(SOURCES SGThread.cxx) +simgear_component(threads threads "${SOURCES}" "${HEADERS}") From 3a210d6fa69a9bdaf29715f1cef720930183ce65 Mon Sep 17 00:00:00 2001 From: James Turner Date: Wed, 7 Sep 2011 20:12:35 +0100 Subject: [PATCH 08/11] Make sgio tests friendly to Windows. --- CMakeLists.txt | 2 ++ simgear/io/CMakeLists.txt | 3 +++ simgear/io/httpget.cxx | 6 +++--- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index de222a92..b79026c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -162,6 +162,8 @@ if(WIN32) # assumed on Windows set(HAVE_GETLOCALTIME 1) + + set( WINSOCK_LIBRARY "ws2_32.lib" ) endif(WIN32) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} ${MSVC_FLAGS}") diff --git a/simgear/io/CMakeLists.txt b/simgear/io/CMakeLists.txt index 9613e4b9..e85d9659 100644 --- a/simgear/io/CMakeLists.txt +++ b/simgear/io/CMakeLists.txt @@ -39,12 +39,14 @@ simgear_component(io io "${SOURCES}" "${HEADERS}") add_executable(test_sock socktest.cxx) target_link_libraries(test_sock sgio sgstructure sgthreads sgdebug ${CMAKE_THREAD_LIBS_INIT} + ${WINSOCK_LIBRARY} ${RT_LIBRARY}) add_executable(test_http test_HTTP.cxx) target_link_libraries(test_http sgio sgstructure sgthreads sgtiming sgmisc sgdebug ${CMAKE_THREAD_LIBS_INIT} + ${WINSOCK_LIBRARY} ${RT_LIBRARY}) add_test(http ${EXECUTABLE_OUTPUT_PATH}/test_http) @@ -53,4 +55,5 @@ add_executable(httpget httpget.cxx) target_link_libraries(httpget sgio sgstructure sgthreads sgtiming sgmisc sgdebug ${CMAKE_THREAD_LIBS_INIT} + ${WINSOCK_LIBRARY} ${RT_LIBRARY}) diff --git a/simgear/io/httpget.cxx b/simgear/io/httpget.cxx index a8e22606..b65a9274 100644 --- a/simgear/io/httpget.cxx +++ b/simgear/io/httpget.cxx @@ -1,11 +1,11 @@ #include #include +#include -#include // for STDOUT_FILENO #include #include -#include + #include #include @@ -136,7 +136,7 @@ int main(int argc, char* argv[]) signal(SIGPIPE, SIG_IGN); if (!outFile) { - outFile = new SGFile(STDOUT_FILENO); + outFile = new SGFile(fileno(stdout)); } if (url.empty()) { From b0015ab6e83348cbe26eec1d81400ff2da52a4a4 Mon Sep 17 00:00:00 2001 From: James Turner Date: Wed, 7 Sep 2011 20:41:55 +0100 Subject: [PATCH 09/11] Further Windows Cmake tweaks. --- CMakeLists.txt | 1 + simgear/io/httpget.cxx | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index b79026c7..a82b0081 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -164,6 +164,7 @@ if(WIN32) set(HAVE_GETLOCALTIME 1) set( WINSOCK_LIBRARY "ws2_32.lib" ) + set( RT_LIBRARY "winmm" ) endif(WIN32) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} ${MSVC_FLAGS}") diff --git a/simgear/io/httpget.cxx b/simgear/io/httpget.cxx index b65a9274..e10a29b4 100644 --- a/simgear/io/httpget.cxx +++ b/simgear/io/httpget.cxx @@ -133,7 +133,9 @@ int main(int argc, char* argv[]) cl.setProxy(proxyHost, proxyPort, proxyAuth); } +#ifndef WIN32 signal(SIGPIPE, SIG_IGN); +#endif if (!outFile) { outFile = new SGFile(fileno(stdout)); From 8fba4b0cbe46d4187889c1b415454611c45b493a Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Thu, 8 Sep 2011 17:41:21 +0200 Subject: [PATCH 10/11] Fix win32 SGThread::join timeout. --- simgear/threads/SGThread.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simgear/threads/SGThread.cxx b/simgear/threads/SGThread.cxx index b4afc651..8e5c3a36 100644 --- a/simgear/threads/SGThread.cxx +++ b/simgear/threads/SGThread.cxx @@ -71,7 +71,7 @@ struct SGThread::PrivateData { { if (_handle == INVALID_HANDLE_VALUE) return; - DWORD ret = WaitForSingleObject(_handle, 0); + DWORD ret = WaitForSingleObject(_handle, INFINITE); if (ret != WAIT_OBJECT_0) return; CloseHandle(_handle); From 7c7f3d4fcdb04318ea79b943c2c00aa0dca8e5ef Mon Sep 17 00:00:00 2001 From: James Turner Date: Fri, 9 Sep 2011 11:48:11 +0100 Subject: [PATCH 11/11] Hopefully fix test compilation on MSVC 2008+CMake --- simgear/props/propertyObject_test.cxx | 3 +++ simgear/props/props_test.cxx | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/simgear/props/propertyObject_test.cxx b/simgear/props/propertyObject_test.cxx index b2c458ad..5bb4ae58 100644 --- a/simgear/props/propertyObject_test.cxx +++ b/simgear/props/propertyObject_test.cxx @@ -5,6 +5,9 @@ #include #include +// working around MSVC weirdness with props.hxx and SGMathFwd +#include + #include "propertyObject.hxx" #include diff --git a/simgear/props/props_test.cxx b/simgear/props/props_test.cxx index b3109821..cd54ec50 100644 --- a/simgear/props/props_test.cxx +++ b/simgear/props/props_test.cxx @@ -6,6 +6,10 @@ #include #include + +// working around MSVC weirdness with props.hxx and SGMathFwd +#include + #include "props.hxx" #include "props_io.hxx"