summaryrefslogtreecommitdiffstats
path: root/src/cache.c
diff options
context:
space:
mode:
authorGravatar Gediminas Jakutis <gediminas@varciai.lt> 2021-03-10 15:04:13 +0200
committerGravatar Gediminas Jakutis <gediminas@varciai.lt> 2021-03-10 15:33:58 +0200
commit8788b9b33ec46e3f96170fb35a70a03addbf9671 (patch)
tree44b620061ca427f436e89c7beb80022febde1e58 /src/cache.c
parentd7e2af2582660e3ed4ce824c33a21ffbf9ed4c6f (diff)
downloadalgos-ld1-8788b9b33ec46e3f96170fb35a70a03addbf9671.tar.gz
algos-ld1-8788b9b33ec46e3f96170fb35a70a03addbf9671.tar.bz2
algos-ld1-8788b9b33ec46e3f96170fb35a70a03addbf9671.zip
refactor && improve.
Make code more reusable and generic while preparing to add uncached ops. Signed-off-by: Gediminas Jakutis <gediminas@varciai.lt>
Diffstat (limited to 'src/cache.c')
-rw-r--r--src/cache.c97
1 files changed, 13 insertions, 84 deletions
diff --git a/src/cache.c b/src/cache.c
index af33f30..2b24dd0 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -33,6 +33,7 @@ int cache_populate(struct stream * const in)
int ret = 0;
size_t i;
struct entry_l *tmp;
+ struct entry_l tmp_store;
try(in->settings->access != cached, err, EINVAL, "cannot populate cache: stream is uncached");
try(!in->cache, err, EINVAL, "stream has no cache allocated");
@@ -41,7 +42,7 @@ int cache_populate(struct stream * const in)
if (in->type == stream_randread) {
for (i = 0; i < in->n && !ret; ++i) {
errno = 0;
- tmp = in->get(in);
+ tmp = in->get(in, &tmp_store);
if (tmp) { /* non-cache reads CAN fail */
in->put(in, tmp);
} else {
@@ -84,6 +85,10 @@ err:
return ret;
}
+/* Optimized copying routine for cached array streams.
+ * The layout let's us basically just use memcpy instead of slow and wasteful
+ * get-put loop, all while completely avoiding the inefficient get-loop for seeking.
+ */
int cache_block_copy(struct stream * const restrict src, struct stream * const restrict dest)
{
int ret = 0;
@@ -100,88 +105,20 @@ err:
return ret;
}
-int cache_list_copy(struct stream * const restrict src, struct stream * const restrict dest)
-{
- int ret = 0;
- size_t ss;
-
- try(src->settings->access != cached || dest->settings->access != cached, err, EINVAL, "cannot cache-copy between uncached streams");
- try(!src->cache, err, EINVAL, "no cache to transfer");
- try(src->n < dest->settings->to, err, EINVAL, "invalid copy size");
- try(!dest->cache, err, EINVAL, "no cache to transfer to");
-
- ss = dest->settings->ss;
-
- /* skip over to start position */
- while (ss--) {
- src->get(src);
- }
-
- do {
- dest->put(dest, src->get(src));
- } while (dest->index < (dest->n - 1));
-
- src->rewind(src);
- dest->rewind(dest);
-
-err:
- return ret;
-}
-
-int cache_split(struct stream * const src, struct stream * const A, struct stream * const B)
-{
- int ret = 0;
- struct settings tmp_settings;
-
- try(src->n < 2, err, EINVAL, "cannot split single element stream.");
-
- /* setting up minimal stream basics */
- A->n = src->n / 2;
- B->n = src->n / 2 + (src->n & 1ul);
- A->index = B->index = 0;
- A->type = B->type = stream_cache; /* disallow any stream operations other than split/merge on children */
- A->fd = B->fd = -1; /* if we're splitting, these are for holding cache only */
- /* we only care about these three functions for these temporary streams */
- A->get = B->get = src->get;
- A->put = B->put = src->put;
- A->split = B->split = src->split;
- A->rewind = B->rewind = src->rewind;
- A->copy = B->copy = src->copy;
-
- tmp_settings = *src->settings;
- A->settings = B->settings = &tmp_settings;
-
- /* setting up A */
- tmp_settings.ss = 0;
- tmp_settings.to = A->n;
- try_s((ret = cache_create(A)), err);
- try_s((ret = src->copy(src, A)), err);
-
- /* setting up B */
- tmp_settings.ss = A->n;
- tmp_settings.to = src->n;
- try_s((ret = cache_create(B)), err);
- try_s((ret = src->copy(src, B)), err);
-
- A->settings = B->settings = src->settings;
-
-err:
- return ret;
-}
-
-struct entry_l *cached_get_array(struct stream * const in)
+struct entry_l *cached_get_array(struct stream * const in, struct entry_l * const store)
{
struct entry_l *ret = NULL;
if (in->index < in->n) {
- ret = (struct entry_l *)(in->cache_a + in->index);
+ store->val = in->cache_a[in->index].val;
++in->index;
+ ret = store;
}
return ret;
}
-struct entry_l *cached_get_list(struct stream * const in)
+struct entry_l *cached_get_list(struct stream * const in, struct entry_l * const store)
{
struct entry_l *ret = NULL;
@@ -189,6 +126,8 @@ struct entry_l *cached_get_list(struct stream * const in)
ret = in->cnode;
in->cnode = ret->next ? ret->next : in->cnode;
++in->index;
+ *store = *ret;
+ ret = store;
}
return ret;
@@ -226,7 +165,7 @@ int cached_put_list(struct stream * const restrict in, const struct entry_l * co
in->cnode = in->cache_l;
in->cnode->val = node->val;
in->cnode->next = NULL;
- in->index = 0;
+ in->index = 1;
} else {
in->cnode->next = in->cnode + 1; /* lol says librin, lmao */
in->cnode = in->cnode->next;
@@ -239,16 +178,6 @@ err:
return ret;
}
-int cache_rewind(struct stream * const restrict in)
-{
- int ret = 0;
-
- in->cnode = in->cnode ? in->cache_l : NULL;
- in->index = 0;
-
- return ret;
-}
-
static int cache_readfile(struct stream * const in)
{
ssize_t ret = 0;