Add AMTL files
This commit is contained in:
213
public/amtl/am-thread-posix.h
Normal file
213
public/amtl/am-thread-posix.h
Normal file
@@ -0,0 +1,213 @@
|
||||
// vim: set sts=8 ts=2 sw=2 tw=99 et:
|
||||
//
|
||||
// Copyright (C) 2013, David Anderson and AlliedModders LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither the name of AlliedModders LLC nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef _include_amtl_thread_posix_h_
|
||||
#define _include_amtl_thread_posix_h_
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#if defined(__linux__)
|
||||
# include <sys/prctl.h>
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
# include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
namespace ke {
|
||||
|
||||
class Mutex : public Lockable
|
||||
{
|
||||
public:
|
||||
Mutex() {
|
||||
#if !defined(NDEBUG)
|
||||
int rv =
|
||||
#endif
|
||||
pthread_mutex_init(&mutex_, NULL);
|
||||
assert(rv == 0);
|
||||
}
|
||||
~Mutex() {
|
||||
pthread_mutex_destroy(&mutex_);
|
||||
}
|
||||
|
||||
bool DoTryLock() KE_OVERRIDE {
|
||||
return pthread_mutex_trylock(&mutex_) == 0;
|
||||
}
|
||||
|
||||
void DoLock() KE_OVERRIDE {
|
||||
pthread_mutex_lock(&mutex_);
|
||||
}
|
||||
|
||||
void DoUnlock() KE_OVERRIDE {
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
}
|
||||
|
||||
pthread_mutex_t *raw() {
|
||||
return &mutex_;
|
||||
}
|
||||
|
||||
private:
|
||||
pthread_mutex_t mutex_;
|
||||
};
|
||||
|
||||
// Currently, this class only supports single-listener CVs.
|
||||
class ConditionVariable : public Lockable
|
||||
{
|
||||
public:
|
||||
ConditionVariable() {
|
||||
#if !defined(NDEBUG)
|
||||
int rv =
|
||||
#endif
|
||||
pthread_cond_init(&cv_, NULL);
|
||||
assert(rv == 0);
|
||||
}
|
||||
~ConditionVariable() {
|
||||
pthread_cond_destroy(&cv_);
|
||||
}
|
||||
|
||||
bool DoTryLock() KE_OVERRIDE {
|
||||
return mutex_.DoTryLock();
|
||||
}
|
||||
void DoLock() KE_OVERRIDE {
|
||||
mutex_.DoLock();
|
||||
}
|
||||
void DoUnlock() KE_OVERRIDE {
|
||||
mutex_.DoUnlock();
|
||||
}
|
||||
|
||||
void Notify() {
|
||||
AssertCurrentThreadOwns();
|
||||
pthread_cond_signal(&cv_);
|
||||
}
|
||||
|
||||
WaitResult Wait(size_t timeout_ms) {
|
||||
AssertCurrentThreadOwns();
|
||||
|
||||
#if defined(__linux__)
|
||||
struct timespec ts;
|
||||
if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
|
||||
return Wait_Error;
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
struct timespec ts;
|
||||
ts.tv_sec = tv.tv_sec;
|
||||
ts.tv_nsec = tv.tv_usec * 1000;
|
||||
#endif
|
||||
|
||||
ts.tv_sec += timeout_ms / 1000;
|
||||
ts.tv_nsec += (timeout_ms % 1000) * 1000000;
|
||||
if (ts.tv_nsec >= 1000000000) {
|
||||
ts.tv_sec++;
|
||||
ts.tv_nsec -= 1000000000;
|
||||
}
|
||||
|
||||
DebugSetUnlocked();
|
||||
int rv = pthread_cond_timedwait(&cv_, mutex_.raw(), &ts);
|
||||
DebugSetLocked();
|
||||
|
||||
if (rv == ETIMEDOUT)
|
||||
return Wait_Timeout;
|
||||
if (rv == 0)
|
||||
return Wait_Signaled;
|
||||
return Wait_Error;
|
||||
}
|
||||
|
||||
WaitResult Wait() {
|
||||
AssertCurrentThreadOwns();
|
||||
|
||||
DebugSetUnlocked();
|
||||
int rv = pthread_cond_wait(&cv_, mutex_.raw());
|
||||
DebugSetLocked();
|
||||
|
||||
if (rv == 0)
|
||||
return Wait_Signaled;
|
||||
return Wait_Error;
|
||||
}
|
||||
|
||||
private:
|
||||
Mutex mutex_;
|
||||
pthread_cond_t cv_;
|
||||
};
|
||||
|
||||
class Thread
|
||||
{
|
||||
struct ThreadData {
|
||||
IRunnable *run;
|
||||
char name[17];
|
||||
};
|
||||
public:
|
||||
Thread(IRunnable *run, const char *name = NULL) {
|
||||
ThreadData *data = new ThreadData;
|
||||
data->run = run;
|
||||
snprintf(data->name, sizeof(data->name), "%s", name ? name : "");
|
||||
|
||||
initialized_ = (pthread_create(&thread_, NULL, Main, data) == 0);
|
||||
if (!initialized_)
|
||||
delete data;
|
||||
}
|
||||
|
||||
bool Succeeded() const {
|
||||
return initialized_;
|
||||
}
|
||||
|
||||
void Join() {
|
||||
if (!Succeeded())
|
||||
return;
|
||||
pthread_join(thread_, NULL);
|
||||
}
|
||||
|
||||
private:
|
||||
static void *Main(void *arg) {
|
||||
AutoPtr<ThreadData> data((ThreadData *)arg);
|
||||
|
||||
if (data->name[0]) {
|
||||
#if defined(__linux__)
|
||||
prctl(PR_SET_NAME, (unsigned long)data->name);
|
||||
#elif defined(__APPLE__)
|
||||
int (*fn)(const char *) = (int (*)(const char *))dlsym(RTLD_DEFAULT, "pthread_setname_np");
|
||||
if (fn)
|
||||
fn(data->name);
|
||||
#endif
|
||||
}
|
||||
data->run->Run();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
bool initialized_;
|
||||
pthread_t thread_;
|
||||
};
|
||||
|
||||
} // namespace ke
|
||||
|
||||
#endif // _include_amtl_thread_posix_h_
|
||||
|
||||
Reference in New Issue
Block a user