diff options
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | xbmc/cores/DllLoader/exports/emu_kernel32.cpp | 141 | ||||
-rw-r--r-- | xbmc/cores/DllLoader/exports/emu_kernel32.h | 9 | ||||
-rw-r--r-- | xbmc/cores/DllLoader/exports/emu_msvcrt.cpp | 16 | ||||
-rw-r--r-- | xbmc/linux/Makefile.in | 1 | ||||
-rw-r--r-- | xbmc/threads/CriticalSection.cpp | 49 | ||||
-rw-r--r-- | xbmc/threads/CriticalSection.h | 104 | ||||
-rw-r--r-- | xbmc/threads/Makefile | 5 | ||||
-rw-r--r-- | xbmc/threads/SharedSection.cpp | 187 | ||||
-rw-r--r-- | xbmc/threads/SharedSection.h | 81 | ||||
-rw-r--r-- | xbmc/threads/SingleLock.cpp | 112 | ||||
-rw-r--r-- | xbmc/threads/SingleLock.h | 69 |
12 files changed, 137 insertions, 639 deletions
diff --git a/configure.in b/configure.in index 68fbc7d2b5..c0920a0fb5 100644 --- a/configure.in +++ b/configure.in @@ -532,6 +532,7 @@ AC_CHECK_HEADER([sys/inotify.h], AC_DEFINE([HAVE_INOTIFY],[1],[Define if we have # Checks for boost headers using CXX instead of CC AC_LANG_PUSH([C++]) AC_CHECK_HEADER([boost/shared_ptr.hpp],, AC_MSG_ERROR($missing_library)) +AC_CHECK_HEADER([boost/thread.hpp],, AC_MSG_ERROR($missing_library)) AC_LANG_POP([C++]) # Checks for platforms libraries. @@ -604,6 +605,7 @@ AC_CHECK_LIB([ssh], [sftp_tell64],, AC_MSG_RESULT([Could not find suitab AC_CHECK_LIB([smbclient], [main],, AC_MSG_ERROR($missing_library)) AC_CHECK_LIB([bluetooth], [hci_devid],, AC_MSG_RESULT([Could not find suitable version of libbluetooth])) AC_CHECK_LIB([yajl], [main],, AC_MSG_ERROR($missing_library)) +AC_CHECK_LIB([boost_thread],[main],, AC_MSG_ERROR($missing_library)) PKG_CHECK_MODULES([FONTCONFIG], [fontconfig], [INCLUDES="$INCLUDES $FONTCONFIG_CFLAGS"; LIBS="$LIBS $FONTCONFIG_LIBS"], AC_MSG_ERROR($missing_library)) diff --git a/xbmc/cores/DllLoader/exports/emu_kernel32.cpp b/xbmc/cores/DllLoader/exports/emu_kernel32.cpp index 0a0bb81055..f9a9cc0c1a 100644 --- a/xbmc/cores/DllLoader/exports/emu_kernel32.cpp +++ b/xbmc/cores/DllLoader/exports/emu_kernel32.cpp @@ -226,93 +226,11 @@ struct SThreadWrapper PCHAR lpDLL; }; -#ifdef _DEBUG -#define MS_VC_EXCEPTION 0x406d1388 -typedef struct tagTHREADNAME_INFO -{ - DWORD dwType; // must be 0x1000 - LPCSTR szName; // pointer to name (in same addr space) - DWORD dwThreadID; // thread ID (-1 caller thread) - DWORD dwFlags; // reserved for future use, most be zero -} THREADNAME_INFO; -#endif - -#ifdef _LINUX -int dllThreadWrapper(LPVOID lpThreadParameter) -#else -unsigned int __stdcall dllThreadWrapper(LPVOID lpThreadParameter) -#endif -{ - SThreadWrapper *param = (SThreadWrapper*)lpThreadParameter; - DWORD result; - -#if defined(_DEBUG) && !defined(_LINUX) - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = "DLL"; - info.dwThreadID = ::GetCurrentThreadId(); - info.dwFlags = 0; - __try - { - RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(DWORD), (DWORD *)&info); - } - __except (EXCEPTION_CONTINUE_EXECUTION) - { - } -#endif - - __try - { - result = param->lpStartAddress(param->lpParameter); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - CLog::Log(LOGERROR, "DLL:%s - Unhandled exception in thread created by dll", param->lpDLL ); - result = 0; - } - - delete param; - return result; - -} - -extern "C" HANDLE WINAPI dllCreateThread( - LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD - DWORD dwStackSize, // initial stack size - LPTHREAD_START_ROUTINE lpStartAddress, // thread function - LPVOID lpParameter, // thread argument - DWORD dwCreationFlags, // creation option - LPDWORD lpThreadId // thread identifier -) -{ - uintptr_t loc = (uintptr_t)_ReturnAddress(); - - SThreadWrapper *param = new SThreadWrapper; - param->lpStartAddress = lpStartAddress; - param->lpParameter = lpParameter; - param->lpDLL = tracker_getdllname(loc); - - return (HANDLE)_beginthreadex(lpThreadAttributes, dwStackSize, dllThreadWrapper, param, dwCreationFlags, (unsigned int *)lpThreadId); -} - - -extern "C" BOOL WINAPI dllTerminateThread(HANDLE tHread, DWORD dwExitCode) -{ - not_implement("kernel32.dll fake function TerminateThread called\n"); //warning - return TRUE; -} - extern "C" void WINAPI dllSleep(DWORD dwTime) { return ::Sleep(dwTime); } -extern "C" HANDLE WINAPI dllGetCurrentThread(void) -{ - HANDLE retval = GetCurrentThread(); - return retval; -} - extern "C" DWORD WINAPI dllGetCurrentProcessId(void) { #ifdef _LINUX @@ -414,65 +332,6 @@ extern "C" UINT WINAPI dllGetPrivateProfileIntA( return nDefault; } -//globals for memory leak hack, no need for well-behaved dlls call init/del in pair -//We can free the sections if applications does not call deletecriticalsection -//need to initialize the list head NULL at mplayer_open_file, and free memory at close file. -std::map<LPCRITICAL_SECTION, LPCRITICAL_SECTION> g_mapCriticalSection; - -extern "C" void WINAPI dllDeleteCriticalSection(LPCRITICAL_SECTION cs) -{ -#ifdef API_DEBUG - CLog::Log(LOGDEBUG, "DeleteCriticalSection(0x%x)", cs); -#endif - if (g_mapCriticalSection.find(cs) != g_mapCriticalSection.end()) - { - LPCRITICAL_SECTION cs_new = g_mapCriticalSection[cs]; - DeleteCriticalSection(cs_new); - delete cs_new; - g_mapCriticalSection.erase(cs); - } -} - -extern "C" void WINAPI dllInitializeCriticalSection(LPCRITICAL_SECTION cs) -{ -#ifdef API_DEBUG - CLog::Log(LOGDEBUG, "InitializeCriticalSection(0x%x)", cs); -#endif - LPCRITICAL_SECTION cs_new = new CRITICAL_SECTION; - memset(cs_new, 0, sizeof(CRITICAL_SECTION)); - InitializeCriticalSection(cs_new); - - // just take the first member of the CRITICAL_SECTION to save ourdata in, this will be used to - // get fast access to the new critial section in dllLeaveCriticalSection and dllEnterCriticalSection - ((LPCRITICAL_SECTION*)cs)[0] = cs_new; - g_mapCriticalSection[cs] = cs_new; -} - -extern "C" void WINAPI dllLeaveCriticalSection(LPCRITICAL_SECTION cs) -{ -#ifdef API_DEBUG - CLog::Log(LOGDEBUG, "LeaveCriticalSection(0x%x) %p\n", ((LPCRITICAL_SECTION*)cs)[0]); -#endif - LeaveCriticalSection(((LPCRITICAL_SECTION*)cs)[0]); -} - -extern "C" void WINAPI dllEnterCriticalSection(LPCRITICAL_SECTION cs) -{ -#ifdef API_DEBUG - CLog::Log(LOGDEBUG, "EnterCriticalSection(0x%x) %p\n", cs, ((LPCRITICAL_SECTION*)cs)[0]); -#endif -#ifndef _LINUX - if (!(LPCRITICAL_SECTION)cs->OwningThread) - { -#ifdef API_DEBUG - CLog::Log(LOGDEBUG, "entered uninitialized critisec!\n"); -#endif - dllInitializeCriticalSection(cs); - } -#endif - EnterCriticalSection(((LPCRITICAL_SECTION*)cs)[0]); -} - extern "C" DWORD WINAPI dllGetVersion() { #ifdef API_DEBUG diff --git a/xbmc/cores/DllLoader/exports/emu_kernel32.h b/xbmc/cores/DllLoader/exports/emu_kernel32.h index 459cf47fef..a1639a9df6 100644 --- a/xbmc/cores/DllLoader/exports/emu_kernel32.h +++ b/xbmc/cores/DllLoader/exports/emu_kernel32.h @@ -598,10 +598,6 @@ extern "C" BOOL WINAPI dllFindClose(HANDLE hFile); extern "C" UINT WINAPI dllGetAtomNameA( ATOM nAtom, LPTSTR lpBuffer, int nSize); extern "C" ATOM WINAPI dllFindAtomA( LPCTSTR lpString); extern "C" ATOM WINAPI dllAddAtomA( LPCTSTR lpString); -extern "C" HANDLE WINAPI dllCreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); -extern "C" BOOL WINAPI dllTerminateThread(HANDLE tHread, DWORD dwExitCode); -extern "C" HANDLE WINAPI dllGetCurrentThread(void); -extern "C" DWORD WINAPI dllGetCurrentThreadId(VOID); extern "C" DWORD WINAPI dllGetCurrentProcessId(void); extern "C" BOOL WINAPI dllDisableThreadLibraryCalls(HMODULE); @@ -621,11 +617,6 @@ extern "C" void WINAPI dllGetSystemInfo(LPSYSTEM_INFO lpSystemInfo); extern "C" UINT WINAPI dllGetPrivateProfileIntA(LPCSTR lpAppName, LPCSTR lpKeyName, INT nDefault, LPCSTR lpFileName); -extern "C" void WINAPI dllDeleteCriticalSection(LPCRITICAL_SECTION cs); -extern "C" void WINAPI dllInitializeCriticalSection(LPCRITICAL_SECTION cs); -extern "C" void WINAPI dllLeaveCriticalSection(LPCRITICAL_SECTION cs); -extern "C" void WINAPI dllEnterCriticalSection(LPCRITICAL_SECTION cs); - extern "C" BOOL WINAPI dllGetVersionExA(LPOSVERSIONINFO lpVersionInfo); extern "C" BOOL WINAPI dllGetVersionExW(LPOSVERSIONINFOW lpVersionInfo); extern "C" DWORD WINAPI dllGetVersion(); diff --git a/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp b/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp index 204675d58d..aea6f1e47d 100644 --- a/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp +++ b/xbmc/cores/DllLoader/exports/emu_msvcrt.cpp @@ -1705,22 +1705,6 @@ extern "C" return 0; } - uintptr_t dll_beginthread( - void( *start_address )( void * ), - unsigned stack_size, - void *arglist - ) - { - return _beginthread(start_address, stack_size, arglist); - } - - HANDLE dll_beginthreadex(LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, - LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, - LPDWORD lpThreadId) - { - return dllCreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId); - } - //SLOW CODE SHOULD BE REVISED int dll_stat(const char *path, struct stat *buffer) { diff --git a/xbmc/linux/Makefile.in b/xbmc/linux/Makefile.in index 8dae7d43cf..c3a5877fdd 100644 --- a/xbmc/linux/Makefile.in +++ b/xbmc/linux/Makefile.in @@ -10,7 +10,6 @@ SRCS=ConvUtils.cpp \ LinuxResourceCounter.cpp \ LinuxTimezone.cpp \ PosixMountProvider.cpp \ - XCriticalSection.cpp \ XEventUtils.cpp \ XFileUtils.cpp \ XHandle.cpp \ diff --git a/xbmc/threads/CriticalSection.cpp b/xbmc/threads/CriticalSection.cpp deleted file mode 100644 index 5e5374e2d7..0000000000 --- a/xbmc/threads/CriticalSection.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* -* XBMC Media Center -* Copyright (c) 2002 Frodo -* Portions Copyright (c) by the authors of ffmpeg and xvid -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "CriticalSection.h" - -////////////////////////////////////////////////////////////////////// -CCriticalSection::CCriticalSection() -{ - m_criticalSection.Initialize(); -} - -////////////////////////////////////////////////////////////////////// -CCriticalSection::~CCriticalSection() -{ - m_criticalSection.Destroy(); -} - -// The C API. -void InitializeCriticalSection(CCriticalSection* section) { section->getCriticalSection().Initialize(); } -void DeleteCriticalSection(CCriticalSection* section) { section->getCriticalSection().Destroy(); } -BOOL OwningCriticalSection(CCriticalSection* section) { return section->getCriticalSection().Owning(); } -DWORD ExitCriticalSection(CCriticalSection* section) { return section->getCriticalSection().Exit(); } -void RestoreCriticalSection(CCriticalSection* section, DWORD count) { return section->getCriticalSection().Restore(count); } -void EnterCriticalSection(CCriticalSection* section) { section->getCriticalSection().Enter(); } -void LeaveCriticalSection(CCriticalSection* section) { section->getCriticalSection().Leave(); } - -void EnterCriticalSection(CCriticalSection& section) { section.getCriticalSection().Enter(); } -void LeaveCriticalSection(CCriticalSection& section) { section.getCriticalSection().Leave(); } -BOOL OwningCriticalSection(CCriticalSection& section) { return section.getCriticalSection().Owning(); } -DWORD ExitCriticalSection(CCriticalSection& section) { return section.getCriticalSection().Exit(); } -void RestoreCriticalSection(CCriticalSection& section, DWORD count) { return section.getCriticalSection().Restore(count); } - diff --git a/xbmc/threads/CriticalSection.h b/xbmc/threads/CriticalSection.h index a574b85cc3..da7c8867ae 100644 --- a/xbmc/threads/CriticalSection.h +++ b/xbmc/threads/CriticalSection.h @@ -3,19 +3,8 @@ // CriticalSection.h: interface for the CCriticalSection class. // ////////////////////////////////////////////////////////////////////// -#ifndef _CRITICAL_SECTION_H_ -#define _CRITICAL_SECTION_H_ -#if _MSC_VER > 1000 #pragma once -#endif // _MSC_VER > 1000 -#ifdef _LINUX -#include "PlatformDefs.h" -#include "linux/XSyncUtils.h" -#include "XCriticalSection.h" -#else -#include "win32/XCriticalSection.h" -#endif /* * Copyright (C) 2005-2008 Team XBMC @@ -38,37 +27,78 @@ * */ -class CCriticalSection +#include <boost/thread/recursive_mutex.hpp> + +/** + * Because there are several different Lockable schemes we use, this + * template extends the boost behavior and adds some xbmc assumptions + * mainly that a CriticalSection (or SharedSection) is "exitable." + * + * "Exitable" specifially means that, no matter how deep the recursion + * on the mutex/critical section, we can exit from it and then restore + * the state. + * + * This requires us to extend boost so that we can keep track of the + * number of locks that have been recursively acquired so that we can + * undo it, and then restore that (See class CSingleExit). + * + * This implements boost's "Lockable concept" which simply means that + * it has the three methods: + * + * lock(); + * try_lock(); + * unlock(); + */ +template<class L> class CountingLockable { +protected: + L m; + unsigned int count; + public: - // Constructor/destructor. - CCriticalSection(); - virtual ~CCriticalSection(); + inline CountingLockable() : count(0) {} - XCriticalSection& getCriticalSection() { return m_criticalSection; } + // boost::thread Lockable concept + inline void lock() { m.lock(); count++; } + inline bool try_lock() { return m.try_lock() ? count++, true : false; } + inline void unlock() { count--; m.unlock(); } -private: - XCriticalSection m_criticalSection; + /** + * This implements the "exitable" behavior mentioned above. + */ + inline unsigned int exit() + { + // it's possibe we don't actually own the lock + // so we will try it. + unsigned int ret = count; + if (try_lock()) + { + unlock(); // unlock the try_lock + for (unsigned int i = 0; i < ret; i++) + unlock(); + } + else + ret = 0; - //don't allow copying a CCriticalSection - CCriticalSection(const CCriticalSection& section) {} - CCriticalSection& operator=(const CCriticalSection& section) {return *this;} -}; + return ret; + } -// The CCritical section overloads. -void InitializeCriticalSection(CCriticalSection* section); -void DeleteCriticalSection(CCriticalSection* section); -BOOL OwningCriticalSection(CCriticalSection* section); -DWORD ExitCriticalSection(CCriticalSection* section); -void RestoreCriticalSection(CCriticalSection* section, DWORD count); -void EnterCriticalSection(CCriticalSection* section); -void LeaveCriticalSection(CCriticalSection* section); + /** + * Restore a previous exit to the provided level. + */ + inline void restore(unsigned int restoreCount) + { + for (unsigned int i = 0; i < restoreCount; i++) + lock(); + } +}; -// And a few special ones. -void EnterCriticalSection(CCriticalSection& section); -void LeaveCriticalSection(CCriticalSection& section); -BOOL OwningCriticalSection(CCriticalSection& section); -DWORD ExitCriticalSection(CCriticalSection& section); -void RestoreCriticalSection(CCriticalSection& section, DWORD count); +/** + * A CCriticalSection is a CountingLockable whose implementation is a boost + * recursive_mutex. + * + * This is not a typedef because of a number of "class CCriticalSection;" + * forward declarations in the code that break when it's done that way. + */ +class CCriticalSection : public CountingLockable<boost::recursive_mutex> {}; -#endif diff --git a/xbmc/threads/Makefile b/xbmc/threads/Makefile index 7c6a22d4e8..bf64ddb51a 100644 --- a/xbmc/threads/Makefile +++ b/xbmc/threads/Makefile @@ -1,11 +1,8 @@ SRCS=Atomics.cpp \ - CriticalSection.cpp \ Event.cpp \ - LockFree.cpp \ Mutex.cpp \ + LockFree.cpp \ Semaphore.cpp \ - SharedSection.cpp \ - SingleLock.cpp \ Thread.cpp \ XBMC_mutex.cpp \ diff --git a/xbmc/threads/SharedSection.cpp b/xbmc/threads/SharedSection.cpp deleted file mode 100644 index b82b4d1e44..0000000000 --- a/xbmc/threads/SharedSection.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2005-2008 Team XBMC - * http://www.xbmc.org - * - * This Program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This Program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBMC; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * http://www.gnu.org/copyleft/gpl.html - * - */ - -#include "SharedSection.h" - -#define MAXSHAREDACCESSES 5000 - -CSharedSection::CSharedSection() -{ - m_sharedLock = 0; - m_exclusive = false; - InitializeCriticalSection(&m_critSection); - m_eventFree = CreateEvent(NULL, TRUE, FALSE, NULL); -} - -CSharedSection::~CSharedSection() -{ - DeleteCriticalSection(&m_critSection); - CloseHandle(m_eventFree); -} - -void CSharedSection::EnterShared() -{ - EnterCriticalSection(&m_critSection); - ResetEvent(m_eventFree); - m_sharedLock++; - LeaveCriticalSection(&m_critSection); -} - -void CSharedSection::LeaveShared() -{ - EnterCriticalSection(&m_critSection); - m_sharedLock--; - if (m_sharedLock == 0) - { - LeaveCriticalSection(&m_critSection); - SetEvent(m_eventFree); - return; - } - LeaveCriticalSection(&m_critSection); -} - -void CSharedSection::EnterExclusive() -{ - EnterCriticalSection(&m_critSection); - while( m_sharedLock != 0 ) - { - LeaveCriticalSection(&m_critSection); - WaitForSingleObject(m_eventFree, INFINITE); - EnterCriticalSection(&m_critSection); - } - - m_exclusive = true; -} - -void CSharedSection::LeaveExclusive() -{ - m_exclusive = false; - LeaveCriticalSection(&m_critSection); -} - -////////////////////////////////////////////////////////////////////// -// SharedLock -////////////////////////////////////////////////////////////////////// - -CSharedLock::CSharedLock(CSharedSection& cs) - : m_cs( cs ) - , m_bIsOwner( false ) -{ - Enter(); -} - -CSharedLock::CSharedLock(const CSharedSection& cs) - : m_cs( const_cast<CSharedSection&>(cs) ) - , m_bIsOwner( false ) -{ - Enter(); -} - -CSharedLock::~CSharedLock() -{ - Leave(); -} - -bool CSharedLock::IsOwner() const -{ - return m_bIsOwner; -} - -bool CSharedLock::Enter() -{ - // Test if we already own the critical section - if ( true == m_bIsOwner ) - { - return true; - } - - // Blocking call - m_cs.EnterShared(); - m_bIsOwner = true; - - return m_bIsOwner; -} - -void CSharedLock::Leave() -{ - if ( false == m_bIsOwner ) - { - return ; - } - - m_cs.LeaveShared(); - m_bIsOwner = false; -} - -////////////////////////////////////////////////////////////////////// -// ExclusiveLock -////////////////////////////////////////////////////////////////////// - -CExclusiveLock::CExclusiveLock(CSharedSection& cs) - : m_cs( cs ) - , m_bIsOwner( false ) -{ - Enter(); -} - -CExclusiveLock::CExclusiveLock(const CSharedSection& cs) - : m_cs( const_cast<CSharedSection&>(cs) ) - , m_bIsOwner( false ) -{ - Enter(); -} - -CExclusiveLock::~CExclusiveLock() -{ - Leave(); -} - -bool CExclusiveLock::IsOwner() const -{ - return m_bIsOwner; -} - -bool CExclusiveLock::Enter() -{ - // Test if we already own the critical section - if ( true == m_bIsOwner ) - { - return true; - } - - // Blocking call - m_cs.EnterExclusive(); - m_bIsOwner = true; - - return m_bIsOwner; -} - -void CExclusiveLock::Leave() -{ - if ( false == m_bIsOwner ) - { - return ; - } - - m_cs.LeaveExclusive(); - m_bIsOwner = false; -} - diff --git a/xbmc/threads/SharedSection.h b/xbmc/threads/SharedSection.h index 1d7cd03dc0..ef7e44e441 100644 --- a/xbmc/threads/SharedSection.h +++ b/xbmc/threads/SharedSection.h @@ -21,71 +21,48 @@ * */ -#include "system.h" // for HANDLE, CRITICALSECTION +#include "threads/CriticalSection.h" +#include <boost/thread/shared_mutex.hpp> -class CSharedSection +/** + * A CSharedSection is a CountingLockable whose implementation is a boost + * shared_mutex. + * + * It implemented boost's shared Locakable concept which requires the + * additional implementation of: + * + * lock_shared() + * try_lock_shared() + * unlock_shared() + */ +class CSharedSection : public CountingLockable<boost::shared_mutex> { - public: - CSharedSection(); - CSharedSection(const CSharedSection& src); - CSharedSection& operator=(const CSharedSection& src); - virtual ~CSharedSection(); - - void EnterExclusive(); - void LeaveExclusive(); - - void EnterShared(); - void LeaveShared(); -private: - - CRITICAL_SECTION m_critSection; - - HANDLE m_eventFree; - bool m_exclusive; - long m_sharedLock; + inline void lock_shared() { m.lock_shared(); } + inline bool try_lock_shared() { return m.try_lock_shared(); } + inline void unlock_shared() { return m.unlock_shared(); } }; -class CSharedLock +class CSharedLock : public boost::shared_lock<CSharedSection> { public: - CSharedLock(CSharedSection& cs); - CSharedLock(const CSharedSection& cs); - virtual ~CSharedLock(); - - bool IsOwner() const; - bool Enter(); - void Leave(); + inline CSharedLock(CSharedSection& cs) : boost::shared_lock<CSharedSection>(cs) {} + inline CSharedLock(const CSharedSection& cs) : boost::shared_lock<CSharedSection>((CSharedSection&)cs) {} -protected: - CSharedLock(const CSharedLock& src); - CSharedLock& operator=(const CSharedLock& src); - - // Reference to critical section object - CSharedSection& m_cs; - // Ownership flag - bool m_bIsOwner; + inline bool IsOwner() const { return owns_lock(); } + inline void Enter() { lock(); } + inline void Leave() { unlock(); } }; -class CExclusiveLock +class CExclusiveLock : public boost::unique_lock<CSharedSection> { public: - CExclusiveLock(CSharedSection& cs); - CExclusiveLock(const CSharedSection& cs); - virtual ~CExclusiveLock(); - - bool IsOwner() const; - bool Enter(); - void Leave(); - -protected: - CExclusiveLock(const CExclusiveLock& src); - CExclusiveLock& operator=(const CExclusiveLock& src); + inline CExclusiveLock(CSharedSection& cs) : boost::unique_lock<CSharedSection>(cs) {} + inline CExclusiveLock(const CSharedSection& cs) : boost::unique_lock<CSharedSection> ((CSharedSection&)cs) {} - // Reference to critical section object - CSharedSection& m_cs; - // Ownership flag - bool m_bIsOwner; + inline bool IsOwner() const { return owns_lock(); } + inline void Leave() { unlock(); } + inline void Enter() { lock(); } }; diff --git a/xbmc/threads/SingleLock.cpp b/xbmc/threads/SingleLock.cpp deleted file mode 100644 index d07f8b8718..0000000000 --- a/xbmc/threads/SingleLock.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * XBMC Media Center - * Copyright (c) 2002 Frodo - * Portions Copyright (c) by the authors of ffmpeg and xvid - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "SingleLock.h" - - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -CSingleLock::CSingleLock(CCriticalSection& cs) - : m_cs( cs ) - , m_bIsOwner( false ) -{ - Enter(); -} - -CSingleLock::CSingleLock(const CCriticalSection& cs) - : m_cs( const_cast<CCriticalSection&>(cs) ) - , m_bIsOwner( false ) -{ - Enter(); -} - -CSingleLock::~CSingleLock() -{ - Leave(); -} - -bool CSingleLock::IsOwner() const -{ - return m_bIsOwner; -} - -bool CSingleLock::Enter() -{ - // Test if we already own the critical section - if ( true == m_bIsOwner ) - { - return true; - } - - // Blocking call - ::EnterCriticalSection( m_cs ); - m_bIsOwner = true; - - return m_bIsOwner; -} - -void CSingleLock::Leave() -{ - if ( false == m_bIsOwner ) - { - return ; - } - - ::LeaveCriticalSection( m_cs ); - m_bIsOwner = false; -} - -CSingleExit::CSingleExit(CCriticalSection& cs) - : m_cs( cs ) - , m_count(0) -{ - Exit(); -} - - CSingleExit::CSingleExit(const CCriticalSection& cs) - : m_cs(const_cast<CCriticalSection&>(cs)) - , m_count(0) -{ - Exit(); -} - -CSingleExit::~CSingleExit() -{ - Restore(); -} - -void CSingleExit::Exit() -{ - if(m_count == 0) - m_count = ::ExitCriticalSection(m_cs); -} - -void CSingleExit::Restore() -{ - if(m_count) - { - RestoreCriticalSection(m_cs, m_count); - m_count = 0; - } -} - - diff --git a/xbmc/threads/SingleLock.h b/xbmc/threads/SingleLock.h index f222f2bf3f..cda2558909 100644 --- a/xbmc/threads/SingleLock.h +++ b/xbmc/threads/SingleLock.h @@ -2,13 +2,6 @@ // ////////////////////////////////////////////////////////////////////// -#if !defined(AFX_SINGLELOCK_H__50A43114_6A71_4FBD_BF51_D1F2DD3A60FA__INCLUDED_) -#define AFX_SINGLELOCK_H__50A43114_6A71_4FBD_BF51_D1F2DD3A60FA__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - /* * XBMC Media Center * Copyright (c) 2002 Frodo @@ -29,40 +22,54 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#pragma once + +#include <boost/thread/locks.hpp> #include "CriticalSection.h" -class CSingleLock + +/** + * This implements a "guard" pattern for a CCriticalSection that + * borrows most of it's functionality from boost's unique_lock. + */ +class CSingleLock : public boost::unique_lock<CCriticalSection> { public: - CSingleLock(CCriticalSection& cs); - CSingleLock(const CCriticalSection& cs); - virtual ~CSingleLock(); + inline CSingleLock(CCriticalSection& cs) : boost::unique_lock<CCriticalSection>(cs) {} + inline CSingleLock(const CCriticalSection& cs) : boost::unique_lock<CCriticalSection> ((CCriticalSection&)cs) {} - bool IsOwner() const; - bool Enter(); - void Leave(); + inline void Leave() { unlock(); } + inline void Enter() { lock(); } +protected: + inline CSingleLock(CCriticalSection& cs, bool dicrim) : boost::unique_lock<CCriticalSection>(cs,boost::try_to_lock) {} +}; -private: - CSingleLock(const CSingleLock& src); - CSingleLock& operator=(const CSingleLock& src); +/** + * This implements a "guard" pattern for a CCriticalSection that + * works like a CSingleLock but only "try"s the lock and so + * it's possible it doesn't actually get it.. + */ +class CSingleTryLock : public CSingleLock +{ +public: + CSingleTryLock(CCriticalSection& cs) : CSingleLock(cs,true) {} - // Reference to critical section object - CCriticalSection& m_cs; - // Ownership flag - bool m_bIsOwner; + inline bool IsOwner() const { return owns_lock(); } }; +/** + * This implements a "guard" pattern for exiting all locks + * currently being held by the current thread and restoring + * those locks on destruction. + * + * This class can be used on a CCriticalSection that isn't owned + * by this thread in which case it will do nothing. + */ class CSingleExit { + CCriticalSection& sec; + unsigned int count; public: - CSingleExit(CCriticalSection& cs); - CSingleExit(const CCriticalSection& cs); - virtual ~CSingleExit(); - - void Exit(); - void Restore(); - - CCriticalSection& m_cs; - unsigned int m_count; + inline CSingleExit(CCriticalSection& cs) : sec(cs), count(cs.exit()) { } + inline ~CSingleExit() { sec.restore(count); } }; -#endif // !defined(AFX_SINGLELOCK_H__50A43114_6A71_4FBD_BF51_D1F2DD3A60FA__INCLUDED_) |