From a842f979c219ef245b09c4607aacc36fbca3f66b Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 19 Mar 2013 19:44:44 -0400 Subject: Simplify future implementation. A read-write lock was a bad idea, as most consumers are probably writers, not readers. --- libdimension/future-impl.h | 7 +++---- 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 * + * Copyright (C) 2010-2013 Tavian Barnes * * * * 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 * + * Copyright (C) 2009-2013 Tavian Barnes * * * * 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); } -- cgit v1.2.3