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