From 4f9122668d0edd36fbf2ef683d7dafd6b77ac24f Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 19 Mar 2013 20:20:03 -0400 Subject: Don't use pointer indirection to emulate mutable for futures. We can just cast away the const, as they're all on the heap anyway. --- libdimension/future-impl.h | 6 ++-- libdimension/future.c | 69 +++++++++++++++++++++++----------------------- 2 files changed, 37 insertions(+), 38 deletions(-) diff --git a/libdimension/future-impl.h b/libdimension/future-impl.h index 953d5a4..4ec6f75 100644 --- a/libdimension/future-impl.h +++ b/libdimension/future-impl.h @@ -43,11 +43,11 @@ struct dmnsn_future { pthread_t thread; /** Mutex to guard progress and total. */ - pthread_mutex_t *mutex; + pthread_mutex_t mutex; /** Condition variable for waiting for a particular amount of progress. */ - pthread_cond_t *cond; + pthread_cond_t cond; /** Minimum waited-on value. */ - double *min_wait; + double min_wait; }; diff --git a/libdimension/future.c b/libdimension/future.c index f645944..6ea15ae 100644 --- a/libdimension/future.c +++ b/libdimension/future.c @@ -26,6 +26,13 @@ #include "dimension-internal.h" #include +/** + * Since C doesn't support anything like C++'s mutable, we fake it by casting + * away the constness. This is okay since all valid dmnsn_futures live on the + * heap, so cannot be const. + */ +#define MUTATE(future) ((dmnsn_future *)future) + /* Allocate a new dmnsn_future* */ dmnsn_future * dmnsn_new_future(void) @@ -34,14 +41,10 @@ dmnsn_new_future(void) future->progress = 0; future->total = 1; - future->mutex = dmnsn_malloc(sizeof(pthread_mutex_t)); - dmnsn_initialize_mutex(future->mutex); + dmnsn_initialize_mutex(&future->mutex); + dmnsn_initialize_cond(&future->cond); - future->cond = dmnsn_malloc(sizeof(pthread_cond_t)); - dmnsn_initialize_cond(future->cond); - - future->min_wait = dmnsn_malloc(sizeof(double)); - *future->min_wait = 1.0; + future->min_wait = 1.0; return future; } @@ -62,15 +65,8 @@ dmnsn_future_join(dmnsn_future *future) } /* Free the future object */ - - dmnsn_free(future->min_wait); - - dmnsn_destroy_cond(future->cond); - dmnsn_free(future->cond); - - dmnsn_destroy_mutex(future->mutex); - dmnsn_free(future->mutex); - + dmnsn_destroy_cond(&future->cond); + dmnsn_destroy_mutex(&future->mutex); dmnsn_free(future); } @@ -99,11 +95,12 @@ dmnsn_future_progress_unlocked(const dmnsn_future *future) double dmnsn_future_progress(const dmnsn_future *future) { + dmnsn_future *mfuture = MUTATE(future); double progress; - dmnsn_lock_mutex(future->mutex); - progress = dmnsn_future_progress_unlocked(future); - dmnsn_unlock_mutex(future->mutex); + dmnsn_lock_mutex(&mfuture->mutex); + progress = dmnsn_future_progress_unlocked(mfuture); + dmnsn_unlock_mutex(&mfuture->mutex); return progress; } @@ -112,24 +109,26 @@ dmnsn_future_progress(const dmnsn_future *future) void dmnsn_future_wait(const dmnsn_future *future, double progress) { - dmnsn_lock_mutex(future->mutex); - while (dmnsn_future_progress_unlocked(future) < progress) { + dmnsn_future *mfuture = MUTATE(future); + + dmnsn_lock_mutex(&mfuture->mutex); + while (dmnsn_future_progress_unlocked(mfuture) < progress) { /* Set the minimum waited-on value */ - if (progress < *future->min_wait) - *future->min_wait = progress; + if (progress < mfuture->min_wait) + mfuture->min_wait = progress; - dmnsn_cond_wait(future->cond, future->mutex); + dmnsn_cond_wait(&mfuture->cond, &mfuture->mutex); } - dmnsn_unlock_mutex(future->mutex); + dmnsn_unlock_mutex(&mfuture->mutex); } /* Set the total number of loop iterations */ void dmnsn_future_set_total(dmnsn_future *future, size_t total) { - dmnsn_lock_mutex(future->mutex); + dmnsn_lock_mutex(&future->mutex); future->total = total; - dmnsn_unlock_mutex(future->mutex); + dmnsn_unlock_mutex(&future->mutex); } /* Increment the number of completed loop iterations */ @@ -141,22 +140,22 @@ dmnsn_future_increment(dmnsn_future *future) on cancellation */ pthread_testcancel(); - dmnsn_lock_mutex(future->mutex); + dmnsn_lock_mutex(&future->mutex); ++future->progress; - if (dmnsn_future_progress_unlocked(future) >= *future->min_wait) { - *future->min_wait = 1.0; - dmnsn_cond_broadcast(future->cond); + if (dmnsn_future_progress_unlocked(future) >= future->min_wait) { + future->min_wait = 1.0; + dmnsn_cond_broadcast(&future->cond); } - dmnsn_unlock_mutex(future->mutex); + dmnsn_unlock_mutex(&future->mutex); } /* Immediately set to 100% completion */ void dmnsn_future_done(dmnsn_future *future) { - dmnsn_lock_mutex(future->mutex); + dmnsn_lock_mutex(&future->mutex); future->progress = future->total; - dmnsn_cond_broadcast(future->cond); - dmnsn_unlock_mutex(future->mutex); + dmnsn_cond_broadcast(&future->cond); + dmnsn_unlock_mutex(&future->mutex); } -- cgit v1.2.3