summaryrefslogtreecommitdiffstats
path: root/src/cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cache.c')
-rw-r--r--src/cache.c160
1 files changed, 112 insertions, 48 deletions
diff --git a/src/cache.c b/src/cache.c
index de182ec..4fe0c46 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -4,32 +4,44 @@
#include <errno.h>
#include <stdlib.h>
+#include <string.h>
+#include <rin/definitions.h>
+#include <rin/diagnostic.h>
#include "defs.h"
-static off_t cache_walker(struct stream * const restrict in, ssize_t idx);
-
-int cache_create(struct stream * const restrict in, const struct settings * const restrict s)
+int cache_create(struct stream * const in, const struct settings * const restrict s)
{
- int ret;
+ int ret = 0;
void *cache;
try(!in->cached, err, EINVAL, "cannot create cache: stream is uncached");
try(!(cache = calloc(in->n, s->stride)), err, ENOMEM, "out of memory");
+ /* yeah... */
in->cache = cache;
+ in->cache_a = cache;
+ in->cache_l = cache;
err:
return ret;
}
-int cache_populate(struct stream * const restrict in)
+int cache_populate(struct stream * const in)
{
int ret = 0;
size_t i;
+ struct entry_l *tmp;
try(!in->cached, err, EINVAL, "cannot populate cache: stream is uncached");
for (i = 0; i < in->n && !ret; ++i) {
- ret = in->get_element(in, i, in->cache + i);
+ errno = 0;
+ tmp = in->get_next_element_direct(in);
+ if (tmp) { /* non-cache reads CAN fail */
+ put(in, tmp);
+ } else {
+ ret = errno;
+ break;
+ }
}
err:
@@ -38,14 +50,14 @@ err:
int cache_flush(struct stream * const in)
{
- int ret;
- size_t i;
+ int ret = 0;
+ struct entry_l *tmp;
try(!in->cached, err, EINVAL, "no cache to flush: stream is uncached");
try(in->out != 1, err, EINVAL, "cannot flush a non-output cache");
- for (i = 0; i < in->n && !ret; ++i) {
- ret = in->put_element(in, i, in->cache + i);
+ while((tmp = get(in))) {
+ in->place_next_element_direct(in, tmp);
}
err:
@@ -54,89 +66,141 @@ err:
int cache_destroy(struct stream * const in)
{
- int ret;
+ int ret = 0;
try(!in->cached, err, EINVAL, "no cache to destroy: stream uncached");
free(in->cache);
+ in->cache_l = NULL;
+ in->cache_a = NULL;
in->cache = NULL;
err:
return ret;
}
-int cache_transfer(struct stream * const from, struct stream * const to)
+int cache_transfer(struct stream * const src, struct stream * const dest)
{
- int ret;
+ int ret = 0;
- try(!from->cached || !to->cached, err, EINVAL, "cannot transfer caches of uncached streams");
- try(!from->cache, err, EINVAL, "no cache to transfer");
- try(!to->cache, err, EINVAL, "cannot transfer cache: recipient cache already exists");
+ try(!src->cached || !dest->cached, err, EINVAL, "cannot transfer caches of uncached streams");
+ try(!src->cache, err, EINVAL, "no cache to transfer");
+ try(dest->cache, err, EINVAL, "cannot transfer cache: recipient cache already exists");
- to->cache = from->cache;
- from->cache = NULL;
+ dest->cache = src->cache;
+ dest->cache_a = (struct entry *) src->cache;
+ dest->cache_l = (struct entry_l *) src->cache;
+ src->cache = NULL;
+ src->cache_a = NULL;
+ src->cache_l = NULL;
err:
return ret;
}
-int cached_get_array(struct stream * const in, ssize_t idx, struct entry_l * const data)
+int cache_block_copy(struct stream const * const src, struct stream * const dest, const struct settings * const s)
{
int ret = 0;
- const struct entry * const cache = in->cache;
- data->val = cache[idx].val;
+ try(!src->cached || !dest->cached, err, EINVAL, "cannot cache-copy between uncached streams");
+ try(!src->cache, err, EINVAL, "no cache to transfer");
+ try(!(src->n < s->to), err, EINVAL, "invalid copy size");
+ try(!dest->cache, err, EINVAL, "no cache to transfer to");
+ memcpy(dest->cache, src->cache_a + s->ss, (s->to - s->ss) * s->stride);
+
+err:
return ret;
}
-int cached_get_list(struct stream * const restrict in, ssize_t idx, struct entry_l * const data)
+int cache_list_copy(struct stream const * const src, struct stream * const dest, const struct settings * const s)
{
- int ret = 0;
- off_t offset;
+ int ret = ENOSYS;
+
+ (void) src;
+ (void) dest;
+ (void) s;
- offset = cache_walker(in, idx);
- *data = in->cache[offset];
+ rin_warn("stub!");
return ret;
}
-int cached_put_array(struct stream * const in, ssize_t idx, const struct entry_l * const data)
+int cache_block_split(struct stream * const src, struct stream * const A, struct stream * const B)
{
int ret = 0;
- struct entry * const cache = in->cache;
- cache[idx].val = data->val;
+ try(src->n < 2, err, EINVAL, "cannot split single element stream.");
+
+ /* copy everything, then change whatever's neccesary */
+ *A = *B = *src;
+ A->n = A->n / 2 + A->n % 2;
+ B->n = B->n / 2;
+ A->index = B->index = 0;
+ B->cache_a = B->cache_a + A->n;
+ B->cache_l = (struct entry_l *) B->cache_a;
+ B->cache = (char *) B->cache_a;
+
+err:
return ret;
}
-int cached_put_list(struct stream * const restrict in, ssize_t idx, const struct entry_l * const data)
+int cache_list_split(struct stream * const src, struct stream * const A, struct stream * const B)
{
- int ret = 0;
- off_t offset;
+ int ret = ENOSYS;
+
+ (void) src;
+ (void) A;
+ (void) B;
- offset = cache_walker(in, idx);
- in->cache[offset] = *data;
+ rin_warn("stub!");
return ret;
}
-static off_t cache_walker(struct stream * const restrict in, ssize_t idx)
+struct entry_l *cached_get_array(struct stream * const in)
{
- size_t i;
- off_t ret = in->prev_off;
+ struct entry_l *ret = NULL;
- if (in->prev_idx < idx) { /* previous index smaller, walk forward */
- for (i = labs(idx - in->prev_idx); i; --i) {
- ret = in->cache[ret].next;
- }
+ if (in->index < in->n) {
+ ret = (struct entry_l *)(in->cache_a + in->index);
+ ++in->index;
+ }
- } else if (in->prev_idx > idx) { /* previous index larger, walk backwards */
- for (i = in->prev_idx - idx; i; --i) {
- ret = in->cache[ret].prev;
- }
- } /* ...or we're standing on it already, if neither */
+ return ret;
+}
+
+struct entry_l *cached_get_list(struct stream * const in)
+{
+ struct entry_l *ret = NULL;
+
+ if (in->index < in->n) {
+ ret = in->cnode;
+ in->cnode = (struct entry_l *) ret->next;
+ ++in->index;
+ }
+
+ return ret;
+}
+
+int cached_put_array(struct stream * const in, const struct entry_l * const data)
+{
+ int ret = EINVAL;
+
+ if (in->index < in->n) {
+ in->cache_a[in->index].val = data->val;
+ ++in->index;
+ }
+
+ return ret;
+}
+
+int cached_put_list(struct stream * const restrict in, const struct entry_l * const node)
+{
+ int ret = ENOSYS;
+
+ (void) in;
+ (void) node;
- in->prev_idx = idx;
- in->prev_off = ret;
+ rin_warn("stub!");
return ret;
}