blob: 9a12f6e8e03496cd3c4475fcce99deb7e347338e [file] [log] [blame]
//===-- PThreadMutex.h ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Created by Greg Clayton on 6/16/07.
//
//===----------------------------------------------------------------------===//
#ifndef __PThreadMutex_h__
#define __PThreadMutex_h__
#include <pthread.h>
#include <assert.h>
#include <stdint.h>
//#define DEBUG_PTHREAD_MUTEX_DEADLOCKS 1
#if defined (DEBUG_PTHREAD_MUTEX_DEADLOCKS)
#define PTHREAD_MUTEX_LOCKER(var, mutex) PThreadMutex::Locker var(mutex, __FUNCTION__, __FILE__, __LINE__)
#else
#define PTHREAD_MUTEX_LOCKER(var, mutex) PThreadMutex::Locker var(mutex)
#endif
class PThreadMutex
{
public:
class Locker
{
public:
#if defined (DEBUG_PTHREAD_MUTEX_DEADLOCKS)
Locker(PThreadMutex& m, const char *function, const char *file, int line);
Locker(PThreadMutex* m, const char *function, const char *file, int line);
Locker(pthread_mutex_t *mutex, const char *function, const char *file, int line);
~Locker();
void Lock();
void Unlock();
#else
Locker(PThreadMutex& m) :
m_pMutex(m.Mutex())
{
Lock();
}
Locker(PThreadMutex* m) :
m_pMutex(m ? m->Mutex() : NULL)
{
Lock();
}
Locker(pthread_mutex_t *mutex) :
m_pMutex(mutex)
{
Lock();
}
void Lock()
{
if (m_pMutex)
::pthread_mutex_lock (m_pMutex);
}
void Unlock()
{
if (m_pMutex)
::pthread_mutex_unlock (m_pMutex);
}
~Locker()
{
Unlock();
}
#endif
// unlock any the current mutex and lock the new one if it is valid
void Reset(pthread_mutex_t *pMutex = NULL)
{
Unlock();
m_pMutex = pMutex;
Lock();
}
pthread_mutex_t *m_pMutex;
#if defined (DEBUG_PTHREAD_MUTEX_DEADLOCKS)
const char *m_function;
const char *m_file;
int m_line;
uint64_t m_lock_time;
#endif
};
PThreadMutex()
{
int err;
err = ::pthread_mutex_init (&m_mutex, NULL); assert(err == 0);
}
PThreadMutex(int type)
{
int err;
::pthread_mutexattr_t attr;
err = ::pthread_mutexattr_init (&attr); assert(err == 0);
err = ::pthread_mutexattr_settype (&attr, type); assert(err == 0);
err = ::pthread_mutex_init (&m_mutex, &attr); assert(err == 0);
err = ::pthread_mutexattr_destroy (&attr); assert(err == 0);
}
~PThreadMutex()
{
int err;
err = ::pthread_mutex_destroy (&m_mutex);
if (err != 0)
{
err = Unlock();
if (err == 0)
::pthread_mutex_destroy (&m_mutex);
}
}
pthread_mutex_t *Mutex()
{
return &m_mutex;
}
int Lock()
{
return ::pthread_mutex_lock (&m_mutex);
}
int Unlock()
{
return ::pthread_mutex_unlock (&m_mutex);
}
protected:
pthread_mutex_t m_mutex;
};
#endif