diff options
Diffstat (limited to 'client/threads.cpp')
-rw-r--r-- | client/threads.cpp | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/client/threads.cpp b/client/threads.cpp new file mode 100644 index 00000000..20774f3a --- /dev/null +++ b/client/threads.cpp @@ -0,0 +1,125 @@ +/* + Copyright (C) 2009 Red Hat, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "common.h" +#include "threads.h" +#include "utils.h" +#include "debug.h" +#ifdef WIN32 +#include <sys/timeb.h> +#endif + +Thread::Thread(thread_main_t thread_main, void* opaque) +{ + int r = pthread_create(&_thread, NULL, thread_main, opaque); + if (r) { + THROW("failed %d", r); + } +} + +void Thread::join() +{ + pthread_join(_thread, NULL); +} + +static inline void rel_time(struct timespec& time, uint64_t delta_nano) +{ +#ifdef WIN32 + struct _timeb now; + _ftime_s(&now); + time.tv_sec = now.time; + time.tv_nsec = now.millitm * 1000 * 1000; +#else + clock_gettime(CLOCK_MONOTONIC, &time); +#endif + delta_nano += (uint64_t)time.tv_sec * 1000 * 1000 * 1000; + delta_nano += time.tv_nsec; + time.tv_sec = long(delta_nano / (1000 * 1000 * 1000)); + time.tv_nsec = long(delta_nano % (1000 * 1000 * 1000)); +} + +void Lock::timed_lock(uint64_t timout_nano) +{ + struct timespec time; + int r; + + rel_time(time, timout_nano); + if ((r = pthread_mutex_timedlock(_mutex.get(), &time))) { + _locked = false; + if (r != ETIMEDOUT) { + THROW("failed %d", r); + } + return; + } + _locked = true; +} + +Condition::Condition() +{ +#ifdef WIN32 + pthread_cond_init(&_condition, NULL); +#else + pthread_condattr_t attr; + pthread_condattr_init(&attr); + int r; + if ((r = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC))) { + THROW("set clock failed %d", r); + } + pthread_cond_init(&_condition, &attr); + pthread_condattr_destroy(&attr); +#endif +} + +bool Condition::timed_wait(Lock& lock, uint64_t nano) +{ + struct timespec time; + rel_time(time, nano); + int r = pthread_cond_timedwait(&_condition, lock.get(), &time); + if (r) { + if (r != ETIMEDOUT) { + THROW("failed %d", r); + } + return false; + } + return true; +} + +Mutex::Mutex(Type type) +{ + pthread_mutexattr_t attr; + + pthread_mutexattr_init(&attr); + if (type == NORMAL) { + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + } else if (type == RECURSIVE) { + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + } else { + THROW("invalid type %d", type); + } + + int r; + if ((r = pthread_mutex_init(&_mutex, &attr))) { + THROW("int failed %d", r); + } + pthread_mutexattr_destroy(&attr); +} + +Mutex::~Mutex() +{ + pthread_mutex_destroy(&_mutex); +} + |