summaryrefslogtreecommitdiffstats
path: root/libdimension
diff options
context:
space:
mode:
Diffstat (limited to 'libdimension')
-rw-r--r--libdimension/canvas.c110
-rw-r--r--libdimension/dimension/canvas.h16
2 files changed, 13 insertions, 113 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 */