LCOV - code coverage report
Current view: top level - src/include/libplacebo - cache.h (source / functions) Hit Total Coverage
Test: Code coverage Lines: 5 5 100.0 %
Date: 2025-03-29 09:04:10 Functions: 0 0 -
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 6 8 75.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * This file is part of libplacebo.
       3                 :            :  *
       4                 :            :  * libplacebo is free software; you can redistribute it and/or
       5                 :            :  * modify it under the terms of the GNU Lesser General Public
       6                 :            :  * License as published by the Free Software Foundation; either
       7                 :            :  * version 2.1 of the License, or (at your option) any later version.
       8                 :            :  *
       9                 :            :  * libplacebo is distributed in the hope that it will be useful,
      10                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12                 :            :  * GNU Lesser General Public License for more details.
      13                 :            :  *
      14                 :            :  * You should have received a copy of the GNU Lesser General Public
      15                 :            :  * License along with libplacebo.  If not, see <http://www.gnu.org/licenses/>.
      16                 :            :  */
      17                 :            : 
      18                 :            : #ifndef LIBPLACEBO_CACHE_H_
      19                 :            : #define LIBPLACEBO_CACHE_H_
      20                 :            : 
      21                 :            : #include <stddef.h>
      22                 :            : #include <stdint.h>
      23                 :            : #include <stdio.h>
      24                 :            : 
      25                 :            : #include <libplacebo/config.h>
      26                 :            : #include <libplacebo/common.h>
      27                 :            : #include <libplacebo/log.h>
      28                 :            : 
      29                 :            : PL_API_BEGIN
      30                 :            : 
      31                 :            : typedef struct pl_cache_obj {
      32                 :            :     // Cache object key. This will uniquely identify this cached object.
      33                 :            :     uint64_t key;
      34                 :            : 
      35                 :            :     // Cache data pointer and length. 0-length cached objects are invalid
      36                 :            :     // and will be silently dropped. You can explicitly remove a cached
      37                 :            :     // object by overwriting it with a length 0 object.
      38                 :            :     void *data;
      39                 :            :     size_t size;
      40                 :            : 
      41                 :            :     // Free callback, to free memory associated with `data`. (Optional)
      42                 :            :     // Will be called when the object is either explicitly deleted, culled
      43                 :            :     // due to hitting size limits, or on pl_cache_destroy().
      44                 :            :     void (*free)(void *data);
      45                 :            : } pl_cache_obj;
      46                 :            : 
      47                 :            : struct pl_cache_params {
      48                 :            :     // Optional `pl_log` that is used for logging internal events related
      49                 :            :     // to the cache, such as insertions, saving and loading.
      50                 :            :     pl_log log;
      51                 :            : 
      52                 :            :     // Size limits. If 0, no limit is imposed.
      53                 :            :     //
      54                 :            :     // Note: libplacebo will never detect or invalidate stale cache entries, so
      55                 :            :     // setting an upper size limit is strongly recommended
      56                 :            :     size_t max_object_size;
      57                 :            :     size_t max_total_size;
      58                 :            : 
      59                 :            :     // Optional external callback to call after a cached object is modified
      60                 :            :     // (including deletion and (re-)insertion). Note that this is not called on
      61                 :            :     // objects which are merely pruned from the cache due to `max_total_size`,
      62                 :            :     // so users must rely on some external mechanism to prune stale entries or
      63                 :            :     // enforce size limits.
      64                 :            :     //
      65                 :            :     // Note: `pl_cache_load` does not trigger this callback.
      66                 :            :     // Note: Ownership of `obj` does *not* pass to the caller.
      67                 :            :     // Note: This function must be thread safe.
      68                 :            :     void (*set)(void *priv, pl_cache_obj obj);
      69                 :            : 
      70                 :            :     // Optional external callback to call on a cache miss. Ownership of the
      71                 :            :     // returned object passes to the `pl_cache`. Objects returned by this
      72                 :            :     // callback *should* have a valid `free` callback, unless lifetime can be
      73                 :            :     // externally managed and guaranteed to outlive the `pl_cache`.
      74                 :            :     //
      75                 :            :     // Note: This function must be thread safe.
      76                 :            :     pl_cache_obj (*get)(void *priv, uint64_t key);
      77                 :            : 
      78                 :            :     // External context for insert/lookup.
      79                 :            :     void *priv;
      80                 :            : };
      81                 :            : 
      82                 :            : #define pl_cache_params(...) (&(struct pl_cache_params) { __VA_ARGS__ })
      83                 :            : PL_API extern const struct pl_cache_params pl_cache_default_params;
      84                 :            : 
      85                 :            : // Thread-safety: Safe
      86                 :            : //
      87                 :            : // Note: In any context in which `pl_cache` is used, users may also pass NULL
      88                 :            : // to disable caching. In other words, NULL is a valid `pl_cache`.
      89                 :            : typedef const struct pl_cache_t {
      90                 :            :     struct pl_cache_params params;
      91                 :            : } *pl_cache;
      92                 :            : 
      93                 :            : // Create a new cache. This function will never fail.
      94                 :            : PL_API pl_cache pl_cache_create(const struct pl_cache_params *params);
      95                 :            : 
      96                 :            : // Destroy a `pl_cache` object, including all underlying objects.
      97                 :            : PL_API void pl_cache_destroy(pl_cache *cache);
      98                 :            : 
      99                 :            : // Explicitly clear all objects in the cache without destroying it. This is
     100                 :            : // similar to `pl_cache_destroy`, but the cache remains valid afterwards.
     101                 :            : //
     102                 :            : // Note: Objects destroyed in this way *not* propagated to the `set` callback.
     103                 :            : PL_API void pl_cache_reset(pl_cache cache);
     104                 :            : 
     105                 :            : // Return the current internal number of objects and total size (bytes)
     106                 :            : PL_API int pl_cache_objects(pl_cache cache);
     107                 :            : PL_API size_t pl_cache_size(pl_cache cache);
     108                 :            : 
     109                 :            : // Return a lightweight, order-independent hash of all objects currently stored
     110                 :            : // in the `pl_cache`. Can be used to avoid re-saving unmodified caches.
     111                 :            : PL_API uint64_t pl_cache_signature(pl_cache cache);
     112                 :            : 
     113                 :            : // --- Cache saving and loading APIs
     114                 :            : 
     115                 :            : // Serialize the internal state of a `pl_cache` into an abstract cache
     116                 :            : // object that can be e.g. saved to disk and loaded again later. Returns the
     117                 :            : // number of objects saved.
     118                 :            : //
     119                 :            : // Note: Using `save/load` is largely redundant with using `insert/lookup`
     120                 :            : // callbacks, and the user should decide whether to use the explicit API or the
     121                 :            : // callback-based API.
     122                 :            : PL_API int pl_cache_save_ex(pl_cache cache,
     123                 :            :                             void (*write)(void *priv, size_t size, const void *ptr),
     124                 :            :                             void *priv);
     125                 :            : 
     126                 :            : // Load the result of a previous `pl_cache_save` call. Any duplicate entries in
     127                 :            : // the `pl_cache` will be overwritten. Returns the number of objects loaded, or
     128                 :            : // a negative number on serious error (e.g. corrupt header)
     129                 :            : //
     130                 :            : // Note: This does not trigger the `update` callback.
     131                 :            : PL_API int pl_cache_load_ex(pl_cache cache,
     132                 :            :                             bool (*read)(void *priv, size_t size, void *ptr),
     133                 :            :                             void *priv);
     134                 :            : 
     135                 :            : // --- Convenience wrappers around pl_cache_save/load_ex
     136                 :            : 
     137                 :            : // Writes data directly to a pointer. Returns the number of bytes that *would*
     138                 :            : // have been written, so this can be used on a size 0 buffer to get the required
     139                 :            : // total size.
     140                 :            : PL_API size_t pl_cache_save(pl_cache cache, uint8_t *data, size_t size);
     141                 :            : 
     142                 :            : // Reads data directly from a pointer. This still reads from `data`, so it does
     143                 :            : // not avoid a copy.
     144                 :            : PL_API int pl_cache_load(pl_cache cache, const uint8_t *data, size_t size);
     145                 :            : 
     146                 :            : // Writes/loads data to/from a FILE stream at the current position.
     147                 :            : #define pl_cache_save_file(c, file) pl_cache_save_ex(c, pl_write_file_cb, file)
     148                 :            : #define pl_cache_load_file(c, file) pl_cache_load_ex(c, pl_read_file_cb,  file)
     149                 :            : 
     150                 :            : static inline void pl_write_file_cb(void *priv, size_t size, const void *ptr)
     151                 :            : {
     152                 :            :     (void) fwrite(ptr, 1, size, (FILE *) priv);
     153                 :            : }
     154                 :            : 
     155                 :            : static inline bool pl_read_file_cb(void *priv, size_t size, void *ptr)
     156                 :            : {
     157                 :            :     return fread(ptr, 1, size, (FILE *) priv) == size;
     158                 :            : }
     159                 :            : 
     160                 :            : // --- Object modification API. Mostly intended for internal use.
     161                 :            : 
     162                 :            : // Insert a new cached object into a `pl_cache`. Returns whether successful.
     163                 :            : // Overwrites any existing cached object with that signature, so this can be
     164                 :            : // used to e.g. delete objects as well (set their size to 0). On success,
     165                 :            : // ownership of `obj` passes to the `pl_cache`.
     166                 :            : //
     167                 :            : // Note: If `object.free` is NULL, this will perform an internal memdup. To
     168                 :            : // bypass this (e.g. when directly adding externally managed memory), you can
     169                 :            : // set the `free` callback to an explicit noop function.
     170                 :            : //
     171                 :            : // Note: `obj->data/free` will be reset to NULL on successful insertion.
     172                 :            : PL_API bool pl_cache_try_set(pl_cache cache, pl_cache_obj *obj);
     173                 :            : 
     174                 :            : // Variant of `pl_cache_try_set` that simply frees `obj` on failure.
     175                 :            : PL_API void pl_cache_set(pl_cache cache, pl_cache_obj *obj);
     176                 :            : 
     177                 :            : // Looks up `obj->key` in the object cache. If successful, `obj->data` is
     178                 :            : // set to memory owned by the caller, which must be either explicitly
     179                 :            : // re-inserted, or explicitly freed (using obj->free).
     180                 :            : //
     181                 :            : // Note: On failure, `obj->data/size/free` are reset to NULL.
     182                 :            : PL_API bool pl_cache_get(pl_cache cache, pl_cache_obj *obj);
     183                 :            : 
     184                 :            : // Run a callback on every object currently stored in `cache`.
     185                 :            : //
     186                 :            : // Note: Running any `pl_cache_*` function on `cache` from this callback is
     187                 :            : // undefined behavior.
     188                 :            : PL_API void pl_cache_iterate(pl_cache cache,
     189                 :            :                              void (*cb)(void *priv, pl_cache_obj obj),
     190                 :            :                              void *priv);
     191                 :            : 
     192                 :            : // Utility wrapper to free a `pl_cache_obj` if necessary (and sanitize it)
     193                 :            : static inline void pl_cache_obj_free(pl_cache_obj *obj)
     194                 :            : {
     195   [ +  +  -  + ]:        961 :     if (obj->free)
     196                 :          3 :         obj->free(obj->data);
     197                 :        962 :     obj->data = NULL;
     198                 :        962 :     obj->free = NULL;
     199   [ +  +  +  - ]:        962 :     obj->size = 0;
     200                 :            : }
     201                 :            : 
     202                 :            : PL_API_END
     203                 :            : 
     204                 :            : #endif // LIBPLACEBO_CACHE_H_

Generated by: LCOV version 1.16