Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:32:46

0001 // (C) Copyright 2012 Vicente J. Botet Escriba
0002 // Distributed under the Boost Software License, Version 1.0. (See
0003 // accompanying file LICENSE_1_0.txt or copy at
0004 // http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 
0007 #ifndef BOOST_THREAD_TESTABLE_LOCKABLE_HPP
0008 #define BOOST_THREAD_TESTABLE_LOCKABLE_HPP
0009 
0010 #include <boost/thread/detail/config.hpp>
0011 
0012 #include <boost/thread/thread_only.hpp>
0013 
0014 #include <boost/atomic.hpp>
0015 #include <boost/assert.hpp>
0016 
0017 #include <boost/config/abi_prefix.hpp>
0018 
0019 namespace boost
0020 {
0021   /**
0022    * Based on Associate Mutexes with Data to Prevent Races, By Herb Sutter, May 13, 2010
0023    * http://www.drdobbs.com/windows/associate-mutexes-with-data-to-prevent-r/224701827?pgno=3
0024    *
0025    * Make our mutex testable if it isn't already.
0026    *
0027    * Many mutex services (including boost::mutex) don't provide a way to ask,
0028    * "Do I already hold a lock on this mutex?"
0029    * Sometimes it is needed to know if a method like is_locked to be available.
0030    * This wrapper associates an arbitrary lockable type with a thread id that stores the ID of the thread that
0031    * currently holds the lockable. The thread id initially holds an invalid value that means no threads own the mutex.
0032    * When we acquire a lock, we set the thread id; and when we release a lock, we reset it back to its default no id state.
0033    *
0034    */
0035   template <typename Lockable>
0036   class testable_mutex
0037   {
0038     Lockable mtx_;
0039     atomic<thread::id> id_;
0040   public:
0041     /// the type of the wrapped lockable
0042     typedef Lockable lockable_type;
0043 
0044     /// Non copyable
0045     BOOST_THREAD_NO_COPYABLE(testable_mutex)
0046 
0047     testable_mutex() : id_(thread::id()) {}
0048 
0049     void lock()
0050     {
0051       BOOST_ASSERT(! is_locked_by_this_thread());
0052       mtx_.lock();
0053       id_ = this_thread::get_id();
0054     }
0055 
0056     void unlock()
0057     {
0058       BOOST_ASSERT(is_locked_by_this_thread());
0059       id_ = thread::id();
0060       mtx_.unlock();
0061     }
0062 
0063     bool try_lock()
0064     {
0065       BOOST_ASSERT(! is_locked_by_this_thread());
0066       if (mtx_.try_lock())
0067       {
0068         id_ = this_thread::get_id();
0069         return true;
0070       }
0071       else
0072       {
0073         return false;
0074       }
0075     }
0076 #ifdef BOOST_THREAD_USES_CHRONO
0077     template <class Rep, class Period>
0078     bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
0079     {
0080       BOOST_ASSERT(! is_locked_by_this_thread());
0081       if (mtx_.try_lock_for(rel_time))
0082       {
0083         id_ = this_thread::get_id();
0084         return true;
0085       }
0086       else
0087       {
0088         return false;
0089       }
0090     }
0091     template <class Clock, class Duration>
0092     bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
0093     {
0094       BOOST_ASSERT(! is_locked_by_this_thread());
0095       if (mtx_.try_lock_until(abs_time))
0096       {
0097         id_ = this_thread::get_id();
0098         return true;
0099       }
0100       else
0101       {
0102         return false;
0103       }
0104     }
0105 #endif
0106 
0107     bool is_locked_by_this_thread() const
0108     {
0109       return this_thread::get_id() == id_;
0110     }
0111     bool is_locked() const
0112     {
0113       return ! (thread::id() == id_);
0114     }
0115 
0116     thread::id get_id() const
0117     {
0118       return id_;
0119     }
0120 
0121     // todo add the shared and upgrade mutex functions
0122   };
0123 
0124   template <typename Lockable>
0125   struct is_testable_lockable : false_type
0126   {};
0127 
0128   template <typename Lockable>
0129   struct is_testable_lockable<testable_mutex<Lockable> > : true_type
0130   {};
0131 
0132 //  /**
0133 //   * Overloaded function used to check if the mutex is locked when it is testable and do nothing otherwise.
0134 //   *
0135 //   * This function is used usually to assert the pre-condition when the function can only be called when the mutex
0136 //   * must be locked by the current thread.
0137 //   */
0138 //  template <typename Lockable>
0139 //  bool is_locked_by_this_thread(testable_mutex<Lockable> const& mtx)
0140 //  {
0141 //    return mtx.is_locked();
0142 //  }
0143 //  template <typename Lockable>
0144 //  bool is_locked_by_this_thread(Lockable const&)
0145 //  {
0146 //    return true;
0147 //  }
0148 }
0149 
0150 #include <boost/config/abi_suffix.hpp>
0151 
0152 #endif // header