blob: 8d3ce0573a3f9fec8650def1c669b9f1ce2c6e69 [file] [log] [blame]
#ifndef ANDROID_THREADS_H_
#define ANDROID_THREADS_H_
#include <media/stagefright/foundation/ABase.h>
#include <media/stagefright/foundation/ADebug.h>
#include <sys/time.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <pthread.h>
namespace android {
struct Thread : public RefBase {
Thread()
: mThread(0)
{
}
status_t run(const char *name) {
if (mThread != 0) {
return INVALID_OPERATION;
}
mName = name;
mExitRequested = false;
int res = pthread_create(&mThread, NULL, &Thread::ThreadWrapper, this);
if (res != 0) {
mThread = 0;
return -errno;
}
return OK;
}
void requestExit() { mExitRequested = true; }
void requestExitAndWait() {
requestExit();
void *dummy;
pthread_join(mThread, &dummy);
mThread = 0;
}
protected:
virtual bool threadLoop() = 0;
~Thread() {
if (mThread) {
requestExitAndWait();
CHECK(!mThread);
}
}
private:
pthread_t mThread;
volatile bool mExitRequested;
std::string mName;
static void *ThreadWrapper(void *param) {
Thread *me = static_cast<Thread *>(param);
while (!me->mExitRequested) {
if (!me->threadLoop()) {
break;
}
}
return NULL;
}
DISALLOW_EVIL_CONSTRUCTORS(Thread);
};
struct Mutex {
Mutex() {
CHECK_EQ(pthread_mutex_init(&mMutex, NULL), 0);
}
~Mutex() {
CHECK_EQ(pthread_mutex_destroy(&mMutex), 0);
}
void lock() {
CHECK_EQ(pthread_mutex_lock(&mMutex), 0);
}
void unlock() {
CHECK_EQ(pthread_mutex_unlock(&mMutex), 0);
}
struct Autolock;
private:
friend struct Condition;
pthread_mutex_t mMutex;
DISALLOW_EVIL_CONSTRUCTORS(Mutex);
};
struct Mutex::Autolock {
Autolock(Mutex &mutex)
: mMutex(mutex) {
mMutex.lock();
}
~Autolock() {
mMutex.unlock();
}
private:
Mutex &mMutex;
DISALLOW_EVIL_CONSTRUCTORS(Autolock);
};
struct Condition {
Condition() {
CHECK_EQ(pthread_cond_init(&mCond, NULL), 0);
}
~Condition() {
CHECK_EQ(pthread_cond_destroy(&mCond), 0);
}
void signal() {
CHECK_EQ(pthread_cond_signal(&mCond), 0);
}
void broadcast() {
CHECK_EQ(pthread_cond_broadcast(&mCond), 0);
}
status_t wait(Mutex &mutex) {
int res = pthread_cond_wait(&mCond, &mutex.mMutex);
return res == 0 ? OK : -errno;
}
status_t waitRelative(Mutex &mutex, int64_t nsecs) {
struct timeval tv;
gettimeofday(&tv, NULL);
struct timespec abstime;
abstime.tv_sec = tv.tv_sec;
abstime.tv_nsec = tv.tv_usec * 1000ll + nsecs;
int res = pthread_cond_timedwait(&mCond, &mutex.mMutex, &abstime);
if (res == 0) {
return OK;
}
return -errno;
}
private:
pthread_cond_t mCond;
DISALLOW_EVIL_CONSTRUCTORS(Condition);
};
} // namespace android
#endif // ANDROID_THREADS_H_