summaryrefslogtreecommitdiffstats
path: root/libdimension/array.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdimension/array.c')
-rw-r--r--libdimension/array.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/libdimension/array.c b/libdimension/array.c
index f8f3c58..82588aa 100644
--- a/libdimension/array.c
+++ b/libdimension/array.c
@@ -26,6 +26,7 @@
static void dmnsn_array_get_impl(const dmnsn_array *array, size_t i, void *obj);
static void dmnsn_array_set_impl(dmnsn_array *array, size_t i, const void *obj);
+/* Allocate a new array - guaranteed not to fail if it returns */
dmnsn_array *
dmnsn_new_array(size_t obj_size)
{
@@ -35,11 +36,13 @@ dmnsn_new_array(size_t obj_size)
array->length = 0;
array->capacity = 4; /* Start with capacity of 4 */
+ /* Allocate the memory */
array->ptr = malloc(array->capacity*array->obj_size);
if (!array->ptr) {
dmnsn_error(DMNSN_SEVERITY_HIGH, "Array allocation failed.");
}
+ /* Allocate the read-write lock */
array->rwlock = malloc(sizeof(pthread_rwlock_t));
if (!array->rwlock || pthread_rwlock_init(array->rwlock, NULL) != 0) {
dmnsn_error(DMNSN_SEVERITY_HIGH, "Array rwlock allocation failed.");
@@ -49,6 +52,7 @@ dmnsn_new_array(size_t obj_size)
return array;
}
+/* Delete the array */
void dmnsn_delete_array(dmnsn_array *array) {
if (array) {
if (pthread_rwlock_destroy(array->rwlock) != 0) {
@@ -61,6 +65,7 @@ void dmnsn_delete_array(dmnsn_array *array) {
}
}
+/* Push obj to the end of the array, atomically */
void
dmnsn_array_push(dmnsn_array *array, const void *obj)
{
@@ -69,6 +74,7 @@ dmnsn_array_push(dmnsn_array *array, const void *obj)
dmnsn_array_unlock(array);
}
+/* Pop obj from the end of the array, atomically */
void
dmnsn_array_pop(dmnsn_array *array, void *obj)
{
@@ -76,11 +82,12 @@ dmnsn_array_pop(dmnsn_array *array, void *obj)
dmnsn_array_wrlock(array);
size = dmnsn_array_size_unlocked(array);
- dmnsn_array_get_impl(array, size - 1, obj);
- dmnsn_array_resize_unlocked(array, size - 1);
+ dmnsn_array_get_impl(array, size - 1, obj); /* Copy the object */
+ dmnsn_array_resize_unlocked(array, size - 1); /* Shrink the array */
dmnsn_array_unlock(array);
}
+/* Get the i'th object, bailing out if i is out of range */
void
dmnsn_array_get(const dmnsn_array *array, size_t i, void *obj)
{
@@ -89,6 +96,7 @@ dmnsn_array_get(const dmnsn_array *array, size_t i, void *obj)
dmnsn_array_unlock(array);
}
+/* Set the i'th object, expanding the array if necessary */
void
dmnsn_array_set(dmnsn_array *array, size_t i, const void *obj)
{
@@ -97,6 +105,7 @@ dmnsn_array_set(dmnsn_array *array, size_t i, const void *obj)
dmnsn_array_unlock(array);
}
+/* Get the size of the array, atomically */
size_t
dmnsn_array_size(const dmnsn_array *array)
{
@@ -109,6 +118,7 @@ dmnsn_array_size(const dmnsn_array *array)
return size;
}
+/* Set the size of the array, atomically */
void
dmnsn_array_resize(dmnsn_array *array, size_t length)
{
@@ -117,6 +127,7 @@ dmnsn_array_resize(dmnsn_array *array, size_t length)
dmnsn_array_unlock(array);
}
+/* Thread-unsafe range-checked element access */
void *
dmnsn_array_at(dmnsn_array *array, size_t i)
{
@@ -126,16 +137,19 @@ dmnsn_array_at(dmnsn_array *array, size_t i)
return (char *)array->ptr + array->obj_size*i;
}
+/* Get the size non-atomically, for manual locking */
size_t
dmnsn_array_size_unlocked(const dmnsn_array *array)
{
return array->length;
}
+/* Set the size non-atomically, for manual locking */
void
dmnsn_array_resize_unlocked(dmnsn_array *array, size_t length)
{
if (length > array->capacity) {
+ /* Resize if we don't have enough capacity */
array->capacity = length*2; /* We are greedy */
array->ptr = realloc(array->ptr, array->obj_size*array->capacity);
if (!array->ptr) {
@@ -146,6 +160,7 @@ dmnsn_array_resize_unlocked(dmnsn_array *array, size_t length)
array->length = length;
}
+/* Set a manual read-lock */
void
dmnsn_array_rdlock(const dmnsn_array *array)
{
@@ -157,6 +172,7 @@ dmnsn_array_rdlock(const dmnsn_array *array)
}
}
+/* Set a manual write-lock */
void
dmnsn_array_wrlock(dmnsn_array *array)
{
@@ -168,6 +184,7 @@ dmnsn_array_wrlock(dmnsn_array *array)
}
}
+/* Unset a manual lock */
void
dmnsn_array_unlock(const dmnsn_array *array)
{
@@ -178,19 +195,23 @@ dmnsn_array_unlock(const dmnsn_array *array)
}
}
+/* Actual "get" implementation */
static void
dmnsn_array_get_impl(const dmnsn_array *array, size_t i, void *obj)
{
if (i >= dmnsn_array_size_unlocked(array)) {
+ /* Range check failed */
dmnsn_error(DMNSN_SEVERITY_HIGH, "Array index out of bounds.");
}
memcpy(obj, array->ptr + array->obj_size*i, array->obj_size);
}
+/* Actual "set" implementation */
static void
dmnsn_array_set_impl(dmnsn_array *array, size_t i, const void *obj)
{
if (i >= dmnsn_array_size_unlocked(array)) {
+ /* Resize if i is out of range */
dmnsn_array_resize_unlocked(array, i + 1);
}
memcpy(array->ptr + array->obj_size*i, obj, array->obj_size);