From: <ric...@us...> - 2009-11-02 05:48:10
|
Revision: 1048 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1048&view=rev Author: rich_sposato Date: 2009-11-02 05:48:02 +0000 (Mon, 02 Nov 2009) Log Message: ----------- Moved thread_local macro code to separate header file. Added more error values to enum family. Modified Paths: -------------- trunk/include/loki/LevelMutex.h trunk/src/LevelMutex.cpp Modified: trunk/include/loki/LevelMutex.h =================================================================== --- trunk/include/loki/LevelMutex.h 2009-11-02 05:43:58 UTC (rev 1047) +++ trunk/include/loki/LevelMutex.h 2009-11-02 05:48:02 UTC (rev 1048) @@ -1,12 +1,12 @@ //////////////////////////////////////////////////////////////////////////////// // // 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 -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. // // The author makes no representations about the suitability of this software @@ -35,36 +35,15 @@ #endif #if !defined(_WIN32) && !defined(_WIN64) - #include <unistd.h> // declares sleep under Linux + #include <unistd.h> // declares usleep under Linux #endif -/** @par thread_local Keyword - The mutexes require compilers to provide thread local storage - meaning each - thread gets its own copy of the data. The next version of C++ will have a - new keyword, thread_local for that purpose. Some existing compilers already - provide thread local storage using different syntax, so these lines use - thread_local to mimic that syntax. If your compiler provides thread local - storage but using different syntax besides "thread_local", you may want to - modify these lines. If your compiler does not support thread local storage, - you can't use LevelMutex. - */ -#ifndef LOKI_THREAD_LOCAL - #if defined( _MSC_VER ) - #if ( _MSC_VER >= 1300 ) - #define LOKI_THREAD_LOCAL __declspec( thread ) - #else - #error "Only Visual Studio versions 7.0 and after supported." - #endif +#include <loki/ThreadLocal.h> // Include Loki's form of thread_local declaration. - #elif ( __GNUC__ ) - #define LOKI_THREAD_LOCAL __thread +#if !defined( LOKI_THREAD_LOCAL ) + #warning "Your compiler will not allow Loki::LevelMutex." +#else - #else - #warning "Check if your compiler provides thread local storage." - #define LOKI_THREAD_LOCAL thread_local - #endif -#endif - #if defined( DEBUG ) || defined( _DEBUG ) #define LOKI_MUTEX_DEBUG_CODE( x ) x #else @@ -106,7 +85,11 @@ InvalidAttribute, ///< PThread mutex improperly initialized. InvalidAddress, ///< Bad pointer used to initialize a PThread mutex. ExceptionThrown, ///< Exception caught in mutex operation. + InvertedPriority, ///< Mutex already locked by thread with lower priority. MayDeadlock, ///< Locking this mutex may cause a deadlock. + NotPrivileged, ///< Program does not have privilege to initialize mutexes. + NotEnoughMemory, ///< Program does not have enough memory to initialize mutex. + NotEnoughResources, ///< Program does not have enough resources to initialize mutex. OtherError ///< Unknown error occurred. }; }; @@ -374,7 +357,7 @@ */ virtual MutexErrors::Type LockThis( unsigned int milliSeconds ) volatile = 0; - /// Called only by MultiUnlock to unlock each particular mutex within a container. + /// Called only by MultiUnlock to unlock each particular mutex within a container. virtual MutexErrors::Type UnlockThis( void ) volatile = 0; /// Pointer to singly-linked list of mutexes locked by the current thread. @@ -565,7 +548,7 @@ Implements a sleeping loop to wait for the mutex to unlock. @par Purpose - Since this class puts the thread to sleep for short intervals, you can use this + Since this class puts the thread to sleep for short intervals, you can use this class for most of your mutexes. Especially for locking any high level resources where any one operation on the resouce consumes many CPU cycles. The purpose of this mutex is to reduce the number of CPU cycles spent in idle loops. All @@ -1101,7 +1084,7 @@ /// Returns true if the mutex is locked by this object. inline bool IsLocked( void ) const { return m_locked; } - /// Provides access to mutex controlled by this. + /// Provides access to mutex controlled by this. const volatile LevelMutexInfo & GetMutex( void ) const { return m_mutex; } private: @@ -1179,7 +1162,7 @@ /// Returns true if the mutexes are locked by this object. inline bool IsLocked( void ) const { return m_locked; } - /// Provides access to the collection of mutexes controlled by this. + /// Provides access to the collection of mutexes controlled by this. const LevelMutexInfo::MutexContainer & GetMutexes( void ) const { return m_mutexes; } private: @@ -1202,4 +1185,6 @@ } // end namespace Loki +#endif // end else if compiler allows thread_local storage + #endif // end file guardian Modified: trunk/src/LevelMutex.cpp =================================================================== --- trunk/src/LevelMutex.cpp 2009-11-02 05:43:58 UTC (rev 1047) +++ trunk/src/LevelMutex.cpp 2009-11-02 05:48:02 UTC (rev 1048) @@ -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,37 +18,23 @@ /// @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 +#include "../include/loki/LevelMutex.h" -// 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( LOKI_THREAD_LOCAL ) -#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( _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; // define nullptr even though new compilers will have this keyword just so we @@ -806,6 +792,9 @@ 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 @@ 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 @@ #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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } // end namespace Loki -#endif // #if defined( COMPILER_ALLOWS_THREAD_LOCAL_STORAGE ) +#endif // #if defined( LOKI_THREAD_LOCAL ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |