Merged master 8748
This commit is contained in:
@@ -0,0 +1,716 @@
|
||||
#ifndef BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
|
||||
#define BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
|
||||
|
||||
// (C) Copyright 2006-8 Anthony Williams
|
||||
// (C) Copyright 2012 Vicente J. Botet Escriba
|
||||
//
|
||||
// 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)
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
#include <boost/thread/detail/thread_interruption.hpp>
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
#include <boost/chrono/system_clocks.hpp>
|
||||
#include <boost/chrono/ceil.hpp>
|
||||
#endif
|
||||
#include <boost/thread/detail/delete.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <boost/config/abi_prefix.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class shared_mutex
|
||||
{
|
||||
private:
|
||||
class state_data
|
||||
{
|
||||
public:
|
||||
state_data () :
|
||||
shared_count(0),
|
||||
exclusive(false),
|
||||
upgrade(false),
|
||||
exclusive_waiting_blocked(false)
|
||||
{}
|
||||
|
||||
void assert_free() const
|
||||
{
|
||||
BOOST_ASSERT( ! exclusive );
|
||||
BOOST_ASSERT( ! upgrade );
|
||||
BOOST_ASSERT( shared_count==0 );
|
||||
}
|
||||
|
||||
void assert_locked() const
|
||||
{
|
||||
BOOST_ASSERT( exclusive );
|
||||
BOOST_ASSERT( shared_count==0 );
|
||||
BOOST_ASSERT( ! upgrade );
|
||||
}
|
||||
|
||||
void assert_lock_shared () const
|
||||
{
|
||||
BOOST_ASSERT( ! exclusive );
|
||||
BOOST_ASSERT( shared_count>0 );
|
||||
//BOOST_ASSERT( (! upgrade) || (shared_count>1));
|
||||
// if upgraded there are at least 2 threads sharing the mutex,
|
||||
// except when unlock_upgrade_and_lock has decreased the number of readers but has not taken yet exclusive ownership.
|
||||
}
|
||||
|
||||
void assert_lock_upgraded () const
|
||||
{
|
||||
BOOST_ASSERT( ! exclusive );
|
||||
BOOST_ASSERT( upgrade );
|
||||
BOOST_ASSERT( shared_count>0 );
|
||||
}
|
||||
|
||||
void assert_lock_not_upgraded () const
|
||||
{
|
||||
BOOST_ASSERT( ! upgrade );
|
||||
}
|
||||
|
||||
bool can_lock () const
|
||||
{
|
||||
return ! (shared_count || exclusive);
|
||||
}
|
||||
|
||||
void exclusive_blocked (bool blocked)
|
||||
{
|
||||
exclusive_waiting_blocked = blocked;
|
||||
}
|
||||
|
||||
void lock ()
|
||||
{
|
||||
exclusive = true;
|
||||
}
|
||||
|
||||
void unlock ()
|
||||
{
|
||||
exclusive = false;
|
||||
exclusive_waiting_blocked = false;
|
||||
}
|
||||
|
||||
bool can_lock_shared () const
|
||||
{
|
||||
return ! (exclusive || exclusive_waiting_blocked);
|
||||
}
|
||||
|
||||
bool more_shared () const
|
||||
{
|
||||
return shared_count > 0 ;
|
||||
}
|
||||
unsigned get_shared_count () const
|
||||
{
|
||||
return shared_count ;
|
||||
}
|
||||
unsigned lock_shared ()
|
||||
{
|
||||
return ++shared_count;
|
||||
}
|
||||
|
||||
|
||||
void unlock_shared ()
|
||||
{
|
||||
--shared_count;
|
||||
}
|
||||
|
||||
bool unlock_shared_downgrades()
|
||||
{
|
||||
if (upgrade) {
|
||||
upgrade=false;
|
||||
exclusive=true;
|
||||
return true;
|
||||
} else {
|
||||
exclusive_waiting_blocked=false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void lock_upgrade ()
|
||||
{
|
||||
++shared_count;
|
||||
upgrade=true;
|
||||
}
|
||||
bool can_lock_upgrade () const
|
||||
{
|
||||
return ! (exclusive || exclusive_waiting_blocked || upgrade);
|
||||
}
|
||||
|
||||
void unlock_upgrade ()
|
||||
{
|
||||
upgrade=false;
|
||||
--shared_count;
|
||||
}
|
||||
|
||||
//private:
|
||||
unsigned shared_count;
|
||||
bool exclusive;
|
||||
bool upgrade;
|
||||
bool exclusive_waiting_blocked;
|
||||
};
|
||||
|
||||
|
||||
|
||||
state_data state;
|
||||
boost::mutex state_change;
|
||||
boost::condition_variable shared_cond;
|
||||
boost::condition_variable exclusive_cond;
|
||||
boost::condition_variable upgrade_cond;
|
||||
|
||||
void release_waiters()
|
||||
{
|
||||
exclusive_cond.notify_one();
|
||||
shared_cond.notify_all();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
BOOST_THREAD_NO_COPYABLE(shared_mutex)
|
||||
|
||||
shared_mutex()
|
||||
{
|
||||
}
|
||||
|
||||
~shared_mutex()
|
||||
{
|
||||
}
|
||||
|
||||
void lock_shared()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
while(!state.can_lock_shared())
|
||||
{
|
||||
shared_cond.wait(lk);
|
||||
}
|
||||
state.lock_shared();
|
||||
}
|
||||
|
||||
bool try_lock_shared()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
if(!state.can_lock_shared())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
state.lock_shared();
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool timed_lock_shared(system_time const& timeout)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
while(!state.can_lock_shared())
|
||||
{
|
||||
if(!shared_cond.timed_wait(lk,timeout))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
state.lock_shared();
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock_shared(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock_shared(get_system_time()+relative_time);
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
while(!state.can_lock_shared())
|
||||
//while(state.exclusive || state.exclusive_waiting_blocked)
|
||||
{
|
||||
if(cv_status::timeout==shared_cond.wait_until(lk,abs_time))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
state.lock_shared();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
void unlock_shared()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_shared();
|
||||
state.unlock_shared();
|
||||
if (! state.more_shared())
|
||||
{
|
||||
if (state.upgrade)
|
||||
{
|
||||
// As there is a thread doing a unlock_upgrade_and_lock that is waiting for ! state.more_shared()
|
||||
// avoid other threads to lock, lock_upgrade or lock_shared, so only this thread is notified.
|
||||
state.upgrade=false;
|
||||
state.exclusive=true;
|
||||
//lk.unlock();
|
||||
upgrade_cond.notify_one();
|
||||
}
|
||||
else
|
||||
{
|
||||
state.exclusive_waiting_blocked=false;
|
||||
//lk.unlock();
|
||||
}
|
||||
release_waiters();
|
||||
}
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
while (state.shared_count || state.exclusive)
|
||||
{
|
||||
state.exclusive_waiting_blocked=true;
|
||||
exclusive_cond.wait(lk);
|
||||
}
|
||||
state.exclusive=true;
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool timed_lock(system_time const& timeout)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
while(state.shared_count || state.exclusive)
|
||||
{
|
||||
state.exclusive_waiting_blocked=true;
|
||||
if(!exclusive_cond.timed_wait(lk,timeout))
|
||||
{
|
||||
if(state.shared_count || state.exclusive)
|
||||
{
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
state.exclusive=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock(get_system_time()+relative_time);
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
return try_lock_until(chrono::steady_clock::now() + rel_time);
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
while(state.shared_count || state.exclusive)
|
||||
{
|
||||
state.exclusive_waiting_blocked=true;
|
||||
if(cv_status::timeout == exclusive_cond.wait_until(lk,abs_time))
|
||||
{
|
||||
if(state.shared_count || state.exclusive)
|
||||
{
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
state.exclusive=true;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
|
||||
if(state.shared_count || state.exclusive)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.exclusive=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_locked();
|
||||
state.exclusive=false;
|
||||
state.exclusive_waiting_blocked=false;
|
||||
state.assert_free();
|
||||
release_waiters();
|
||||
}
|
||||
|
||||
void lock_upgrade()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
|
||||
{
|
||||
shared_cond.wait(lk);
|
||||
}
|
||||
state.lock_shared();
|
||||
state.upgrade=true;
|
||||
}
|
||||
|
||||
#if defined BOOST_THREAD_USES_DATETIME
|
||||
bool timed_lock_upgrade(system_time const& timeout)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
|
||||
{
|
||||
if(!shared_cond.timed_wait(lk,timeout))
|
||||
{
|
||||
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
state.lock_shared();
|
||||
state.upgrade=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock_upgrade(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock_upgrade(get_system_time()+relative_time);
|
||||
}
|
||||
#endif
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
bool try_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
return try_lock_upgrade_until(chrono::steady_clock::now() + rel_time);
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool try_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
|
||||
{
|
||||
if(cv_status::timeout == shared_cond.wait_until(lk,abs_time))
|
||||
{
|
||||
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
state.lock_shared();
|
||||
state.upgrade=true;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
bool try_lock_upgrade()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.lock_shared();
|
||||
state.upgrade=true;
|
||||
state.assert_lock_upgraded();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_upgrade()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
//state.upgrade=false;
|
||||
state.unlock_upgrade();
|
||||
if(! state.more_shared() )
|
||||
{
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
} else {
|
||||
shared_cond.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
// Upgrade <-> Exclusive
|
||||
void unlock_upgrade_and_lock()
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_upgraded();
|
||||
state.unlock_shared();
|
||||
while (state.more_shared())
|
||||
{
|
||||
upgrade_cond.wait(lk);
|
||||
}
|
||||
state.upgrade=false;
|
||||
state.exclusive=true;
|
||||
state.assert_locked();
|
||||
}
|
||||
|
||||
void unlock_and_lock_upgrade()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_locked();
|
||||
state.exclusive=false;
|
||||
state.upgrade=true;
|
||||
state.lock_shared();
|
||||
state.exclusive_waiting_blocked=false;
|
||||
state.assert_lock_upgraded();
|
||||
release_waiters();
|
||||
}
|
||||
|
||||
bool try_unlock_upgrade_and_lock()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_upgraded();
|
||||
if( !state.exclusive
|
||||
&& !state.exclusive_waiting_blocked
|
||||
&& state.upgrade
|
||||
&& state.shared_count==1)
|
||||
{
|
||||
state.shared_count=0;
|
||||
state.exclusive=true;
|
||||
state.upgrade=false;
|
||||
state.assert_locked();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
bool
|
||||
try_unlock_upgrade_and_lock_for(
|
||||
const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
return try_unlock_upgrade_and_lock_until(
|
||||
chrono::steady_clock::now() + rel_time);
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool
|
||||
try_unlock_upgrade_and_lock_until(
|
||||
const chrono::time_point<Clock, Duration>& abs_time)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_upgraded();
|
||||
if (state.shared_count != 1)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
cv_status status = shared_cond.wait_until(lk,abs_time);
|
||||
if (state.shared_count == 1)
|
||||
break;
|
||||
if(status == cv_status::timeout)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
state.upgrade=false;
|
||||
state.exclusive=true;
|
||||
state.exclusive_waiting_blocked=false;
|
||||
state.shared_count=0;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Shared <-> Exclusive
|
||||
void unlock_and_lock_shared()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_locked();
|
||||
state.exclusive=false;
|
||||
state.lock_shared();
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
}
|
||||
|
||||
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
|
||||
bool try_unlock_shared_and_lock()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_shared();
|
||||
if( !state.exclusive
|
||||
&& !state.exclusive_waiting_blocked
|
||||
&& !state.upgrade
|
||||
&& state.shared_count==1)
|
||||
{
|
||||
state.shared_count=0;
|
||||
state.exclusive=true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
bool
|
||||
try_unlock_shared_and_lock_for(
|
||||
const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
return try_unlock_shared_and_lock_until(
|
||||
chrono::steady_clock::now() + rel_time);
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool
|
||||
try_unlock_shared_and_lock_until(
|
||||
const chrono::time_point<Clock, Duration>& abs_time)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_shared();
|
||||
if (state.shared_count != 1)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
cv_status status = shared_cond.wait_until(lk,abs_time);
|
||||
if (state.shared_count == 1)
|
||||
break;
|
||||
if(status == cv_status::timeout)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
state.upgrade=false;
|
||||
state.exclusive=true;
|
||||
state.exclusive_waiting_blocked=false;
|
||||
state.shared_count=0;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Shared <-> Upgrade
|
||||
void unlock_upgrade_and_lock_shared()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_upgraded();
|
||||
state.upgrade=false;
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
}
|
||||
|
||||
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
|
||||
bool try_unlock_shared_and_lock_upgrade()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_shared();
|
||||
if( !state.exclusive
|
||||
&& !state.exclusive_waiting_blocked
|
||||
&& !state.upgrade
|
||||
)
|
||||
{
|
||||
state.upgrade=true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#ifdef BOOST_THREAD_USES_CHRONO
|
||||
template <class Rep, class Period>
|
||||
bool
|
||||
try_unlock_shared_and_lock_upgrade_for(
|
||||
const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
return try_unlock_shared_and_lock_upgrade_until(
|
||||
chrono::steady_clock::now() + rel_time);
|
||||
}
|
||||
template <class Clock, class Duration>
|
||||
bool
|
||||
try_unlock_shared_and_lock_upgrade_until(
|
||||
const chrono::time_point<Clock, Duration>& abs_time)
|
||||
{
|
||||
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
#endif
|
||||
boost::unique_lock<boost::mutex> lk(state_change);
|
||||
state.assert_lock_shared();
|
||||
if( state.exclusive
|
||||
|| state.exclusive_waiting_blocked
|
||||
|| state.upgrade
|
||||
)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
cv_status status = exclusive_cond.wait_until(lk,abs_time);
|
||||
if( ! state.exclusive
|
||||
&& ! state.exclusive_waiting_blocked
|
||||
&& ! state.upgrade
|
||||
)
|
||||
break;
|
||||
if(status == cv_status::timeout)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
state.upgrade=true;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef shared_mutex upgrade_mutex;
|
||||
}
|
||||
|
||||
#include <boost/config/abi_suffix.hpp>
|
||||
|
||||
#endif
|
||||
@@ -1,3 +0,0 @@
|
||||
1
|
||||
2
|
||||
1.0
|
||||
@@ -1,76 +0,0 @@
|
||||
program msksim
|
||||
|
||||
use, intrinsic :: iso_c_binding
|
||||
|
||||
! To change to a new code, edit the following line and the filenames
|
||||
! that contain the parity check and generator matrices.
|
||||
parameter (N=198, M=126, K=72) ! M and N are global variables on the C side.
|
||||
|
||||
character(50) pchk_file,gen_file
|
||||
integer(1) codeword(1:N), decoded(1:K), message(1:K)
|
||||
real*8 lratio(N), rxdata(N)
|
||||
|
||||
pchk_file="./jtmode_codes/peg-198-72-irreg-8x3-2x4.pchk"
|
||||
gen_file="./jtmode_codes/peg-198-72-irreg-8x3-2x4.gen"
|
||||
|
||||
rate=real(K)/real(N)
|
||||
|
||||
call init_ldpc(trim(pchk_file)//char(0),trim(gen_file)//char(0))
|
||||
|
||||
message(1:K/2)=1
|
||||
message((K/2+1):K)=0
|
||||
call ldpc_encode(message,codeword)
|
||||
|
||||
max_iterations=50
|
||||
ntrials=1000000
|
||||
|
||||
write(*,*) "Eb/N0 ngood nundetected"
|
||||
do idb = 0, 11
|
||||
db=idb/2.0-0.5
|
||||
sigma=1/sqrt( 2*rate*(10**(db/10.0)) )
|
||||
|
||||
ngood=0
|
||||
nue=0
|
||||
|
||||
do itrial=1, ntrials
|
||||
|
||||
do i=1,N
|
||||
rxdata(i) = 2.0*(codeword(i)-0.5) + sigma*gran()
|
||||
enddo
|
||||
|
||||
! correct signal normalization is important for this decoder.
|
||||
rxav=sum(rxdata)/N
|
||||
rx2av=sum(rxdata*rxdata)/N
|
||||
rxsig=sqrt(rx2av-rxav*rxav)
|
||||
rxdata=rxdata/rxsig
|
||||
|
||||
! s can be tuned to trade a few tenth's dB of threshold
|
||||
! for an order of magnitude in UER
|
||||
do i=1,N
|
||||
s=0.75
|
||||
lratio(i)=exp(2.0*rxdata(i)/(s*s))
|
||||
enddo
|
||||
|
||||
call ldpc_decode(lratio, decoded, max_iterations, niterations)
|
||||
|
||||
if( niterations .ge. 0 ) then
|
||||
nueflag=0
|
||||
do i=1,K
|
||||
if( message(i) .ne. decoded(i) ) then
|
||||
nueflag=1
|
||||
endif
|
||||
enddo
|
||||
if( nueflag .eq. 1 ) then
|
||||
nue=nue+1
|
||||
else
|
||||
ngood=ngood+1;
|
||||
endif
|
||||
endif
|
||||
|
||||
enddo
|
||||
|
||||
write(*,"(f4.1,1x,i8,1x,i8)") db,ngood,nue
|
||||
|
||||
enddo
|
||||
|
||||
end program msksim
|
||||
@@ -1,27 +0,0 @@
|
||||
Type 1 Prefixes and Suffixes:
|
||||
|
||||
1A 1S 3A 3B6 3B8 3B9 3C 3C0 3D2 3D2C 3D2R 3DA 3V 3W 3X
|
||||
3Y 3YB 3YP 4J 4L 4S 4U1I 4U1U 4W 4X 5A 5B 5H 5N 5R
|
||||
5T 5U 5V 5W 5X 5Z 6W 6Y 7O 7P 7Q 7X 8P 8Q 8R
|
||||
9A 9G 9H 9J 9K 9L 9M2 9M6 9N 9Q 9U 9V 9X 9Y A2
|
||||
A3 A4 A5 A6 A7 A9 AP BS7 BV BV9 BY C2 C3 C5 C6
|
||||
C9 CE CE0X CE0Y CE0Z CE9 CM CN CP CT CT3 CU CX CY0 CY9
|
||||
D2 D4 D6 DL DU E3 E4 EA EA6 EA8 EA9 EI EK EL EP
|
||||
ER ES ET EU EX EY EZ F FG FH FJ FK FKC FM FO
|
||||
FOA FOC FOM FP FR FRG FRJ FRT FT5W FT5X FT5Z FW FY M MD
|
||||
MI MJ MM MU MW H4 H40 HA HB HB0 HC HC8 HH HI HK
|
||||
HK0A HK0M HL HM HP HR HS HV HZ I IS IS0 J2 J3 J5
|
||||
J6 J7 J8 JA JDM JDO JT JW JX JY K KG4 KH0 KH1 KH2
|
||||
KH3 KH4 KH5 KH5K KH6 KH7 KH8 KH9 KL KP1 KP2 KP4 KP5 LA LU
|
||||
LX LY LZ OA OD OE OH OH0 OJ0 OK OM ON OX OY OZ
|
||||
P2 P4 PA PJ2 PJ7 PY PY0F PT0S PY0T PZ R1F R1M S0 S2 S5
|
||||
S7 S9 SM SP ST SU SV SVA SV5 SV9 T2 T30 T31 T32 T33
|
||||
T5 T7 T8 T9 TA TF TG TI TI9 TJ TK TL TN TR TT
|
||||
TU TY TZ UA UA2 UA9 UK UN UR V2 V3 V4 V5 V6 V7
|
||||
V8 VE VK VK0H VK0M VK9C VK9L VK9M VK9N VK9W VK9X VP2E VP2M VP2V VP5
|
||||
VP6 VP6D VP8 VP8G VP8H VP8O VP8S VP9 VQ9 VR VU VU4 VU7 XE XF4
|
||||
XT XU XW XX9 XZ YA YB YI YJ YK YL YN YO YS YU
|
||||
YV YV0 Z2 Z3 ZA ZB ZC4 ZD7 ZD8 ZD9 ZF ZK1N ZK1S ZK2 ZK3
|
||||
ZL ZL7 ZL8 ZL9 ZP ZS ZS8 KC4 E5
|
||||
|
||||
Short-list of Add-on Suffixes: /0 /1 /2 /3 /4 /5 /6 /7 /8 /9 /A /P
|
||||
Reference in New Issue
Block a user