.. _program_listing_file_include_fastdds_utils_TimedMutex.hpp: Program Listing for File TimedMutex.hpp ======================================= |exhale_lsh| :ref:`Return to documentation for file ` (``include/fastdds/utils/TimedMutex.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp // Copyright 2018 Proyectos y Sistemas de Mantenimiento SL (eProsima). // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef FASTDDS_UTILS__TIMEDMUTEX_HPP #define FASTDDS_UTILS__TIMEDMUTEX_HPP #include #include #if defined(_WIN32) #if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 193632528 #include #elif defined(MINGW_COMPILER) #include #else #include extern int clock_gettime( int, struct timespec* tv); #endif // if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 193632528 #elif _GTHREAD_USE_MUTEX_TIMEDLOCK #include #else #include #endif // if defined(_WIN32) namespace eprosima { namespace fastdds { #if defined(_WIN32) #if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 193632528 using TimedMutex = std::timed_mutex; using RecursiveTimedMutex = std::recursive_timed_mutex; #elif defined(MINGW_COMPILER) using TimedMutex = std::timed_mutex; using RecursiveTimedMutex = std::recursive_timed_mutex; #else class TimedMutex { public: TimedMutex() { _Mtx_init(&mutex_, _Mtx_timed); } TimedMutex( const TimedMutex&) = delete; TimedMutex& operator =( const TimedMutex&) = delete; ~TimedMutex() { _Mtx_destroy(mutex_); } void lock() { _Mtx_lock(mutex_); } void unlock() { _Mtx_unlock(mutex_); } template bool try_lock_for( const std::chrono::duration& rel_time) { return try_lock_until(std::chrono::steady_clock::now() + rel_time); } template bool try_lock_until( const std::chrono::time_point& abs_time) { std::chrono::nanoseconds nsecs = abs_time - Clock::now(); if (0 < nsecs.count()) { struct timespec max_wait = { 0, 0 }; clock_gettime(1, &max_wait); nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec); auto secs = std::chrono::duration_cast(nsecs); nsecs -= secs; max_wait.tv_sec += secs.count(); max_wait.tv_nsec = (long)nsecs.count(); return (_Thrd_success == _Mtx_timedlock(mutex_, (xtime*)&max_wait)); } else { return (_Thrd_success == _Mtx_trylock(mutex_)); } } void* native_handle() noexcept { return mutex_; } private: _Mtx_t mutex_; }; class RecursiveTimedMutex { public: RecursiveTimedMutex() { _Mtx_init(&mutex_, _Mtx_timed | _Mtx_recursive); } RecursiveTimedMutex( const TimedMutex&) = delete; RecursiveTimedMutex& operator =( const TimedMutex&) = delete; ~RecursiveTimedMutex() { _Mtx_destroy(mutex_); } void lock() { _Mtx_lock(mutex_); } void unlock() { _Mtx_unlock(mutex_); } bool try_lock() { return (_Thrd_success == _Mtx_trylock(mutex_)); } template bool try_lock_for( const std::chrono::duration& rel_time) { return try_lock_until(std::chrono::steady_clock::now() + rel_time); } template bool try_lock_until( const std::chrono::time_point& abs_time) { std::chrono::nanoseconds nsecs = abs_time - Clock::now(); if (0 < nsecs.count()) { struct timespec max_wait = { 0, 0 }; clock_gettime(1, &max_wait); nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec); auto secs = std::chrono::duration_cast(nsecs); nsecs -= secs; max_wait.tv_sec += secs.count(); max_wait.tv_nsec = (long)nsecs.count(); return (_Thrd_success == _Mtx_timedlock(mutex_, (xtime*)&max_wait)); } else { return (_Thrd_success == _Mtx_trylock(mutex_)); } } void* native_handle() noexcept { return mutex_; } private: _Mtx_t mutex_; }; #endif // if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 193632528 #elif _GTHREAD_USE_MUTEX_TIMEDLOCK || !defined(__unix__) using TimedMutex = std::timed_mutex; using RecursiveTimedMutex = std::recursive_timed_mutex; #else class TimedMutex { public: TimedMutex() { pthread_mutex_init(&mutex_, nullptr); } TimedMutex( const TimedMutex&) = delete; TimedMutex& operator =( const TimedMutex&) = delete; ~TimedMutex() { pthread_mutex_destroy(&mutex_); } void lock() { pthread_mutex_lock(&mutex_); } void unlock() { pthread_mutex_unlock(&mutex_); } template bool try_lock_for( const std::chrono::duration& rel_time) { return try_lock_until(std::chrono::steady_clock::now() + rel_time); } template bool try_lock_until( const std::chrono::time_point& abs_time) { std::chrono::nanoseconds nsecs = abs_time - Clock::now(); struct timespec max_wait = { 0, 0 }; clock_gettime(CLOCK_REALTIME, &max_wait); nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec); auto secs = std::chrono::duration_cast(nsecs); nsecs -= secs; max_wait.tv_sec += secs.count(); max_wait.tv_nsec = (long)nsecs.count(); return (0 == pthread_mutex_timedlock(&mutex_, &max_wait)); } pthread_mutex_t* native_handle() noexcept { return &mutex_; } private: pthread_mutex_t mutex_; }; class RecursiveTimedMutex { public: RecursiveTimedMutex() { pthread_mutexattr_init(&mutex_attr_); pthread_mutexattr_settype(&mutex_attr_, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&mutex_, &mutex_attr_); } RecursiveTimedMutex( const RecursiveTimedMutex&) = delete; RecursiveTimedMutex& operator =( const RecursiveTimedMutex&) = delete; ~RecursiveTimedMutex() { pthread_mutex_destroy(&mutex_); pthread_mutexattr_destroy(&mutex_attr_); } void lock() { pthread_mutex_lock(&mutex_); } void unlock() { pthread_mutex_unlock(&mutex_); } bool try_lock() { return (0 == pthread_mutex_trylock(&mutex_)); } template bool try_lock_for( const std::chrono::duration& rel_time) { return try_lock_until(std::chrono::steady_clock::now() + rel_time); } template bool try_lock_until( const std::chrono::time_point& abs_time) { std::chrono::nanoseconds nsecs = abs_time - Clock::now(); struct timespec max_wait = { 0, 0 }; clock_gettime(CLOCK_REALTIME, &max_wait); nsecs = nsecs + std::chrono::nanoseconds(max_wait.tv_nsec); auto secs = std::chrono::duration_cast(nsecs); nsecs -= secs; max_wait.tv_sec += secs.count(); max_wait.tv_nsec = (long)nsecs.count(); return (0 == pthread_mutex_timedlock(&mutex_, &max_wait)); } pthread_mutex_t* native_handle() noexcept { return &mutex_; } private: pthread_mutexattr_t mutex_attr_; pthread_mutex_t mutex_; }; #endif //_WIN32 } //namespace fastdds } //namespace eprosima #endif // FASTDDS_UTILS__TIMEDMUTEX_HPP