1
1
forked from 0ad/0ad
0ad/source/ps/ThreadUtil.h
Ykkrosh c9fa7f13d9 Add GPL header
This was SVN commit r6830.
2009-04-18 17:00:33 +00:00

200 lines
4.1 KiB
C++

/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
/*
ThreadUtil.h - Thread Utility Functions
--Overview--
Contains three classes: CMutex, CRWLock and CLocker.
CMutex is a Mutual Exclusion lock that can be locked and unlocked. The Lock
function waits for the current lock holder (if any) to release the lock and
then acquires it.
CRWLock is a lock where any number of readers *or* one writer can hold the lock.
CLocker is a generic wrapper class that can wrap any data class with any locker
class.
--Example--
CMutex usage:
CMutex protectData;
void function()
{
protectData.Lock();
.. do stuff with data ..
protectData.Unlock();
}
CLocker usage:
class CDataClass {};
CLocker<CDataClass> instance;
void function()
{
instance.Lock();
.. do stuff with instance ..
instance.Unlock();
}
CLocker usage 2:
class CDataClass {};
class CCustomLockerClass { void MyOwnLock(); void MyOwnUnlock(); };
CLocker<CDataClass, CCustomLockerClass> instance;
void function()
{
instance.MyOwnLock();
.. do stuff with instance ..
instance.MyOwnUnlock();
}
--More Info--
*/
#ifndef _ThreadUtil_h
#define _ThreadUtil_h
//--------------------------------------------------------
// Includes / Compiler directives
//--------------------------------------------------------
#include "lib/posix/posix_pthread.h"
#ifdef DEBUG_LOCKS
#define LOCK_MUTEX(_mutex) STMT( \
printf("pthread_mutex_lock: 1 %p [pid:%d]\n", _mutex, pthread_self()); \
pthread_mutex_lock(_mutex); \
printf("pthread_mutex_lock: 2 %p [pid:%d]\n", _mutex, pthread_self()) \
)
#define UNLOCK_MUTEX(_mutex) STMT( \
pthread_mutex_unlock(_mutex); \
printf("pthread_mutex_unlock: %p [pid:%d]\n", _mutex, pthread_self()) \
)
#else
#define LOCK_MUTEX(_mutex) pthread_mutex_lock(_mutex)
#define UNLOCK_MUTEX(_mutex) pthread_mutex_unlock(_mutex)
#endif
//-------------------------------------------------
// Types
//-------------------------------------------------
//-------------------------------------------------
// Declarations
//-------------------------------------------------
/**
* A Mutual Exclusion lock.
*/
class CMutex
{
public:
inline CMutex()
{
pthread_mutex_init(&m_Mutex, NULL);
}
inline ~CMutex()
{
if (pthread_mutex_destroy(&m_Mutex) != 0)
{
Unlock();
pthread_mutex_destroy(&m_Mutex);
}
}
/**
* Atomically wait for the mutex to become unlocked, then lock it.
*/
inline void Lock()
{
LOCK_MUTEX(&m_Mutex);
}
/**
* Unlock the mutex.
*/
inline void Unlock()
{
UNLOCK_MUTEX(&m_Mutex);
}
pthread_mutex_t m_Mutex;
};
// CScopeLock
// ---------------------------------------------------------------------| Class
// Locks a CMutex over the objects lifetime
class CScopeLock
{
NONCOPYABLE(CScopeLock);
public:
inline CScopeLock(pthread_mutex_t &mutex): m_Mutex(mutex)
{
LOCK_MUTEX(&m_Mutex);
}
inline CScopeLock(CMutex &mutex): m_Mutex(mutex.m_Mutex)
{
LOCK_MUTEX(&m_Mutex);
}
inline ~CScopeLock()
{
UNLOCK_MUTEX(&m_Mutex);
}
private:
pthread_mutex_t &m_Mutex;
};
// CLocker
// ---------------------------------------------------------------------| Class
// This will not give access to the wrapped class constructors directly,
// to use them you have to do CLocker(CWrappedClass(args))
template <typename _T>
struct CLocker: public CMutex, public _T
{
public:
inline CLocker()
{}
/*
GCC doesn't take these... I don't understand what the problem is! // Simon
inline CLocker(const _T &arg): _T(arg)
{}
inline CLocker(_T &arg): _T(arg)
{}*/
};
#endif