Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-22 10:29:21

0001 #ifndef BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
0002 #define BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
0003 
0004 //  (C) Copyright 2006-8 Anthony Williams
0005 //  (C) Copyright 2012 Vicente J. Botet Escriba
0006 //
0007 //  Distributed under the Boost Software License, Version 1.0. (See
0008 //  accompanying file LICENSE_1_0.txt or copy at
0009 //  http://www.boost.org/LICENSE_1_0.txt)
0010 
0011 #include <boost/assert.hpp>
0012 #include <boost/bind/bind.hpp>
0013 #include <boost/static_assert.hpp>
0014 #include <boost/thread/mutex.hpp>
0015 #include <boost/thread/condition_variable.hpp>
0016 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0017 #include <boost/thread/detail/thread_interruption.hpp>
0018 #endif
0019 #ifdef BOOST_THREAD_USES_CHRONO
0020 #include <boost/chrono/system_clocks.hpp>
0021 #include <boost/chrono/ceil.hpp>
0022 #endif
0023 #include <boost/thread/detail/delete.hpp>
0024 
0025 #include <boost/config/abi_prefix.hpp>
0026 
0027 namespace boost
0028 {
0029     class shared_mutex
0030     {
0031     private:
0032         class state_data
0033         {
0034         public:
0035             state_data () :
0036               shared_count(0),
0037               exclusive(false),
0038               upgrade(false),
0039               exclusive_waiting_blocked(false)
0040             {}
0041 
0042             void assert_free() const
0043             {
0044                 BOOST_ASSERT( ! exclusive );
0045                 BOOST_ASSERT( ! upgrade );
0046                 BOOST_ASSERT( shared_count==0 );
0047             }
0048 
0049             void assert_locked() const
0050             {
0051                 BOOST_ASSERT( exclusive );
0052                 BOOST_ASSERT( shared_count==0 );
0053                 BOOST_ASSERT( ! upgrade );
0054             }
0055 
0056             void assert_lock_shared () const
0057             {
0058                 BOOST_ASSERT( ! exclusive );
0059                 BOOST_ASSERT( shared_count>0 );
0060                 //BOOST_ASSERT( (! upgrade) || (shared_count>1));
0061                 // if upgraded there are at least 2 threads sharing the mutex,
0062                 // except when unlock_upgrade_and_lock has decreased the number of readers but has not taken yet exclusive ownership.
0063             }
0064 
0065             void assert_lock_upgraded () const
0066             {
0067                 BOOST_ASSERT( ! exclusive );
0068                 BOOST_ASSERT(  upgrade );
0069                 BOOST_ASSERT(  shared_count>0 );
0070             }
0071 
0072             void assert_lock_not_upgraded () const
0073             {
0074                 BOOST_ASSERT(  ! upgrade );
0075             }
0076 
0077             bool can_lock () const
0078             {
0079                 return ! (shared_count || exclusive);
0080             }
0081 
0082             void lock ()
0083             {
0084                 exclusive = true;
0085             }
0086 
0087             void unlock ()
0088             {
0089                 exclusive = false;
0090                 exclusive_waiting_blocked = false;
0091             }
0092 
0093             bool can_lock_shared () const
0094             {
0095                 return ! (exclusive || exclusive_waiting_blocked);
0096             }
0097 
0098             bool no_shared () const
0099             {
0100                 return shared_count==0;
0101             }
0102 
0103             bool one_shared () const
0104             {
0105                 return shared_count==1;
0106             }
0107 
0108             void lock_shared ()
0109             {
0110                 ++shared_count;
0111             }
0112 
0113 
0114             void unlock_shared ()
0115             {
0116                 --shared_count;
0117             }
0118 
0119             void lock_upgrade ()
0120             {
0121                 ++shared_count;
0122                 upgrade=true;
0123             }
0124             bool can_lock_upgrade () const
0125             {
0126                 return ! (exclusive || exclusive_waiting_blocked || upgrade);
0127             }
0128 
0129             void unlock_upgrade ()
0130             {
0131                 upgrade=false;
0132                 --shared_count;
0133             }
0134 
0135         //private:
0136             unsigned shared_count;
0137             bool exclusive;
0138             bool upgrade;
0139             bool exclusive_waiting_blocked;
0140         };
0141 
0142 
0143 
0144         state_data state;
0145         boost::mutex state_change;
0146         boost::condition_variable shared_cond;
0147         boost::condition_variable exclusive_cond;
0148         boost::condition_variable upgrade_cond;
0149 
0150         void release_waiters()
0151         {
0152             exclusive_cond.notify_one();
0153             shared_cond.notify_all();
0154         }
0155 
0156     public:
0157 
0158         BOOST_THREAD_NO_COPYABLE(shared_mutex)
0159 
0160         shared_mutex()
0161         {
0162         }
0163 
0164         ~shared_mutex()
0165         {
0166         }
0167 
0168         void lock_shared()
0169         {
0170 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0171             boost::this_thread::disable_interruption do_not_disturb;
0172 #endif
0173             boost::unique_lock<boost::mutex> lk(state_change);
0174             shared_cond.wait(lk, boost::bind(&state_data::can_lock_shared, boost::ref(state)));
0175             state.lock_shared();
0176         }
0177 
0178         bool try_lock_shared()
0179         {
0180             boost::unique_lock<boost::mutex> lk(state_change);
0181 
0182             if(!state.can_lock_shared())
0183             {
0184                 return false;
0185             }
0186             state.lock_shared();
0187             return true;
0188         }
0189 
0190 #if defined BOOST_THREAD_USES_DATETIME
0191         bool timed_lock_shared(system_time const& timeout)
0192         {
0193 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0194             boost::this_thread::disable_interruption do_not_disturb;
0195 #endif
0196             boost::unique_lock<boost::mutex> lk(state_change);
0197             if(!shared_cond.timed_wait(lk, timeout, boost::bind(&state_data::can_lock_shared, boost::ref(state))))
0198             {
0199                 return false;
0200             }
0201             state.lock_shared();
0202             return true;
0203         }
0204 
0205         template<typename TimeDuration>
0206         bool timed_lock_shared(TimeDuration const & relative_time)
0207         {
0208 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0209             boost::this_thread::disable_interruption do_not_disturb;
0210 #endif
0211             boost::unique_lock<boost::mutex> lk(state_change);
0212             if(!shared_cond.timed_wait(lk, relative_time, boost::bind(&state_data::can_lock_shared, boost::ref(state))))
0213             {
0214                 return false;
0215             }
0216             state.lock_shared();
0217             return true;
0218         }
0219 #endif
0220 #ifdef BOOST_THREAD_USES_CHRONO
0221         template <class Rep, class Period>
0222         bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
0223         {
0224           return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
0225         }
0226         template <class Clock, class Duration>
0227         bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time)
0228         {
0229 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0230           boost::this_thread::disable_interruption do_not_disturb;
0231 #endif
0232           boost::unique_lock<boost::mutex> lk(state_change);
0233           if(!shared_cond.wait_until(lk, abs_time, boost::bind(&state_data::can_lock_shared, boost::ref(state))))
0234           {
0235               return false;
0236           }
0237           state.lock_shared();
0238           return true;
0239         }
0240 #endif
0241         void unlock_shared()
0242         {
0243             boost::unique_lock<boost::mutex> lk(state_change);
0244             state.assert_lock_shared();
0245             state.unlock_shared();
0246             if (state.no_shared())
0247             {
0248                 if (state.upgrade)
0249                 {
0250                     // As there is a thread doing a unlock_upgrade_and_lock that is waiting for state.no_shared()
0251                     // avoid other threads to lock, lock_upgrade or lock_shared, so only this thread is notified.
0252                     state.upgrade=false;
0253                     state.exclusive=true;
0254                     //lk.unlock();
0255                     upgrade_cond.notify_one();
0256                 }
0257                 else
0258                 {
0259                     state.exclusive_waiting_blocked=false;
0260                     //lk.unlock();
0261                 }
0262                 release_waiters();
0263             }
0264         }
0265 
0266         void lock()
0267         {
0268 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0269             boost::this_thread::disable_interruption do_not_disturb;
0270 #endif
0271             boost::unique_lock<boost::mutex> lk(state_change);
0272             state.exclusive_waiting_blocked=true;
0273             exclusive_cond.wait(lk, boost::bind(&state_data::can_lock, boost::ref(state)));
0274             state.exclusive=true;
0275         }
0276 
0277 #if defined BOOST_THREAD_USES_DATETIME
0278         bool timed_lock(system_time const& timeout)
0279         {
0280 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0281             boost::this_thread::disable_interruption do_not_disturb;
0282 #endif
0283             boost::unique_lock<boost::mutex> lk(state_change);
0284             state.exclusive_waiting_blocked=true;
0285             if(!exclusive_cond.timed_wait(lk, timeout, boost::bind(&state_data::can_lock, boost::ref(state))))
0286             {
0287                 state.exclusive_waiting_blocked=false;
0288                 release_waiters();
0289                 return false;
0290             }
0291             state.exclusive=true;
0292             return true;
0293         }
0294 
0295         template<typename TimeDuration>
0296         bool timed_lock(TimeDuration const & relative_time)
0297         {
0298 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0299             boost::this_thread::disable_interruption do_not_disturb;
0300 #endif
0301             boost::unique_lock<boost::mutex> lk(state_change);
0302             state.exclusive_waiting_blocked=true;
0303             if(!exclusive_cond.timed_wait(lk, relative_time, boost::bind(&state_data::can_lock, boost::ref(state))))
0304             {
0305                 state.exclusive_waiting_blocked=false;
0306                 release_waiters();
0307                 return false;
0308             }
0309             state.exclusive=true;
0310             return true;
0311         }
0312 #endif
0313 #ifdef BOOST_THREAD_USES_CHRONO
0314         template <class Rep, class Period>
0315         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
0316         {
0317           return try_lock_until(chrono::steady_clock::now() + rel_time);
0318         }
0319         template <class Clock, class Duration>
0320         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
0321         {
0322 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0323           boost::this_thread::disable_interruption do_not_disturb;
0324 #endif
0325           boost::unique_lock<boost::mutex> lk(state_change);
0326           state.exclusive_waiting_blocked=true;
0327           if(!exclusive_cond.wait_until(lk, abs_time, boost::bind(&state_data::can_lock, boost::ref(state))))
0328           {
0329               state.exclusive_waiting_blocked=false;
0330               release_waiters();
0331               return false;
0332           }
0333           state.exclusive=true;
0334           return true;
0335         }
0336 #endif
0337 
0338         bool try_lock()
0339         {
0340             boost::unique_lock<boost::mutex> lk(state_change);
0341             if(!state.can_lock())
0342             {
0343                 return false;
0344             }
0345             state.exclusive=true;
0346             return true;
0347         }
0348 
0349         void unlock()
0350         {
0351             boost::unique_lock<boost::mutex> lk(state_change);
0352             state.assert_locked();
0353             state.exclusive=false;
0354             state.exclusive_waiting_blocked=false;
0355             state.assert_free();
0356             release_waiters();
0357         }
0358 
0359         void lock_upgrade()
0360         {
0361 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0362             boost::this_thread::disable_interruption do_not_disturb;
0363 #endif
0364             boost::unique_lock<boost::mutex> lk(state_change);
0365             shared_cond.wait(lk, boost::bind(&state_data::can_lock_upgrade, boost::ref(state)));
0366             state.lock_shared();
0367             state.upgrade=true;
0368         }
0369 
0370 #if defined BOOST_THREAD_USES_DATETIME
0371         bool timed_lock_upgrade(system_time const& timeout)
0372         {
0373 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0374             boost::this_thread::disable_interruption do_not_disturb;
0375 #endif
0376             boost::unique_lock<boost::mutex> lk(state_change);
0377             if(!shared_cond.timed_wait(lk, timeout, boost::bind(&state_data::can_lock_upgrade, boost::ref(state))))
0378             {
0379                 return false;
0380             }
0381             state.lock_shared();
0382             state.upgrade=true;
0383             return true;
0384         }
0385 
0386         template<typename TimeDuration>
0387         bool timed_lock_upgrade(TimeDuration const & relative_time)
0388         {
0389 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0390             boost::this_thread::disable_interruption do_not_disturb;
0391 #endif
0392             boost::unique_lock<boost::mutex> lk(state_change);
0393             if(!shared_cond.timed_wait(lk, relative_time, boost::bind(&state_data::can_lock_upgrade, boost::ref(state))))
0394             {
0395                 return false;
0396             }
0397             state.lock_shared();
0398             state.upgrade=true;
0399             return true;
0400         }
0401 #endif
0402 #ifdef BOOST_THREAD_USES_CHRONO
0403         template <class Rep, class Period>
0404         bool try_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time)
0405         {
0406           return try_lock_upgrade_until(chrono::steady_clock::now() + rel_time);
0407         }
0408         template <class Clock, class Duration>
0409         bool try_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time)
0410         {
0411 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0412           boost::this_thread::disable_interruption do_not_disturb;
0413 #endif
0414           boost::unique_lock<boost::mutex> lk(state_change);
0415           if(!shared_cond.wait_until(lk, abs_time, boost::bind(&state_data::can_lock_upgrade, boost::ref(state))))
0416           {
0417               return false;
0418           }
0419           state.lock_shared();
0420           state.upgrade=true;
0421           return true;
0422         }
0423 #endif
0424         bool try_lock_upgrade()
0425         {
0426             boost::unique_lock<boost::mutex> lk(state_change);
0427             if(!state.can_lock_upgrade())
0428             {
0429                 return false;
0430             }
0431             state.lock_shared();
0432             state.upgrade=true;
0433             state.assert_lock_upgraded();
0434             return true;
0435         }
0436 
0437         void unlock_upgrade()
0438         {
0439             boost::unique_lock<boost::mutex> lk(state_change);
0440             //state.upgrade=false;
0441             state.unlock_upgrade();
0442             if(state.no_shared())
0443             {
0444                 state.exclusive_waiting_blocked=false;
0445                 release_waiters();
0446             } else {
0447                 shared_cond.notify_all();
0448             }
0449         }
0450 
0451         // Upgrade <-> Exclusive
0452         void unlock_upgrade_and_lock()
0453         {
0454 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0455             boost::this_thread::disable_interruption do_not_disturb;
0456 #endif
0457             boost::unique_lock<boost::mutex> lk(state_change);
0458             state.assert_lock_upgraded();
0459             state.unlock_shared();
0460             upgrade_cond.wait(lk, boost::bind(&state_data::no_shared, boost::ref(state)));
0461             state.upgrade=false;
0462             state.exclusive=true;
0463             state.assert_locked();
0464         }
0465 
0466         void unlock_and_lock_upgrade()
0467         {
0468             boost::unique_lock<boost::mutex> lk(state_change);
0469             state.assert_locked();
0470             state.exclusive=false;
0471             state.upgrade=true;
0472             state.lock_shared();
0473             state.exclusive_waiting_blocked=false;
0474             state.assert_lock_upgraded();
0475             release_waiters();
0476         }
0477 
0478         bool try_unlock_upgrade_and_lock()
0479         {
0480           boost::unique_lock<boost::mutex> lk(state_change);
0481           state.assert_lock_upgraded();
0482           if(    !state.exclusive
0483               && !state.exclusive_waiting_blocked
0484               && state.upgrade
0485               && state.shared_count==1)
0486           {
0487             state.shared_count=0;
0488             state.exclusive=true;
0489             state.upgrade=false;
0490             state.assert_locked();
0491             return true;
0492           }
0493           return false;
0494         }
0495 #ifdef BOOST_THREAD_USES_CHRONO
0496         template <class Rep, class Period>
0497         bool
0498         try_unlock_upgrade_and_lock_for(
0499                                 const chrono::duration<Rep, Period>& rel_time)
0500         {
0501           return try_unlock_upgrade_and_lock_until(
0502                                  chrono::steady_clock::now() + rel_time);
0503         }
0504         template <class Clock, class Duration>
0505         bool
0506         try_unlock_upgrade_and_lock_until(
0507                           const chrono::time_point<Clock, Duration>& abs_time)
0508         {
0509 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0510           boost::this_thread::disable_interruption do_not_disturb;
0511 #endif
0512           boost::unique_lock<boost::mutex> lk(state_change);
0513           state.assert_lock_upgraded();
0514           if(!shared_cond.wait_until(lk, abs_time, boost::bind(&state_data::one_shared, boost::ref(state))))
0515           {
0516               return false;
0517           }
0518           state.upgrade=false;
0519           state.exclusive=true;
0520           state.exclusive_waiting_blocked=false;
0521           state.shared_count=0;
0522           return true;
0523         }
0524 #endif
0525 
0526         // Shared <-> Exclusive
0527         void unlock_and_lock_shared()
0528         {
0529             boost::unique_lock<boost::mutex> lk(state_change);
0530             state.assert_locked();
0531             state.exclusive=false;
0532             state.lock_shared();
0533             state.exclusive_waiting_blocked=false;
0534             release_waiters();
0535         }
0536 
0537 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
0538         bool try_unlock_shared_and_lock()
0539         {
0540           boost::unique_lock<boost::mutex> lk(state_change);
0541           state.assert_lock_shared();
0542           if(    !state.exclusive
0543               && !state.exclusive_waiting_blocked
0544               && !state.upgrade
0545               && state.shared_count==1)
0546           {
0547             state.shared_count=0;
0548             state.exclusive=true;
0549             return true;
0550           }
0551           return false;
0552         }
0553 #ifdef BOOST_THREAD_USES_CHRONO
0554         template <class Rep, class Period>
0555             bool
0556             try_unlock_shared_and_lock_for(
0557                                 const chrono::duration<Rep, Period>& rel_time)
0558         {
0559           return try_unlock_shared_and_lock_until(
0560                                  chrono::steady_clock::now() + rel_time);
0561         }
0562         template <class Clock, class Duration>
0563             bool
0564             try_unlock_shared_and_lock_until(
0565                           const chrono::time_point<Clock, Duration>& abs_time)
0566         {
0567 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0568           boost::this_thread::disable_interruption do_not_disturb;
0569 #endif
0570           boost::unique_lock<boost::mutex> lk(state_change);
0571           state.assert_lock_shared();
0572           if(!shared_cond.wait_until(lk, abs_time, boost::bind(&state_data::one_shared, boost::ref(state))))
0573           {
0574               return false;
0575           }
0576           state.upgrade=false;
0577           state.exclusive=true;
0578           state.exclusive_waiting_blocked=false;
0579           state.shared_count=0;
0580           return true;
0581         }
0582 #endif
0583 #endif
0584 
0585         // Shared <-> Upgrade
0586         void unlock_upgrade_and_lock_shared()
0587         {
0588             boost::unique_lock<boost::mutex> lk(state_change);
0589             state.assert_lock_upgraded();
0590             state.upgrade=false;
0591             state.exclusive_waiting_blocked=false;
0592             release_waiters();
0593         }
0594 
0595 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
0596         bool try_unlock_shared_and_lock_upgrade()
0597         {
0598           boost::unique_lock<boost::mutex> lk(state_change);
0599           state.assert_lock_shared();
0600           if(state.can_lock_upgrade())
0601           {
0602             state.upgrade=true;
0603             return true;
0604           }
0605           return false;
0606         }
0607 #ifdef BOOST_THREAD_USES_CHRONO
0608         template <class Rep, class Period>
0609             bool
0610             try_unlock_shared_and_lock_upgrade_for(
0611                                 const chrono::duration<Rep, Period>& rel_time)
0612         {
0613           return try_unlock_shared_and_lock_upgrade_until(
0614                                  chrono::steady_clock::now() + rel_time);
0615         }
0616         template <class Clock, class Duration>
0617             bool
0618             try_unlock_shared_and_lock_upgrade_until(
0619                           const chrono::time_point<Clock, Duration>& abs_time)
0620         {
0621 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0622           boost::this_thread::disable_interruption do_not_disturb;
0623 #endif
0624           boost::unique_lock<boost::mutex> lk(state_change);
0625           state.assert_lock_shared();
0626           if(!exclusive_cond.wait_until(lk, abs_time, boost::bind(&state_data::can_lock_upgrade, boost::ref(state))))
0627           {
0628               return false;
0629           }
0630           state.upgrade=true;
0631           return true;
0632         }
0633 #endif
0634 #endif
0635     };
0636 
0637     typedef shared_mutex upgrade_mutex;
0638 }
0639 
0640 #include <boost/config/abi_suffix.hpp>
0641 
0642 #endif