#ifndef INCLUDE_UTIL_PLATFORM_THREADS_BOOSTTHREADS_HPP #define INCLUDE_UTIL_PLATFORM_THREADS_BOOSTTHREADS_HPP #ifdef _MSC_VER #pragma warning( push ) #pragma warning( disable : 4275 ) // warning C4275: non dll-interface class 'std::runtime_error' used as base for dll-interface class 'boost::thread_resource_error' #pragma warning( disable : 4251 ) // warning C4251: 'boost::thread_group::m_threads' : class 'std::list<_Ty>' needs to have dll-interface to be used by clients of class 'boost::thread_group' #endif #include #include #include #include #include #include #include #if defined(RCF_USE_BOOST_READ_WRITE_MUTEX) #include #endif #ifdef _MSC_VER #pragma warning( pop ) #endif #include #include namespace Platform { namespace Threads { typedef boost::thread thread; typedef boost::thread_group thread_group; template struct thread_specific_ptr { typedef boost::thread_specific_ptr Val; }; typedef boost::mutex mutex; typedef boost::try_mutex try_mutex; typedef boost::recursive_mutex recursive_mutex; typedef boost::recursive_try_mutex recursive_try_mutex; class condition : boost::noncopyable { public: template void wait(const T &t) { mCondition.wait(t); } template bool timed_wait(const T &t, int timeoutMs) { boost::xtime xt; boost::xtime_get(&xt, boost::TIME_UTC); xt.sec += timeoutMs / 1000; xt.nsec += 1000*(timeoutMs - 1000*(timeoutMs / 1000)); return mCondition.timed_wait(t, xt); } void notify_one() { mCondition.notify_one(); } void notify_all() { mCondition.notify_all(); } private: boost::condition mCondition; }; #if defined(RCF_USE_BOOST_READ_WRITE_MUTEX) // use the read/write mutex from boost.threads // NB: v 1.32 and 1.33.0 have it, 1.33.1 doesn't (removed due to unresolved bugs...) enum read_write_scheduling_policy { writer_priority = boost::read_write_scheduling_policy::writer_priority, reader_priority = boost::read_write_scheduling_policy::reader_priority, alternating_many_reads = boost::read_write_scheduling_policy::alternating_many_reads, alternating_single_read = boost::read_write_scheduling_policy::alternating_single_read }; class read_write_mutex : public boost::read_write_mutex { public: read_write_mutex(read_write_scheduling_policy policy) : boost::read_write_mutex(boost::read_write_scheduling_policy::read_write_scheduling_policy_enum(policy)) {} }; #else // simple drop in replacement for boost::read_write_mutex, until there's a final version in boost.threads enum read_write_scheduling_policy { writer_priority , reader_priority , alternating_many_reads , alternating_single_read }; class read_write_mutex; namespace detail { class scoped_read_lock : boost::noncopyable { public: scoped_read_lock(read_write_mutex &rwm); ~scoped_read_lock(); void lock(); void unlock(); private: typedef recursive_mutex::scoped_lock scoped_lock; read_write_mutex & rwm; bool locked; }; class scoped_write_lock : boost::noncopyable { public: scoped_write_lock(read_write_mutex &rwm); ~scoped_write_lock(); void lock(); void unlock(); private: typedef recursive_mutex::scoped_lock scoped_lock; read_write_mutex & rwm; scoped_lock readLock; scoped_lock writeLock; bool locked; }; } // namespace detail class read_write_mutex : boost::noncopyable { public: read_write_mutex(read_write_scheduling_policy rwsp) : readerCount(RCF_DEFAULT_INIT) { RCF_UNUSED_VARIABLE(rwsp); } private: typedef recursive_mutex::scoped_lock scoped_lock; void waitOnReadUnlock(scoped_lock &lock) { readUnlockEvent.wait(lock); } void notifyReadUnlock() { readUnlockEvent.notify_all(); } recursive_mutex readMutex; recursive_mutex writeMutex; condition readUnlockEvent; int readerCount; public: typedef detail::scoped_read_lock scoped_read_lock; typedef detail::scoped_write_lock scoped_write_lock; friend class detail::scoped_read_lock; friend class detail::scoped_write_lock; }; namespace detail { inline scoped_read_lock::scoped_read_lock(read_write_mutex &rwm) : rwm(rwm), locked(RCF_DEFAULT_INIT) { lock(); } inline scoped_read_lock::~scoped_read_lock() { unlock(); } inline void scoped_read_lock::lock() { if (!locked) { { scoped_lock lock( rwm.readMutex ); ++rwm.readerCount; } locked = true; } } inline void scoped_read_lock::unlock() { if (locked) { { scoped_lock lock( rwm.readMutex ); --rwm.readerCount; rwm.notifyReadUnlock(); } locked = false; } } inline scoped_write_lock::scoped_write_lock(read_write_mutex &rwm) : rwm(rwm), readLock(rwm.readMutex, false), writeLock(rwm.writeMutex, false), locked(RCF_DEFAULT_INIT) { lock(); } inline scoped_write_lock::~scoped_write_lock() { unlock(); } inline void scoped_write_lock::lock() { if (!locked) { readLock.lock(); while (rwm.readerCount > 0) { rwm.waitOnReadUnlock(readLock); } writeLock.lock(); locked = true; } } inline void scoped_write_lock::unlock() { if (locked) { writeLock.unlock(); readLock.unlock(); locked = false; } } } // namespace detail #endif // RCF_USE_BOOST_READ_WRITE_MUTEX } // namespace Threads } // namespace Platform #endif // ! INCLUDE_UTIL_PLATFORM_THREADS_BOOSTTHREADS_HPP