diff options
-rw-r--r-- | libdimension/canvas.c | 110 | ||||
-rw-r--r-- | libdimension/dimension/canvas.h | 16 | ||||
-rw-r--r-- | libdimensionxx/canvas.cpp | 4 | ||||
-rw-r--r-- | libdimensionxx/dimensionxx/canvas.hpp | 2 |
4 files changed, 16 insertions, 116 deletions
diff --git a/libdimension/canvas.c b/libdimension/canvas.c index 13b1e9e..c2bd5cf 100644 --- a/libdimension/canvas.c +++ b/libdimension/canvas.c @@ -22,12 +22,10 @@ #include <pthread.h> #include <stdlib.h> /* For malloc(), free() */ -/* Allocate a new canvas, of width x and height y. If any intermediary step - fails, free all acquired memory to avoid leaks. */ +/* Allocate a new canvas, of width x and height y */ dmnsn_canvas * dmnsn_new_canvas(unsigned int x, unsigned int y) { - unsigned int i, j, k, l; /* Allocate the dmnsn_canvas struct */ dmnsn_canvas *canvas = malloc(sizeof(dmnsn_canvas)); @@ -42,47 +40,6 @@ dmnsn_new_canvas(unsigned int x, unsigned int y) free(canvas); return NULL; } - - /* Allocate the rwlocks */ - canvas->rwlocks = malloc(sizeof(pthread_rwlock_t)*x*y); - if (!canvas->rwlocks) { - free(canvas->pixels); - free(canvas); - return NULL; - } - - /* Initialize the rwlocks */ - for (i = 0; i < x; ++i) { - for (j = 0; j < y; ++j) { - if (pthread_rwlock_init(&canvas->rwlocks[j*x + i], NULL) != 0) { - /* pthread_rwlock_init failed. Destroy the locks we've already made, - free the canvas, and return NULL. We leak memory if destruction - fails (i.e. someone is somehow using an rwlock already). */ - - for (l = 0; l < j; ++l) { - for (k = 0; k < x; ++k) { - if (pthread_rwlock_destroy(&canvas->rwlocks[l*x + k]) != 0) { - /* Low severity, because leaked locks won't actually hurt us */ - dmnsn_error(DMNSN_SEVERITY_LOW, - "Leaking rwlocks in failed allocation."); - } - } - } - - for (k = 0; k < i; ++k) { - if (pthread_rwlock_destroy(&canvas->rwlocks[j*x + k]) != 0) { - dmnsn_error(DMNSN_SEVERITY_LOW, - "Leaking rwlocks in failed allocation."); - } - } - - free(canvas->rwlocks); - free(canvas->pixels); - free(canvas); - return NULL; - } - } - } } return canvas; @@ -92,78 +49,31 @@ dmnsn_new_canvas(unsigned int x, unsigned int y) void dmnsn_delete_canvas(dmnsn_canvas *canvas) { - unsigned int i, j; - if (canvas) { - /* Destroy the rwlocks */ - for (i = 0; i < canvas->x; ++i) { - for (j = 0; j < canvas->y; ++j) { - if (pthread_rwlock_destroy(&canvas->rwlocks[j*canvas->x + i]) != 0) { - dmnsn_error(DMNSN_SEVERITY_LOW, - "Leaking rwlocks in deallocation."); - } - } - } - - /* Free the locks, pixels, and canvas */ - free(canvas->rwlocks); + /* Free the pixels and canvas */ free(canvas->pixels); free(canvas); } } -/* Get a pixel at (x,y) thread-safely, using dmnsn_rdlock_pixel. */ +/* Get a pixel at (x,y) */ dmnsn_color dmnsn_get_pixel(const dmnsn_canvas *canvas, unsigned int x, unsigned int y) { - dmnsn_color color; - dmnsn_rdlock_pixel(canvas, x, y); - color = canvas->pixels[y*canvas->x + x]; - dmnsn_unlock_pixel(canvas, x, y); - return color; + return canvas->pixels[y*canvas->x + x]; } -/* Set a pixel at (x,y) thread-safely, using dmnsn_wrlock_pixel. */ +/* Set a pixel at (x,y) */ void dmnsn_set_pixel(dmnsn_canvas *canvas, unsigned int x, unsigned int y, dmnsn_color color) { - dmnsn_wrlock_pixel(canvas, x, y); - canvas->pixels[y*canvas->x + x] = color; - dmnsn_unlock_pixel(canvas, x, y); + canvas->pixels[y*canvas->x + x] = color; } -/* Acquire a read-lock for a pixel */ -void -dmnsn_rdlock_pixel(const dmnsn_canvas *canvas, unsigned int x, unsigned int y) -{ - if (pthread_rwlock_rdlock(&canvas->rwlocks[y*canvas->x + x]) != 0) { - /* Medium severity, because undefined behaviour is pretty likely if our - reads and writes aren't synced */ - dmnsn_error(DMNSN_SEVERITY_MEDIUM, - "Couldn't acquire read-lock for pixel."); - } -} - -/* Acquire a write-lock for a pixel */ -void -dmnsn_wrlock_pixel(dmnsn_canvas *canvas, unsigned int x, unsigned int y) +/* Point to the pixel at (x,y) */ +dmnsn_color * +dmnsn_pixel_at(dmnsn_canvas *canvas, unsigned int x, unsigned int y) { - if (pthread_rwlock_wrlock(&canvas->rwlocks[y*canvas->x + x]) != 0) { - /* Medium severity, because undefined behaviour is pretty likely if our - reads and writes aren't synced */ - dmnsn_error(DMNSN_SEVERITY_MEDIUM, - "Couldn't acquire write-lock for pixel."); - } -} - -/* Unlock a pixel */ -void -dmnsn_unlock_pixel(const dmnsn_canvas *canvas, unsigned int x, unsigned int y) -{ - if (pthread_rwlock_unlock(&canvas->rwlocks[y*canvas->x + x]) != 0) { - /* Medium severity, because if the pixel is locked, we're likely to hang - the next time we try to read or write it */ - dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't unlock pixel."); - } + return canvas->pixels + y*canvas->x + x; } diff --git a/libdimension/dimension/canvas.h b/libdimension/dimension/canvas.h index 50cc612..cd414a9 100644 --- a/libdimension/dimension/canvas.h +++ b/libdimension/dimension/canvas.h @@ -25,8 +25,6 @@ #ifndef DIMENSION_CANVAS_H #define DIMENSION_CANVAS_H -#include <pthread.h> - typedef struct { unsigned int x, y; @@ -35,26 +33,18 @@ typedef struct { * at (a,b) is accessible as pixels[b*x + a]. */ dmnsn_color *pixels; - - /* Read-write locks for each pixel */ - pthread_rwlock_t *rwlocks; } dmnsn_canvas; /* Allocate and free a canvas */ dmnsn_canvas *dmnsn_new_canvas(unsigned int x, unsigned int y); void dmnsn_delete_canvas(dmnsn_canvas *canvas); -/* These handle the rwlocks correctly */ +/* Pixel accessors */ dmnsn_color dmnsn_get_pixel(const dmnsn_canvas *canvas, unsigned int x, unsigned int y); void dmnsn_set_pixel(dmnsn_canvas *canvas, unsigned int x, unsigned int y, dmnsn_color color); - -/* Manual locking */ -void dmnsn_rdlock_pixel(const dmnsn_canvas *canvas, - unsigned int x, unsigned int y); -void dmnsn_wrlock_pixel(dmnsn_canvas *canvas, unsigned int x, unsigned int y); -void dmnsn_unlock_pixel(const dmnsn_canvas *canvas, - unsigned int x, unsigned int y); +dmnsn_color *dmnsn_pixel_at(dmnsn_canvas *canvas, + unsigned int x, unsigned int y); #endif /* DIMENSION_CANVAS_H */ diff --git a/libdimensionxx/canvas.cpp b/libdimensionxx/canvas.cpp index 411d4e8..35ff2fb 100644 --- a/libdimensionxx/canvas.cpp +++ b/libdimensionxx/canvas.cpp @@ -46,14 +46,14 @@ namespace Dimension return m_canvas->y; } - // Get a particular pixel, thread-safely, with dmnsn_get_pixel(). + // Get a particular pixel Color Canvas::pixel(unsigned int x, unsigned int y) const { return Color(dmnsn_get_pixel(m_canvas, x, y)); } - // Set a particular pixel, thread-safely, with dmnsn_set_pixel(). + // Set a particular pixel void Canvas::pixel(unsigned int x, unsigned int y, const Color& c) { diff --git a/libdimensionxx/dimensionxx/canvas.hpp b/libdimensionxx/dimensionxx/canvas.hpp index f9e77e5..84787ed 100644 --- a/libdimensionxx/dimensionxx/canvas.hpp +++ b/libdimensionxx/dimensionxx/canvas.hpp @@ -42,7 +42,7 @@ namespace Dimension unsigned int width() const; unsigned int height() const; - // Get and set a pixel, thread-safely. + // Get and set a pixel Color pixel(unsigned int x, unsigned int y) const; void pixel(unsigned int x, unsigned int y, const Color& c); |