summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2013-03-19 19:44:44 -0400
committerTavian Barnes <tavianator@tavianator.com>2013-03-19 19:51:44 -0400
commita842f979c219ef245b09c4607aacc36fbca3f66b (patch)
tree644b5db03f4cce676f0aac49714b766ab8fed74b
parente597ca66bebb5ef62d3aac6ee832e5ccc811454d (diff)
downloaddimension-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.h7
-rw-r--r--libdimension/future.c52
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);
}