diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2013-03-19 19:44:44 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2013-03-19 19:51:44 -0400 |
commit | a842f979c219ef245b09c4607aacc36fbca3f66b (patch) | |
tree | 644b5db03f4cce676f0aac49714b766ab8fed74b | |
parent | e597ca66bebb5ef62d3aac6ee832e5ccc811454d (diff) | |
download | dimension-a842f979c219ef245b09c4607aacc36fbca3f66b.tar.xz |
Simplify future implementation.
A read-write lock was a bad idea, as most consumers are probably
writers, not readers.
-rw-r--r-- | libdimension/future-impl.h | 7 | ||||
-rw-r--r-- | libdimension/future.c | 52 |
2 files changed, 28 insertions, 31 deletions
diff --git a/libdimension/future-impl.h b/libdimension/future-impl.h index c25a7c2..953d5a4 100644 --- a/libdimension/future-impl.h +++ b/libdimension/future-impl.h @@ -1,5 +1,5 @@ /************************************************************************* - * Copyright (C) 2010-2011 Tavian Barnes <tavianator@tavianator.com> * + * Copyright (C) 2010-2013 Tavian Barnes <tavianator@tavianator.com> * * * * This file is part of The Dimension Library. * * * @@ -42,12 +42,11 @@ struct dmnsn_future { /** The worker thread. */ pthread_t thread; - /** Read-write synchronization. */ - pthread_rwlock_t *rwlock; + /** Mutex to guard progress and total. */ + pthread_mutex_t *mutex; /** Condition variable for waiting for a particular amount of progress. */ pthread_cond_t *cond; - pthread_mutex_t *mutex; /** Minimum waited-on value. */ double *min_wait; diff --git a/libdimension/future.c b/libdimension/future.c index c328815..f645944 100644 --- a/libdimension/future.c +++ b/libdimension/future.c @@ -1,5 +1,5 @@ /************************************************************************* - * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> * + * Copyright (C) 2009-2013 Tavian Barnes <tavianator@tavianator.com> * * * * This file is part of The Dimension Library. * * * @@ -34,17 +34,12 @@ dmnsn_new_future(void) future->progress = 0; future->total = 1; - /* Initialize the rwlock, condition variable, and mutex */ - - future->rwlock = dmnsn_malloc(sizeof(pthread_rwlock_t)); - dmnsn_initialize_rwlock(future->rwlock); + future->mutex = dmnsn_malloc(sizeof(pthread_mutex_t)); + dmnsn_initialize_mutex(future->mutex); future->cond = dmnsn_malloc(sizeof(pthread_cond_t)); dmnsn_initialize_cond(future->cond); - future->mutex = dmnsn_malloc(sizeof(pthread_mutex_t)); - dmnsn_initialize_mutex(future->mutex); - future->min_wait = dmnsn_malloc(sizeof(double)); *future->min_wait = 1.0; @@ -70,14 +65,11 @@ dmnsn_future_join(dmnsn_future *future) dmnsn_free(future->min_wait); - dmnsn_destroy_mutex(future->mutex); - dmnsn_free(future->mutex); - dmnsn_destroy_cond(future->cond); dmnsn_free(future->cond); - dmnsn_destroy_rwlock(future->rwlock); - dmnsn_free(future->rwlock); + dmnsn_destroy_mutex(future->mutex); + dmnsn_free(future->mutex); dmnsn_free(future); } @@ -92,15 +84,26 @@ dmnsn_future_cancel(dmnsn_future *future) pthread_cancel(future->thread); } +/** + * Get the current progress, without locking anything. + * + * future->mutex must be locked for this call to be safe. + */ +static inline double +dmnsn_future_progress_unlocked(const dmnsn_future *future) +{ + return (double)future->progress/future->total; +} + /* Get the current progress of the worker thread, in [0.0, 1.0] */ double dmnsn_future_progress(const dmnsn_future *future) { double progress; - dmnsn_read_lock(future->rwlock); - progress = (double)future->progress/future->total; - dmnsn_unlock_rwlock(future->rwlock); + dmnsn_lock_mutex(future->mutex); + progress = dmnsn_future_progress_unlocked(future); + dmnsn_unlock_mutex(future->mutex); return progress; } @@ -110,7 +113,7 @@ void dmnsn_future_wait(const dmnsn_future *future, double progress) { dmnsn_lock_mutex(future->mutex); - while (dmnsn_future_progress(future) < progress) { + while (dmnsn_future_progress_unlocked(future) < progress) { /* Set the minimum waited-on value */ if (progress < *future->min_wait) *future->min_wait = progress; @@ -124,9 +127,9 @@ dmnsn_future_wait(const dmnsn_future *future, double progress) void dmnsn_future_set_total(dmnsn_future *future, size_t total) { - dmnsn_write_lock(future->rwlock); + dmnsn_lock_mutex(future->mutex); future->total = total; - dmnsn_unlock_rwlock(future->rwlock); + dmnsn_unlock_mutex(future->mutex); } /* Increment the number of completed loop iterations */ @@ -138,12 +141,10 @@ dmnsn_future_increment(dmnsn_future *future) on cancellation */ pthread_testcancel(); - dmnsn_write_lock(future->rwlock); + dmnsn_lock_mutex(future->mutex); ++future->progress; - dmnsn_unlock_rwlock(future->rwlock); - dmnsn_lock_mutex(future->mutex); - if (dmnsn_future_progress(future) >= *future->min_wait) { + if (dmnsn_future_progress_unlocked(future) >= *future->min_wait) { *future->min_wait = 1.0; dmnsn_cond_broadcast(future->cond); } @@ -154,11 +155,8 @@ dmnsn_future_increment(dmnsn_future *future) void dmnsn_future_done(dmnsn_future *future) { - dmnsn_write_lock(future->rwlock); - future->progress = future->total; - dmnsn_unlock_rwlock(future->rwlock); - dmnsn_lock_mutex(future->mutex); + future->progress = future->total; dmnsn_cond_broadcast(future->cond); dmnsn_unlock_mutex(future->mutex); } |