Moved thread_local macro code to separate header file. Added more error values to enum family.

git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@1048 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
rich_sposato 2009-11-02 05:48:02 +00:00
parent 096a7d5841
commit f16c81d265
2 changed files with 69 additions and 59 deletions

View file

@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////////////////////////
//
// LevelMutex facility for the Loki Library
// Copyright (c) 2008 Richard Sposato
// Copyright (c) 2008, 2009 Richard Sposato
// The copyright on this file is protected under the terms of the MIT license.
//
// Permission to use, copy, modify, distribute and sell this software for any
@ -18,36 +18,22 @@
/// @file LevelMutex.cpp Contains functions needed by LevelMutex class.
// ----------------------------------------------------------------------------
// First assume the compiler does allow thread-local storage by #defining the
// macro which allows compiler to see the code inside this file.
// Then #undefine the macro for compilers which are known for not supporting
// thread-local storage.
#define COMPILER_ALLOWS_THREAD_LOCAL_STORAGE 1
// The __APPLE__ macro does not refer to a compiler, but to the Apple OSX operating system.
#if defined( __APPLE__ )
#warning "GCC for Apple does not allow thread_local storage, so you can not use Loki::LevelMutex."
#undef COMPILER_ALLOWS_THREAD_LOCAL_STORAGE
#endif
#if ( defined( __CYGWIN__ ) && ( __GNUC__ <= 3 ) )
#warning "Older versions of GCC for Cygwin do not allow thread_local storage, so you can not use Loki::LevelMutex."
#undef COMPILER_ALLOWS_THREAD_LOCAL_STORAGE
#endif
#if defined( COMPILER_ALLOWS_THREAD_LOCAL_STORAGE )
#include "../include/loki/LevelMutex.h"
#if defined( LOKI_THREAD_LOCAL )
#if !defined( _MSC_VER )
#include <unistd.h> // needed for usleep function.
#endif
#include <algorithm>
#include <cerrno>
#if defined( DEBUG ) || defined( _DEBUG )
#define DEBUG_LOKI_LEVEL_MUTEX 1
#include <iostream>
#endif
using namespace ::std;
@ -806,6 +792,9 @@ SpinLevelMutex::SpinLevelMutex( unsigned int level ) :
switch ( result )
{
case 0:
//#if defined( DEBUG_LOKI_LEVEL_MUTEX )
// cout << __FUNCTION__ << '\t' << __LINE__ << endl;
//#endif
return;
case EBUSY:
throw MutexException( "pthread mutex already initialized!",
@ -817,6 +806,18 @@ SpinLevelMutex::SpinLevelMutex( unsigned int level ) :
case EFAULT:
throw MutexException( "pthread mutex has an invalid address!",
level, MutexErrors::InvalidAddress );
case ENOMEM:
throw MutexException(
"System does not have enough memory to initialize a pthread mutex.",
level, MutexErrors::NotEnoughMemory );
case EPERM:
throw MutexException(
"Program does not have privilege to initialize a pthread mutex.",
level, MutexErrors::NotPrivileged );
case EAGAIN:
throw MutexException(
"Program does not have resources to initialize another pthread mutex.",
level, MutexErrors::NotEnoughResources );
}
#endif
}
@ -830,6 +831,9 @@ SpinLevelMutex::~SpinLevelMutex( void )
#if defined( _MSC_VER )
::DeleteCriticalSection( &m_mutex );
#else
//#if defined( DEBUG_LOKI_LEVEL_MUTEX )
// cout << __FUNCTION__ << '\t' << __LINE__ << endl;
//#endif
::pthread_mutex_destroy( &m_mutex );
#endif
}
@ -853,17 +857,29 @@ MutexErrors::Type SpinLevelMutex::Lock( void ) volatile
switch ( result )
{
case 0:
//#if defined( DEBUG_LOKI_LEVEL_MUTEX )
// cout << __FUNCTION__ << '\t' << __LINE__ << endl;
//#endif
break;
default:
case EINVAL:
throw MutexException( "pthread mutex not initialized properly!",
GetLevel(), MutexErrors::NotInitialized );
throw MutexException( "pthread mutex locked by thread with lower priority!",
GetLevel(), MutexErrors::InvertedPriority );
case EFAULT :
throw MutexException( "pthread mutex is not valid!",
GetLevel(), MutexErrors::InvalidAddress );
case EDEADLK:
throw MutexException( "locking this pthread mutex may cause a deadlock!",
GetLevel(), MutexErrors::MayDeadlock );
case EBUSY:
throw MutexException( "Mutex is already locked by this thread.",
GetLevel(), MutexErrors::AlreadyLocked );
case EAGAIN:
throw MutexException( "Mutex already locked too many times by this thread.",
GetLevel(), MutexErrors::TooMuchRecursion );
case EPERM:
throw MutexException( "This thread does not own the mutex.",
GetLevel(), MutexErrors::NotPrivileged );
}
#endif
return MutexErrors::Success;
@ -884,6 +900,9 @@ MutexErrors::Type SpinLevelMutex::TryLock( void ) volatile
switch ( result )
{
case 0:
//#if defined( DEBUG_LOKI_LEVEL_MUTEX )
// cout << __FUNCTION__ << '\t' << __LINE__ << endl;
//#endif
return MutexErrors::Success;
default:
case EBUSY:
@ -891,6 +910,9 @@ MutexErrors::Type SpinLevelMutex::TryLock( void ) volatile
case EAGAIN:
throw MutexException( "pthread mutex reached recursion limit!",
GetLevel(), MutexErrors::TooMuchRecursion );
case EINVAL:
throw MutexException( "pthread mutex locked by thread with lower priority!",
GetLevel(), MutexErrors::InvertedPriority );
}
return MutexErrors::TryFailed;
#endif
@ -910,6 +932,9 @@ MutexErrors::Type SpinLevelMutex::Unlock( void ) volatile
if ( EPERM == result )
throw MutexException( "current thread did not lock this pthread mutex!",
GetLevel(), MutexErrors::NotLockedByThread );
//#if defined( DEBUG_LOKI_LEVEL_MUTEX )
// cout << __FUNCTION__ << '\t' << __LINE__ << endl;
//#endif
#endif
return MutexErrors::Success;
}
@ -1165,4 +1190,4 @@ bool MultiMutexLocker::Unlock( void )
} // end namespace Loki
#endif // #if defined( COMPILER_ALLOWS_THREAD_LOCAL_STORAGE )
#endif // #if defined( LOKI_THREAD_LOCAL )