diff --git a/config/check_depend.cmake b/config/check_depend.cmake index 3fb780ec6..f5b80c6dd 100644 --- a/config/check_depend.cmake +++ b/config/check_depend.cmake @@ -57,12 +57,23 @@ OPTION(ORO_NO_EMIT_CORBA_IOR "Do not emit CORBA IORs if name service not used" O find_package(Boost 1.38 COMPONENTS filesystem system unit_test_framework thread serialization) # Look for boost +if (NOT Boost_SYSTEM_FOUND) + message(SEND_ERROR "Orocos RTT requires Boost System library, but it was not found.") +endif() +if (NOT Boost_THREAD_FOUND) + message(SEND_ERROR "Orocos RTT requires Boost Thread library, but it was not found.") +endif() +list(APPEND OROCOS-RTT_INCLUDE_DIRS ${Boost_SYSTEM_INCLUDE_DIRS}) +list(APPEND OROCOS-RTT_LIBRARIES ${Boost_SYSTEM_LIBRARIES}) if ( PLUGINS_ENABLE ) - if (NOT Boost_FILESYSTEM_FOUND OR NOT Boost_SYSTEM_FOUND) - message(SEND_ERROR "Plugins require Boost Filesystem and System libraries, but they were not found.") + if (NOT Boost_FILESYSTEM_FOUND) + message(SEND_ERROR "Plugins require Boost Filesystem library, but it was not found.") + endif() + if (NOT Boost_SERIALIZATION_FOUND) + message(SEND_ERROR "Plugins require Boost Serialization librariy, but it was not found.") endif() - list(APPEND OROCOS-RTT_INCLUDE_DIRS ${Boost_FILESYSTEM_INCLUDE_DIRS} ${Boost_SYSTEM_INCLUDE_DIRS} ${Boost_SERIALIZATION_INCLUDE_DIRS}) - list(APPEND OROCOS-RTT_LIBRARIES ${Boost_FILESYSTEM_LIBRARIES} ${Boost_SYSTEM_LIBRARIES} ${Boost_SERIALIZATION_LIBRARIES}) + list(APPEND OROCOS-RTT_INCLUDE_DIRS ${Boost_FILESYSTEM_INCLUDE_DIRS} ${Boost_SERIALIZATION_INCLUDE_DIRS}) + list(APPEND OROCOS-RTT_LIBRARIES ${Boost_FILESYSTEM_LIBRARIES} ${Boost_SERIALIZATION_LIBRARIES}) endif() if(Boost_INCLUDE_DIR) diff --git a/rtt/os/Condition.hpp b/rtt/os/Condition.hpp index da21c8b4f..af886a29e 100644 --- a/rtt/os/Condition.hpp +++ b/rtt/os/Condition.hpp @@ -49,6 +49,10 @@ #include #endif +/// @todo Replace boost::system::system_error by std::system_error for C++11 and newer. +#include +#include + namespace RTT { namespace os { @@ -68,7 +72,13 @@ namespace RTT */ Condition() { - rtos_cond_init( &c); + int ret = rtos_cond_init( &c); + if ( ret == 0 ) + return; +#ifndef ORO_EMBEDDED + throw boost::system::system_error(-ret, boost::system::system_category(), + "Failed to initialize an instance of RTT::os::Condition"); +#endif } /** @@ -78,7 +88,10 @@ namespace RTT */ ~Condition() { - rtos_cond_destroy( &c ); + int ret = rtos_cond_destroy( &c ); + if ( ret == 0 ) + return; + assert(false && "Failed to destroy an instance of RTT::os::Condition"); } /** @@ -89,7 +102,18 @@ namespace RTT */ bool wait (Mutex& m) { - return rtos_cond_wait( &c, &m.m ) == 0 ? true : false; + int ret = rtos_cond_wait( &c, &m.m ); + if ( ret == 0 ) + return true; + if ( ret == -EBUSY || ret == -EWOULDBLOCK || ret == -ETIMEDOUT || ret == -EINTR ) + return false; +#ifndef ORO_EMBEDDED + throw boost::system::system_error(-ret, boost::system::system_category(), + "Failed to wait on an instance of RTT::os::Condition"); +#else + assert(false && "Failed to wait on an instance of RTT::os::Condition"); + return false; +#endif } /** @@ -103,8 +127,20 @@ namespace RTT template bool wait (Mutex& m, Predicate& p) { - while( !p() ) - if ( rtos_cond_wait( &c, &m.m ) != 0) return false; + while( !p() ) { + int ret = rtos_cond_wait( &c, &m.m ); + if ( ret == 0 ) + continue; + if ( ret == -EBUSY || ret == -EWOULDBLOCK || ret == -ETIMEDOUT || ret == -EINTR ) + return false; + #ifndef ORO_EMBEDDED + throw boost::system::system_error(-ret, boost::system::system_category(), + "Failed to wait on an instance of RTT::os::Condition"); + #else + assert(false && "Failed to wait on an instance of RTT::os::Condition"); + return false; + #endif + } return true; } /** @@ -112,7 +148,15 @@ namespace RTT */ void broadcast() { - rtos_cond_broadcast( &c ); + int ret = rtos_cond_broadcast( &c ); + if ( ret == 0 ) + return; +#ifndef ORO_EMBEDDED + throw boost::system::system_error(-ret, boost::system::system_category(), + "Failed to broadcast an instance of RTT::os::Condition"); +#else + assert(false && "Failed to broadcast an instance of RTT::os::Condition"); +#endif } /** @@ -128,9 +172,18 @@ namespace RTT */ bool wait_until(Mutex& m, nsecs abs_time) { - if ( rtos_cond_timedwait( &c, &m.m, abs_time ) == 0 ) + int ret = rtos_cond_timedwait( &c, &m.m, abs_time ); + if ( ret == 0 ) return true; + if ( ret == -EBUSY || ret == -EWOULDBLOCK || ret == -ETIMEDOUT || ret == -EINTR ) + return false; +#ifndef ORO_EMBEDDED + throw boost::system::system_error(-ret, boost::system::system_category(), + "Failed to wait on an instance of RTT::os::Condition"); +#else + assert(false && "Failed to wait on an instance of RTT::os::Condition"); return false; +#endif } #else protected: diff --git a/rtt/os/Mutex.hpp b/rtt/os/Mutex.hpp index 0820d481f..3fc282be1 100644 --- a/rtt/os/Mutex.hpp +++ b/rtt/os/Mutex.hpp @@ -46,6 +46,8 @@ #include "Semaphore.hpp" #include "Time.hpp" +/// @todo Replace boost::system::system_error by std::system_error for C++11 and newer. +#include #include #ifdef ORO_OS_USE_BOOST_THREAD @@ -101,7 +103,13 @@ namespace RTT */ Mutex() { - rtos_mutex_init( &m); + int ret = rtos_mutex_init( &m); + if ( ret == 0 ) + return; +#ifndef ORO_EMBEDDED + throw boost::system::system_error(-ret, boost::system::system_category(), + "Failed to initialize an instance of RTT::os::Mutex"); +#endif } /** @@ -113,18 +121,37 @@ namespace RTT { if ( trylock() ) { unlock(); - rtos_mutex_destroy( &m ); + int ret = rtos_mutex_destroy( &m ); + if ( ret == 0 ) + return; + assert(false && "Failed to destroy an instance of RTT::os::Mutex"); } } virtual void lock () { - rtos_mutex_lock( &m ); + int ret = rtos_mutex_lock( &m ); + if ( ret == 0 ) + return; +#ifndef ORO_EMBEDDED + throw boost::system::system_error(-ret, boost::system::system_category(), + "Failed to lock an instance of RTT::os::Mutex"); +#else + assert(false && "Failed to lock an instance of RTT::os::Mutex"); +#endif } virtual void unlock() { - rtos_mutex_unlock( &m ); + int ret = rtos_mutex_unlock( &m ); + if ( ret == 0 ) + return; +#ifndef ORO_EMBEDDED + throw boost::system::system_error(-ret, boost::system::system_category(), + "Failed to unlock an instance of RTT::os::Mutex"); +#else + assert(false && "Failed to unlock an instance of RTT::os::Mutex"); +#endif } /** @@ -134,9 +161,18 @@ namespace RTT */ virtual bool trylock() { - if ( rtos_mutex_trylock( &m ) == 0 ) - return true; - return false; + int ret = rtos_mutex_trylock( &m ); + if ( ret == 0 ) + return true; + if ( ret == -EBUSY || ret == -EWOULDBLOCK || ret == -ETIMEDOUT || ret == -EINTR ) + return false; +#ifndef ORO_EMBEDDED + throw boost::system::system_error(-ret, boost::system::system_category(), + "Failed to lock an instance of RTT::os::Mutex"); +#else + assert(false && "Failed to lock an instance of RTT::os::Mutex"); + return false; +#endif } /** @@ -148,9 +184,18 @@ namespace RTT */ virtual bool timedlock(Seconds s) { - if ( rtos_mutex_trylock_for( &m, Seconds_to_nsecs(s) ) == 0 ) + int ret = rtos_mutex_trylock_for( &m, Seconds_to_nsecs(s) ); + if ( ret == 0 ) return true; + if ( ret == -EBUSY || ret == -EWOULDBLOCK || ret == -ETIMEDOUT || ret == -EINTR ) + return false; +#ifndef ORO_EMBEDDED + throw boost::system::system_error(-ret, boost::system::system_category(), + "Failed to lock an instance of RTT::os::Mutex"); +#else + assert(false && "Failed to lock an instance of RTT::os::Mutex"); return false; +#endif } #else protected: @@ -226,7 +271,13 @@ namespace RTT */ MutexRecursive() { - rtos_mutex_rec_init( &recm ); + int ret = rtos_mutex_rec_init( &recm ); + if ( ret == 0 ) + return; +#ifndef ORO_EMBEDDED + throw boost::system::system_error(-ret, boost::system::system_category(), + "Failed to initialize an instance of RTT::os::MutexRecursive"); +#endif } /** @@ -238,18 +289,39 @@ namespace RTT { if ( trylock() ) { unlock(); - rtos_mutex_rec_destroy( &recm ); + // The calling thread might have locked the mutex more than once. + while(rtos_mutex_rec_unlock( &recm ) == 0); + int ret = rtos_mutex_rec_destroy( &recm ); + if ( ret == 0 ) + return; + assert(false && "Failed to destroy an instance of RTT::os::MutexRecursive"); } } void lock () { - rtos_mutex_rec_lock( &recm ); + int ret = rtos_mutex_rec_lock( &recm ); + if ( ret == 0 ) + return; +#ifndef ORO_EMBEDDED + throw boost::system::system_error(-ret, boost::system::system_category(), + "Failed to lock an instance of RTT::os::MutexRecursive"); +#else + assert(false && "Failed to lock an instance of RTT::os::MutexRecursive"); +#endif } virtual void unlock() { - rtos_mutex_rec_unlock( &recm ); + int ret = rtos_mutex_rec_unlock( &recm ); + if ( ret == 0 ) + return; +#ifndef ORO_EMBEDDED + throw boost::system::system_error(-ret, boost::system::system_category(), + "Failed to unlock an instance of RTT::os::MutexRecursive"); +#else + assert(false && "Failed to unlock an instance of RTT::os::MutexRecursive"); +#endif } /** @@ -259,9 +331,18 @@ namespace RTT */ virtual bool trylock() { - if ( rtos_mutex_rec_trylock( &recm ) == 0 ) + int ret = rtos_mutex_rec_trylock( &recm ); + if ( ret == 0 ) return true; + if ( ret == -EBUSY || ret == -EWOULDBLOCK || ret == -ETIMEDOUT || ret == -EINTR ) + return false; +#ifndef ORO_EMBEDDED + throw boost::system::system_error(-ret, boost::system::system_category(), + "Failed to lock an instance of RTT::os::MutexRecursive"); +#else + assert(false && "Failed to lock an instance of RTT::os::MutexRecursive"); return false; +#endif } /** @@ -273,9 +354,18 @@ namespace RTT */ virtual bool timedlock(Seconds s) { - if ( rtos_mutex_rec_trylock_for( &recm, Seconds_to_nsecs(s) ) == 0 ) + int ret = rtos_mutex_rec_trylock_for( &recm, Seconds_to_nsecs(s) ); + if ( ret == 0 ) return true; + if ( ret == -EBUSY || ret == -EWOULDBLOCK || ret == -ETIMEDOUT || ret == -EINTR ) + return false; +#ifndef ORO_EMBEDDED + throw boost::system::system_error(-ret, boost::system::system_category(), + "Failed to lock an instance of RTT::os::MutexRecursive"); +#else + assert(false && "Failed to lock an instance of RTT::os::MutexRecursive"); return false; +#endif } #else protected: diff --git a/rtt/os/gnulinux/fosi.h b/rtt/os/gnulinux/fosi.h index 5f2d3b1e2..2d97e80c3 100644 --- a/rtt/os/gnulinux/fosi.h +++ b/rtt/os/gnulinux/fosi.h @@ -119,16 +119,28 @@ extern "C" static inline NANO_TIME rtos_get_time_ns( void ) { TIME_SPEC tv; - clock_gettime(CLOCK_MONOTONIC, &tv); + if ( clock_gettime(CLOCK_MONOTONIC, &tv) != 0) + return 0; + // we can not include the C++ Time.hpp header ! +#ifdef __cplusplus + return NANO_TIME( tv.tv_sec ) * 1000000000LL + NANO_TIME( tv.tv_nsec ); +#else return ( NANO_TIME ) ( tv.tv_sec * 1000000000LL ) + ( NANO_TIME ) ( tv.tv_nsec ); +#endif } // internal use only, for rtos_mutex_trylock_for/rtos_mutex_rec_trylock_for! static inline NANO_TIME rtos_get_realtime_ns( void ) { TIME_SPEC tv; - clock_gettime(CLOCK_REALTIME, &tv); + if ( clock_gettime(CLOCK_REALTIME, &tv) != 0) + return 0; + // we can not include the C++ Time.hpp header ! +#ifdef __cplusplus + return NANO_TIME( tv.tv_sec ) * 1000000000LL + NANO_TIME( tv.tv_nsec ); +#else return ( NANO_TIME ) ( tv.tv_sec * 1000000000LL ) + ( NANO_TIME ) ( tv.tv_nsec ); +#endif } /** @@ -143,7 +155,10 @@ extern "C" static inline int rtos_nanosleep( const TIME_SPEC * rqtp, TIME_SPEC * rmtp ) { // return usleep(rqtp->tv_nsec/1000L); - return nanosleep( rqtp, rmtp ); + if ( nanosleep( rqtp, rmtp ) == 0 ) + return 0; + else + return -errno; } /** @@ -172,22 +187,34 @@ extern "C" static inline int rtos_sem_destroy(rt_sem_t* m ) { - return sem_destroy(m); + if ( sem_destroy(m) == 0 ) + return 0; + else + return -errno; } static inline int rtos_sem_signal(rt_sem_t* m ) { - return sem_post(m); + if ( sem_post(m) == 0 ) + return 0; + else + return -errno; } static inline int rtos_sem_wait(rt_sem_t* m ) { - return sem_wait(m); + if ( sem_wait(m) == 0 ) + return 0; + else + return -errno; } static inline int rtos_sem_trywait(rt_sem_t* m ) { - return sem_trywait(m); + if ( sem_trywait(m) == 0 ) + return 0; + else + return -errno; } static inline int rtos_sem_value(rt_sem_t* m ) @@ -195,7 +222,8 @@ extern "C" int val = 0; if ( sem_getvalue(m, &val) == 0) return val; - return -1; + else + return -errno; } // Mutex functions @@ -205,43 +233,43 @@ extern "C" static inline int rtos_mutex_init(rt_mutex_t* m) { - return pthread_mutex_init(m, 0 ); + return -pthread_mutex_init(m, 0 ); } static inline int rtos_mutex_destroy(rt_mutex_t* m ) { - return pthread_mutex_destroy(m); + return -pthread_mutex_destroy(m); } static inline int rtos_mutex_rec_init(rt_rec_mutex_t* m) { pthread_mutexattr_t attr; int ret = pthread_mutexattr_init(&attr); - if (ret != 0) return ret; + if (ret != 0) return -ret; // make mutex recursive ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP); - if (ret != 0) return ret; + if (ret != 0) return -ret; ret = pthread_mutex_init(m, &attr); pthread_mutexattr_destroy(&attr); - return ret; + return -ret; } static inline int rtos_mutex_rec_destroy(rt_rec_mutex_t* m ) { - return pthread_mutex_destroy(m); + return -pthread_mutex_destroy(m); } static inline int rtos_mutex_lock( rt_mutex_t* m) { - return pthread_mutex_lock(m); + return -pthread_mutex_lock(m); } static inline int rtos_mutex_rec_lock( rt_rec_mutex_t* m) { - return pthread_mutex_lock(m); + return -pthread_mutex_lock(m); } static inline int rtos_mutex_trylock_for( rt_mutex_t* m, NANO_TIME relative_time) @@ -251,7 +279,7 @@ extern "C" // by rtos_get_realtime_ns() using CLOCK_REALTIME (may be affected by time // adjustments while waiting) TIME_SPEC arg_time = ticks2timespec( rtos_get_realtime_ns() + relative_time ); - return pthread_mutex_timedlock(m, &arg_time); + return -pthread_mutex_timedlock(m, &arg_time); } static inline int rtos_mutex_rec_trylock_for( rt_rec_mutex_t* m, NANO_TIME relative_time) @@ -261,7 +289,7 @@ extern "C" // by rtos_get_realtime_ns() using CLOCK_REALTIME (may be affected by time // adjustments while waiting) TIME_SPEC arg_time = ticks2timespec( rtos_get_realtime_ns() + relative_time ); - return pthread_mutex_timedlock(m, &arg_time); + return -pthread_mutex_timedlock(m, &arg_time); } static inline int rtos_mutex_lock_until( rt_mutex_t* m, NANO_TIME abs_time) @@ -286,22 +314,22 @@ extern "C" static inline int rtos_mutex_trylock( rt_mutex_t* m) { - return pthread_mutex_trylock(m); + return -pthread_mutex_trylock(m); } static inline int rtos_mutex_rec_trylock( rt_rec_mutex_t* m) { - return pthread_mutex_trylock(m); + return -pthread_mutex_trylock(m); } static inline int rtos_mutex_unlock( rt_mutex_t* m) { - return pthread_mutex_unlock(m); + return -pthread_mutex_unlock(m); } static inline int rtos_mutex_rec_unlock( rt_rec_mutex_t* m) { - return pthread_mutex_unlock(m); + return -pthread_mutex_unlock(m); } static inline void rtos_enable_rt_warning() @@ -318,40 +346,40 @@ extern "C" { pthread_condattr_t attr; int ret = pthread_condattr_init(&attr); - if (ret != 0) return ret; + if (ret != 0) return -ret; // set the clock selection condition variable attribute to CLOCK_MONOTONIC ret = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); if (ret != 0) { pthread_condattr_destroy(&attr); - return ret; + return -ret; } ret = pthread_cond_init(cond, &attr); pthread_condattr_destroy(&attr); - return ret; + return -ret; } static inline int rtos_cond_destroy(rt_cond_t *cond) { - return pthread_cond_destroy(cond); + return -pthread_cond_destroy(cond); } static inline int rtos_cond_wait(rt_cond_t *cond, rt_mutex_t *mutex) { - return pthread_cond_wait(cond, mutex); + return -pthread_cond_wait(cond, mutex); } static inline int rtos_cond_timedwait(rt_cond_t *cond, rt_mutex_t *mutex, NANO_TIME abs_time) { TIME_SPEC arg_time = ticks2timespec( abs_time ); - return pthread_cond_timedwait(cond, mutex, &arg_time); + return -pthread_cond_timedwait(cond, mutex, &arg_time); } static inline int rtos_cond_broadcast(rt_cond_t *cond) { - return pthread_cond_broadcast(cond); + return -pthread_cond_broadcast(cond); } #define rtos_printf printf diff --git a/rtt/os/macosx/fosi.h b/rtt/os/macosx/fosi.h index 4592986fb..57380b14e 100644 --- a/rtt/os/macosx/fosi.h +++ b/rtt/os/macosx/fosi.h @@ -147,7 +147,10 @@ extern "C" static inline int rtos_nanosleep( const TIME_SPEC * rqtp, TIME_SPEC * rmtp ) { // return usleep(rqtp->tv_nsec/1000L); - return nanosleep( rqtp, rmtp ); + if ( nanosleep( rqtp, rmtp ) == 0 ) + return 0; + else + return -errno; } static inline long long nano2ticks( long long nano ) @@ -170,22 +173,22 @@ extern "C" static inline int rtos_sem_init(rt_sem_t* m, int value ) { - return semaphore_create(mach_task_self(), m, SYNC_POLICY_FIFO, value); + return -semaphore_create(mach_task_self(), m, SYNC_POLICY_FIFO, value); } static inline int rtos_sem_destroy(rt_sem_t* m ) { - return semaphore_destroy(mach_task_self(), *m); + return -semaphore_destroy(mach_task_self(), *m); } static inline int rtos_sem_signal(rt_sem_t* m ) { - return semaphore_signal(*m); + return -semaphore_signal(*m); } static inline int rtos_sem_wait(rt_sem_t* m ) { - return semaphore_wait(*m); + return -semaphore_wait(*m); } static inline int rtos_sem_wait_timed(rt_sem_t* m, NANO_TIME delay ) @@ -201,7 +204,7 @@ extern "C" #endif }; - return semaphore_timedwait( *m, mach_delayvl); + return -semaphore_timedwait( *m, mach_delayvl); } static inline int rtos_sem_trywait(rt_sem_t* m ) @@ -243,9 +246,7 @@ extern "C" delayvl.tv_nsec #endif }; - int rc = semaphore_timedwait( *m, mach_delayvl); - // map to return values from gnulinux, and expected by the calling layer - return (KERN_OPERATION_TIMED_OUT == rc ? -1 : 0); + return -semaphore_timedwait( *m, mach_delayvl); } // semaphore_value is not supported on darwin diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 24ac8f2d7..6b74b8040 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -94,7 +94,7 @@ IF (BUILD_TESTING) endif() # repeat for each test - ADD_EXECUTABLE( core-test test-runner.cpp logger_test.cpp time_test.cpp ptr_test.cpp ) + ADD_EXECUTABLE( core-test test-runner.cpp logger_test.cpp time_test.cpp ptr_test.cpp os_test.cpp ) TARGET_LINK_LIBRARIES( core-test orocos-rtt-${OROCOS_TARGET}_dynamic ${TEST_LIBRARIES}) SET_TARGET_PROPERTIES( core-test PROPERTIES COMPILE_DEFINITIONS "${COMPILE_DEFS}") diff --git a/tests/os_test.cpp b/tests/os_test.cpp new file mode 100644 index 000000000..ab1633291 --- /dev/null +++ b/tests/os_test.cpp @@ -0,0 +1,128 @@ +/*************************************************************************** + tag: Peter Soetens Mon Jan 10 15:59:51 CET 2005 buffers_test.cpp + + buffers_test.cpp - description + ------------------- + begin : Mon January 10 2005 + copyright : (C) 2005 Peter Soetens + email : peter.soetens@mech.kuleuven.ac.be + + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + + +#include "unit.hpp" + +#include + +#include +#include +#include + +using namespace RTT; +using namespace RTT::os; + +BOOST_AUTO_TEST_SUITE(OsTestSuite) + +BOOST_AUTO_TEST_CASE( testMutex ) +{ + Mutex m; + + m.lock(); + m.unlock(); + { + MutexLock lock(m); + } + + BOOST_CHECK(m.trylock()); + m.unlock(); + { + MutexTryLock lock(m); + BOOST_CHECK(lock.isSuccessful()); + MutexTryLock lock2(m); +#if !defined(OROCOS_TARGET_XENOMAI) + BOOST_CHECK(!lock2.isSuccessful()); +#else + // a Xenomai mutex is always recursive + BOOST_CHECK(lock2.isSuccessful()); +#endif + } + + BOOST_CHECK(m.timedlock(Seconds(1.))); + m.unlock(); + { + MutexTimedLock lock(m, Seconds(1.)); + BOOST_CHECK(lock.isSuccessful()); + MutexTimedLock lock2(m, Seconds(1.)); +#if !defined(OROCOS_TARGET_XENOMAI) + BOOST_CHECK(!lock2.isSuccessful()); +#else + // a Xenomai mutex is always recursive + BOOST_CHECK(lock2.isSuccessful()); +#endif + } + + BOOST_CHECK(m.timedlock(Seconds(1.))); +#if !defined(OROCOS_TARGET_XENOMAI) + BOOST_CHECK(!m.trylock()); + BOOST_CHECK(!m.timedlock(Seconds(1.))); +#else + // a Xenomai mutex is always recursive +#endif + m.unlock(); + + // Test locked mutex during destruction + m.lock(); +} + +BOOST_AUTO_TEST_CASE( testMutexRecursive ) +{ + MutexRecursive m; + + m.lock(); + m.lock(); + m.unlock(); + m.unlock(); + { + MutexLock lock(m); + MutexLock lock2(m); + } + + BOOST_CHECK(m.trylock()); + BOOST_CHECK(m.trylock()); + m.unlock(); + m.unlock(); + { + MutexTryLock lock(m); + BOOST_CHECK(lock.isSuccessful()); + MutexTryLock lock2(m); + BOOST_CHECK(lock2.isSuccessful()); + } + + BOOST_CHECK(m.timedlock(Seconds(1.))); + BOOST_CHECK(m.timedlock(Seconds(1.))); + m.unlock(); + m.unlock(); + { + MutexTimedLock lock(m, Seconds(1.)); + BOOST_CHECK(lock.isSuccessful()); + MutexTimedLock lock2(m, Seconds(1.)); + BOOST_CHECK(lock2.isSuccessful()); + } + + BOOST_CHECK(m.timedlock(Seconds(1.))); + BOOST_CHECK(m.trylock()); + m.unlock(); + m.unlock(); + + // Test locked mutex during destruction + m.lock(); +} + +BOOST_AUTO_TEST_SUITE_END()