00001 #include <math.h>
00002 #include <unistd.h>
00003 #include <pthread.h>
00004 #include <sys/time.h>
00005 #include "threads.h"
00006 #include "utility.h"
00007
00008
00009 namespace audiere {
00010
00011 struct ThreadInternal {
00012 AI_ThreadRoutine routine;
00013 void* opaque;
00014 };
00015
00016
00017 void* ThreadRoutine(void* arg) {
00018 ThreadInternal* ti = (ThreadInternal*)arg;
00019 ti->routine(ti->opaque);
00020 delete ti;
00021 return NULL;
00022 }
00023
00024
00025 bool AI_CreateThread(AI_ThreadRoutine routine, void* opaque, int priority) {
00026 ThreadInternal* ti = new ThreadInternal;
00027 ti->routine = routine;
00028 ti->opaque = opaque;
00029
00030 pthread_attr_t attr;
00031 if (pthread_attr_init(&attr)) {
00032 delete ti;
00033 return false;
00034 }
00035
00036
00037 int policy;
00038 if (pthread_attr_getschedpolicy(&attr, &policy)) {
00039 pthread_attr_destroy(&attr);
00040 delete ti;
00041 return false;
00042 }
00043
00044 int min_prio = sched_get_priority_min(policy);
00045 int max_prio = sched_get_priority_max(policy);
00046
00047
00048 sched_param sched;
00049 if (pthread_attr_getschedparam(&attr, &sched)) {
00050 pthread_attr_destroy(&attr);
00051 delete ti;
00052 return false;
00053 }
00054
00055
00056 sched.sched_priority = clamp(
00057 min_prio,
00058 sched.sched_priority + priority,
00059 max_prio);
00060
00061 if (pthread_attr_setschedparam(&attr, &sched)) {
00062 pthread_attr_destroy(&attr);
00063 delete ti;
00064 return false;
00065 }
00066
00067 pthread_t thread;
00068 int result = pthread_create(&thread, &attr, ThreadRoutine, ti);
00069 if (result != 0) {
00070 pthread_attr_destroy(&attr);
00071 delete ti;
00072 return false;
00073 }
00074
00075 pthread_attr_destroy(&attr);
00076 return true;
00077 }
00078
00079
00080 void AI_Sleep(unsigned milliseconds) {
00081 int seconds = milliseconds / 1000;
00082 int useconds = (milliseconds % 1000) * 1000;
00083
00084 sleep(seconds);
00085 usleep(useconds);
00086 }
00087
00088
00089 struct Mutex::Impl {
00090 pthread_mutex_t mutex;
00091 };
00092
00093 Mutex::Mutex() {
00094 m_impl = new Impl;
00095 int result = pthread_mutex_init(&m_impl->mutex, 0);
00096 if (result != 0) {
00097 delete m_impl;
00098 m_impl = 0;
00099 ADR_LOG("pthread_mutex_init() failed in Mutex::Mutex()");
00100 abort();
00101 }
00102 }
00103
00104 Mutex::~Mutex() {
00105 pthread_mutex_destroy(&m_impl->mutex);
00106 delete m_impl;
00107 }
00108
00109 void Mutex::lock() {
00110 pthread_mutex_lock(&m_impl->mutex);
00111 }
00112
00113 void Mutex::unlock() {
00114 pthread_mutex_unlock(&m_impl->mutex);
00115 }
00116
00117
00118 struct CondVar::Impl {
00119 pthread_cond_t cond;
00120 };
00121
00122 CondVar::CondVar() {
00123 m_impl = new Impl;
00124 int result = pthread_cond_init(&m_impl->cond, 0);
00125 if (result != 0) {
00126 delete m_impl;
00127 m_impl = 0;
00128 ADR_LOG("pthread_cond_init() failed in CondVar::CondVar()");
00129 abort();
00130 }
00131 }
00132
00133 CondVar::~CondVar() {
00134 pthread_cond_destroy(&m_impl->cond);
00135 delete m_impl;
00136 }
00137
00138 void CondVar::wait(Mutex& mutex, float seconds) {
00139 double ds = seconds;
00140
00141 timeval tv;
00142 gettimeofday(&tv, 0);
00143 ds += tv.tv_sec + tv.tv_usec / 1000000000.0;
00144
00145 timespec ts;
00146 ts.tv_sec = int(ds);
00147 ts.tv_nsec = int((ds - floor(ds)) * 1000000000);
00148 pthread_cond_timedwait(&m_impl->cond, &mutex.m_impl->mutex, &ts);
00149 }
00150
00151 void CondVar::notify() {
00152 pthread_cond_signal(&m_impl->cond);
00153 }
00154
00155 }