diff options
author | 2020-03-27 14:40:33 +0200 | |
---|---|---|
committer | 2020-03-27 14:40:33 +0200 | |
commit | 7754455c48c50764ad7291ea508109c53b60517f (patch) | |
tree | f8b3f0fe7ad2509ff8c40a998cde91f8f7353f80 /src/cache.c | |
parent | 8b4c2c3194dbf9b18ecf475597d257ee7125a1e1 (diff) | |
download | algos-ld1-7754455c48c50764ad7291ea508109c53b60517f.tar.gz algos-ld1-7754455c48c50764ad7291ea508109c53b60517f.tar.bz2 algos-ld1-7754455c48c50764ad7291ea508109c53b60517f.zip |
cache I/O implementation and fixes.
Signed-off-by: Gediminas Jakutis <gediminas@varciai.lt>
Diffstat (limited to 'src/cache.c')
-rw-r--r-- | src/cache.c | 92 |
1 files changed, 89 insertions, 3 deletions
diff --git a/src/cache.c b/src/cache.c index ebe1047..de182ec 100644 --- a/src/cache.c +++ b/src/cache.c @@ -6,11 +6,14 @@ #include <stdlib.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 ret; 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"); in->cache = cache; @@ -21,7 +24,9 @@ err: int cache_populate(struct stream * const restrict in) { int ret = 0; - ssize_t i; + size_t i; + + 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); @@ -34,7 +39,10 @@ err: int cache_flush(struct stream * const in) { int ret; - ssize_t i; + size_t i; + + 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); @@ -48,9 +56,87 @@ int cache_destroy(struct stream * const in) { int ret; - try(!in->cache, err, EINVAL, "trying to destroy cache of uncached streadm"); + try(!in->cached, err, EINVAL, "no cache to destroy: stream uncached"); free(in->cache); in->cache = NULL; err: return ret; } + +int cache_transfer(struct stream * const from, struct stream * const to) +{ + int ret; + + 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"); + + to->cache = from->cache; + from->cache = NULL; +err: + return ret; +} + +int cached_get_array(struct stream * const in, ssize_t idx, struct entry_l * const data) +{ + int ret = 0; + const struct entry * const cache = in->cache; + + data->val = cache[idx].val; + + return ret; +} + +int cached_get_list(struct stream * const restrict in, ssize_t idx, struct entry_l * const data) +{ + int ret = 0; + off_t offset; + + offset = cache_walker(in, idx); + *data = in->cache[offset]; + + return ret; +} + +int cached_put_array(struct stream * const in, ssize_t idx, const struct entry_l * const data) +{ + int ret = 0; + struct entry * const cache = in->cache; + + cache[idx].val = data->val; + + return ret; +} + +int cached_put_list(struct stream * const restrict in, ssize_t idx, const struct entry_l * const data) +{ + int ret = 0; + off_t offset; + + offset = cache_walker(in, idx); + in->cache[offset] = *data; + + return ret; +} + +static off_t cache_walker(struct stream * const restrict in, ssize_t idx) +{ + size_t i; + off_t ret = in->prev_off; + + if (in->prev_idx < idx) { /* previous index smaller, walk forward */ + for (i = labs(idx - in->prev_idx); i; --i) { + ret = in->cache[ret].next; + } + + } 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 */ + + in->prev_idx = idx; + in->prev_off = ret; + + return ret; +} |