diff options
Diffstat (limited to 'src/cache.c')
-rw-r--r-- | src/cache.c | 160 |
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; } |