summaryrefslogtreecommitdiffstats
path: root/src/cache.c
diff options
context:
space:
mode:
authorGravatar Gediminas Jakutis <gediminas@varciai.lt> 2021-02-09 05:43:36 +0200
committerGravatar Gediminas Jakutis <gediminas@varciai.lt> 2021-02-09 05:43:36 +0200
commit41efe7b8f9f67d5956ab677f3631478c48114ac1 (patch)
tree9b2d1cff2bc30b484a9192a498d38344803d83d9 /src/cache.c
parent7754455c48c50764ad7291ea508109c53b60517f (diff)
downloadalgos-ld1-41efe7b8f9f67d5956ab677f3631478c48114ac1.tar.gz
algos-ld1-41efe7b8f9f67d5956ab677f3631478c48114ac1.tar.bz2
algos-ld1-41efe7b8f9f67d5956ab677f3631478c48114ac1.zip
A major overhaul of the whole thing.
It has come to my attention that previously, the project was built on top of some *very* incorrect assumptions. This patch mostly addresses that. And while it does NOT leave the project in otherwise working state, it does weed out most, if not all, of effects of previously incorrect assumptions, so it can be built the right way from here on forth. Signed-off-by: Gediminas Jakutis <gediminas@varciai.lt>
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;
}