#ifndef MULTIPLE_LOCKS_HPP #define MULTIPLE_LOCKS_HPP // multiple_locks.hpp // // (C) Copyright 2008 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) template unsigned try_lock(MutexType1& m1,MutexType2& m2) { boost::unique_lock l1(m1,boost::try_to_lock); if(!l1) { return 1; } if(!m2.try_lock()) { return 2; } l1.release(); return 0; } template unsigned try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3) { boost::unique_lock l1(m1,boost::try_to_lock); if(!l1) { return 1; } if(unsigned const failed_lock=try_lock(m2,m3)) { return failed_lock+1; } l1.release(); return 0; } template unsigned try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3, MutexType4& m4) { boost::unique_lock l1(m1,boost::try_to_lock); if(!l1) { return 1; } if(unsigned const failed_lock=try_lock(m2,m3,m4)) { return failed_lock+1; } l1.release(); return 0; } template unsigned try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3, MutexType4& m4,MutexType5& m5) { boost::unique_lock l1(m1,boost::try_to_lock); if(!l1) { return 1; } if(unsigned const failed_lock=try_lock(m2,m3,m4,m5)) { return failed_lock+1; } l1.release(); return 0; } namespace detail { template unsigned lock_helper(MutexType1& m1,MutexType2& m2) { boost::unique_lock l1(m1); if(!m2.try_lock()) { return 1; } l1.release(); return 0; } template unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3) { boost::unique_lock l1(m1); if(unsigned const failed_lock=try_lock(m2,m3)) { return failed_lock; } l1.release(); return 0; } template unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3, MutexType4& m4) { boost::unique_lock l1(m1); if(unsigned const failed_lock=try_lock(m2,m3,m4)) { return failed_lock; } l1.release(); return 0; } template unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3, MutexType4& m4,MutexType5& m5) { boost::unique_lock l1(m1); if(unsigned const failed_lock=try_lock(m2,m3,m4,m5)) { return failed_lock; } l1.release(); return 0; } } template void lock(MutexType1& m1,MutexType2& m2) { unsigned const lock_count=2; unsigned lock_first=0; while(true) { switch(lock_first) { case 0: lock_first=detail::lock_helper(m1,m2); if(!lock_first) return; break; case 1: lock_first=detail::lock_helper(m2,m1); if(!lock_first) return; lock_first=(lock_first+1)%lock_count; break; } } } template void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3) { unsigned const lock_count=3; unsigned lock_first=0; while(true) { switch(lock_first) { case 0: lock_first=detail::lock_helper(m1,m2,m3); if(!lock_first) return; break; case 1: lock_first=detail::lock_helper(m2,m3,m1); if(!lock_first) return; lock_first=(lock_first+1)%lock_count; break; case 2: lock_first=detail::lock_helper(m3,m1,m2); if(!lock_first) return; lock_first=(lock_first+2)%lock_count; break; } } } template void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3, MutexType4& m4) { unsigned const lock_count=4; unsigned lock_first=0; while(true) { switch(lock_first) { case 0: lock_first=detail::lock_helper(m1,m2,m3,m4); if(!lock_first) return; break; case 1: lock_first=detail::lock_helper(m2,m3,m4,m1); if(!lock_first) return; lock_first=(lock_first+1)%lock_count; break; case 2: lock_first=detail::lock_helper(m3,m4,m1,m2); if(!lock_first) return; lock_first=(lock_first+2)%lock_count; break; case 3: lock_first=detail::lock_helper(m4,m1,m2,m3); if(!lock_first) return; lock_first=(lock_first+3)%lock_count; break; } } } template void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3, MutexType4& m4,MutexType5& m5) { unsigned const lock_count=5; unsigned lock_first=0; while(true) { switch(lock_first) { case 0: lock_first=detail::lock_helper(m1,m2,m3,m4,m5); if(!lock_first) return; break; case 1: lock_first=detail::lock_helper(m2,m3,m4,m5,m1); if(!lock_first) return; lock_first=(lock_first+1)%lock_count; break; case 2: lock_first=detail::lock_helper(m3,m4,m5,m1,m2); if(!lock_first) return; lock_first=(lock_first+2)%lock_count; break; case 3: lock_first=detail::lock_helper(m4,m5,m1,m2,m3); if(!lock_first) return; lock_first=(lock_first+3)%lock_count; break; case 4: lock_first=detail::lock_helper(m5,m1,m2,m3,m4); if(!lock_first) return; lock_first=(lock_first+4)%lock_count; break; } } } #endif