diff options
Diffstat (limited to 'src/rt/sync')
| -rw-r--r-- | src/rt/sync/condition_variable.cpp | 28 | ||||
| -rw-r--r-- | src/rt/sync/condition_variable.h | 1 | ||||
| -rw-r--r-- | src/rt/sync/lock_free_queue.cpp | 4 | ||||
| -rw-r--r-- | src/rt/sync/lock_free_queue.h | 3 | ||||
| -rw-r--r-- | src/rt/sync/sync.cpp | 12 | ||||
| -rw-r--r-- | src/rt/sync/sync.h | 9 | ||||
| -rw-r--r-- | src/rt/sync/timer.cpp | 61 | ||||
| -rw-r--r-- | src/rt/sync/timer.h | 25 |
8 files changed, 138 insertions, 5 deletions
diff --git a/src/rt/sync/condition_variable.cpp b/src/rt/sync/condition_variable.cpp index d4032572..c34ab7f4 100644 --- a/src/rt/sync/condition_variable.cpp +++ b/src/rt/sync/condition_variable.cpp @@ -9,14 +9,16 @@ // #define TRACE -condition_variable::condition_variable() { #if defined(__WIN32__) +condition_variable::condition_variable() { _event = CreateEvent(NULL, FALSE, FALSE, NULL); +} #else +condition_variable::condition_variable() { pthread_cond_init(&_cond, NULL); pthread_mutex_init(&_mutex, NULL); -#endif } +#endif condition_variable::~condition_variable() { #if defined(__WIN32__) @@ -31,15 +33,31 @@ condition_variable::~condition_variable() { * Wait indefinitely until condition is signaled. */ void condition_variable::wait() { + timed_wait(0); +} + +void condition_variable::timed_wait(size_t timeout_in_ns) { #ifdef TRACE - printf("waiting on condition_variable: 0x%" PRIxPTR "\n", - (uintptr_t)this); + printf("waiting on condition_variable: 0x%" PRIxPTR " for %d ns. \n", + (uintptr_t) this, (int) timeout_in_ns); #endif #if defined(__WIN32__) WaitForSingleObject(_event, INFINITE); #else pthread_mutex_lock(&_mutex); - pthread_cond_wait(&_cond, &_mutex); + // wait() automatically releases the mutex while it waits, and acquires + // it right before exiting. This allows signal() to acquire the mutex + // when signaling.) + if (timeout_in_ns == 0) { + pthread_cond_wait(&_cond, &_mutex); + } else { + timeval time_val; + gettimeofday(&time_val, NULL); + timespec time_spec; + time_spec.tv_sec = time_val.tv_sec + 0; + time_spec.tv_nsec = time_val.tv_usec * 1000 + timeout_in_ns; + pthread_cond_timedwait(&_cond, &_mutex, &time_spec); + } pthread_mutex_unlock(&_mutex); #endif #ifdef TRACE diff --git a/src/rt/sync/condition_variable.h b/src/rt/sync/condition_variable.h index f847ef99..f336a7f2 100644 --- a/src/rt/sync/condition_variable.h +++ b/src/rt/sync/condition_variable.h @@ -13,6 +13,7 @@ public: virtual ~condition_variable(); void wait(); + void timed_wait(size_t timeout_in_ns); void signal(); }; diff --git a/src/rt/sync/lock_free_queue.cpp b/src/rt/sync/lock_free_queue.cpp index 69241ece..3f859862 100644 --- a/src/rt/sync/lock_free_queue.cpp +++ b/src/rt/sync/lock_free_queue.cpp @@ -18,6 +18,7 @@ lock_free_queue::lock_free_queue() : _tail(this) { void lock_free_queue::enqueue(lock_free_queue_node *item) { + lock.lock(); item->next = (lock_free_queue_node *) NULL; lock_free_queue_node *last = _tail; _tail = item; @@ -25,10 +26,12 @@ lock_free_queue::enqueue(lock_free_queue_node *item) { last = last->next; } last->next = item; + lock.unlock(); } lock_free_queue_node * lock_free_queue::dequeue() { + lock.lock(); lock_free_queue_node *item = next; if (item && !(next = item->next)) { _tail = (lock_free_queue_node *) this; @@ -41,6 +44,7 @@ lock_free_queue::dequeue() { } while ((lost = help) != (lock_free_queue_node *) NULL); } } + lock.unlock(); return item; } diff --git a/src/rt/sync/lock_free_queue.h b/src/rt/sync/lock_free_queue.h index 1f09ec52..c1a309b8 100644 --- a/src/rt/sync/lock_free_queue.h +++ b/src/rt/sync/lock_free_queue.h @@ -1,6 +1,8 @@ #ifndef LOCK_FREE_QUEUE_H #define LOCK_FREE_QUEUE_H +#include "spin_lock.h" + class lock_free_queue_node { public: lock_free_queue_node *next; @@ -8,6 +10,7 @@ public: }; class lock_free_queue : lock_free_queue_node { + spin_lock lock; lock_free_queue_node *_tail; public: lock_free_queue(); diff --git a/src/rt/sync/sync.cpp b/src/rt/sync/sync.cpp new file mode 100644 index 00000000..09a6f291 --- /dev/null +++ b/src/rt/sync/sync.cpp @@ -0,0 +1,12 @@ +#include "../globals.h" +#include "sync.h" + +void sync::yield() { +#ifdef __APPLE__ + pthread_yield_np(); +#elif __WIN32__ + Sleep(1); +#else + pthread_yield(); +#endif +} diff --git a/src/rt/sync/sync.h b/src/rt/sync/sync.h new file mode 100644 index 00000000..902b5661 --- /dev/null +++ b/src/rt/sync/sync.h @@ -0,0 +1,9 @@ +#ifndef SYNC_H +#define SYNC_H + +class sync { +public: + static void yield(); +}; + +#endif /* SYNC_H */ diff --git a/src/rt/sync/timer.cpp b/src/rt/sync/timer.cpp new file mode 100644 index 00000000..0487b397 --- /dev/null +++ b/src/rt/sync/timer.cpp @@ -0,0 +1,61 @@ +#include "../globals.h" +#include "timer.h" + +#if defined(__APPLE__) +#include <mach/mach_time.h> +#endif + +timer::timer() { +#if __WIN32__ + uint64_t ticks_per_second; + QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second); + _ticks_per_us = ticks_per_second / 1000000; +#endif + reset(0); +} + +void +timer::reset(uint64_t timeout) { + _start = get_time(); + _timeout = timeout; +} + +uint64_t +timer::get_elapsed_time() { + return get_time() - _start; +} + +int64_t +timer::get_timeout() { + return _timeout - get_elapsed_time(); +} + +bool +timer::has_timed_out() { + return get_timeout() <= 0; +} + +uint64_t +timer::get_time() { +#ifdef __APPLE__ + uint64_t time = mach_absolute_time(); + mach_timebase_info_data_t info = {0, 0}; + if (info.denom == 0) { + mach_timebase_info(&info); + } + uint64_t time_nano = time * (info.numer / info.denom); + return time_nano / 1000; +#elif __WIN32__ + uint64_t ticks; + QueryPerformanceCounter((LARGE_INTEGER *)&ticks); + return ticks / _ticks_per_us; +#else + timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (ts.tv_sec * 1000000000LL + ts.tv_nsec) / 1000; +#endif +} + +timer::~timer() { + // Nop. +} diff --git a/src/rt/sync/timer.h b/src/rt/sync/timer.h new file mode 100644 index 00000000..509fd22c --- /dev/null +++ b/src/rt/sync/timer.h @@ -0,0 +1,25 @@ +/* + * Utility class to measure time in a platform independent way. + */ + +#ifndef TIMER_H +#define TIMER_H + +class timer { +private: + uint64_t _start; + uint64_t _timeout; + uint64_t get_time(); +#if __WIN32__ + uint64_t _ticks_per_us; +#endif +public: + timer(); + void reset(uint64_t timeout); + uint64_t get_elapsed_time(); + int64_t get_timeout(); + bool has_timed_out(); + virtual ~timer(); +}; + +#endif /* TIMER_H */ |