blob: c517d234bc35fc0e570afe1c6b1a83057292a3a0 [file] [log] [blame]
// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Implementation of threading classes using Linux pthreads.
// Also works under Native Client.
#include "threading.h"
#include <pthread.h>
#include <sys/time.h>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "log.h"
namespace speech_synthesis {
namespace {
// Implementation of a Mutex using pthreads
class PthreadMutex : public Mutex {
public:
PthreadMutex() {
pthread_mutex_init(&mutex_, NULL);
}
virtual ~PthreadMutex() {
pthread_mutex_destroy(&mutex_);
}
// Mutex overrides:
virtual void Lock() OVERRIDE {
pthread_mutex_lock(&mutex_);
}
virtual void Unlock() OVERRIDE {
pthread_mutex_unlock(&mutex_);
}
private:
pthread_mutex_t mutex_;
friend class PthreadCondVar;
DISALLOW_COPY_AND_ASSIGN(PthreadMutex);
};
class PthreadCondVar : public CondVar {
public:
PthreadCondVar() {
pthread_cond_init(&cond_var_, NULL);
}
virtual ~PthreadCondVar() {
pthread_cond_destroy(&cond_var_);
}
// CondVar overrides:
virtual void Wait(Mutex* mutex) OVERRIDE {
pthread_cond_wait(&cond_var_, &(static_cast<PthreadMutex*>(mutex))->mutex_);
}
virtual void WaitWithTimeout(Mutex* mutex, int timeout_ms) OVERRIDE {
struct timeval now;
struct timespec timeout;
int future_us;
gettimeofday(&now, NULL);
future_us = now.tv_usec + timeout_ms * 1000;
timeout.tv_nsec = (future_us % 1000000) * 1000;
timeout.tv_sec = now.tv_sec + future_us / 1000000;
pthread_cond_timedwait(&cond_var_,
&(static_cast<PthreadMutex*>(mutex))->mutex_,
&timeout);
}
virtual void Signal() OVERRIDE {
pthread_cond_signal(&cond_var_);
}
private:
pthread_cond_t cond_var_;
DISALLOW_COPY_AND_ASSIGN(PthreadCondVar);
};
// Implementation of a joinable Thread using Pthread's Thread class
class PthreadThread : public Thread {
public:
explicit PthreadThread(pthread_t *thread)
: thread_(thread) { }
virtual ~PthreadThread() {
CHECK(thread_ == NULL);
}
// Thread override.
virtual void Join() OVERRIDE {
pthread_join(*thread_, NULL);
delete thread_;
thread_ = NULL;
}
private:
pthread_t* thread_;
DISALLOW_COPY_AND_ASSIGN(PthreadThread);
};
void* ThreadStart(void *userdata) {
Runnable *action = static_cast<Runnable *>(userdata);
action->Run();
return NULL;
}
} // namespace
// static
Mutex* Mutex::Create() {
return new PthreadMutex();
}
// static
CondVar* CondVar::Create() {
return new PthreadCondVar();
}
// static
Thread* Thread::StartJoinableThread(Runnable *action) {
pthread_t* thread = new pthread_t;
pthread_create(thread, NULL, ThreadStart, action);
return new PthreadThread(thread);
}
} // namespace speech_synthesis